javaxmlspring-mvcmarshallingspring-oxm

Producing a XML view with a XStreamMarshaller Spring


I am using the spring framework 3.1 (with hibernate) and I am trying to produce an XML representation like:

<user>
<iduser>1</iduser>
<email>bla@hello.com</email>
<firstName>bob</firstName>
</user>

from this java class:

@Entity
public class User {

    @GenericGenerator(name = "table-hilo-generator", strategy = "org.hibernate.id.IncrementGenerator")
    @GeneratedValue(generator = "table-hilo-generator")
    @Id
    @Column(name = "iduser", unique = true, nullable = false)
    private int iduser;

    @NotBlank
    @NotNull
    @NotEmpty
    @Length(max = EMAIL_MAX_SIZE)
    @Column(name = "email", nullable = false)
    private String email;

    @NotBlank
    @NotNull
    @NotEmpty
    @Length(max = FIRST_NAME_MAX_SIZE)
    @Column(name = "firstName", nullable = false)
    private String firstName;
}

my servlet-conf.xml contains this view in a ContentNegotiatingViewResolver:

<!-- XML View -->
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
  <constructor-arg>
    <bean class="org.springframework.oxm.xstream.XStreamMarshaller">
        <property name="aliases">
        <map>
                <entry key="user123" value="com.....entities.User" />
        </map>
        </property>
    </bean>
   </constructor-arg>
</bean>

But I don't understand why the result is a strange xml with hundreds of elements such that:

<org.springframework.validation.BeanPropertyBindingResult>
<nestedPath/>
<nestedPathStack serialization="custom">
<unserializable-parents/>
<vector>
<default>
<capacityIncrement>0</capacityIncrement>
<elementCount>0</elementCount>
<elementData>
<null/>
<null/>
<null/>
<null/>
<null/>
<null/>
<null/>
<null/>
<null/>
<null/>
</elementData>
</default>
</vector>
</nestedPathStack>
<objectName>user</objectName>
<messageCodesResolver class="org.springframework.validation.DefaultMessageCodesResolver">
<prefix/>

1-Probably, the marshaller is playing too much with the reflection, how can I obtain the expected result that I want? ( 2-I am interested also in producing a XML file with a list of Users) How can I do that?


Solution

  • Like you have noted, what is happening is since you have not specified the explicit model key that needs to be serialized, it is serializing the first non-null valued model object, which in this happens be BindingResult(used for keeping the binding/validation errors in your model). There are a few fixes that you can make:

    a. Specify the exact modelKey for your marshalling view, this should work and set the model to the specific model key:

    <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
    <property name="marshaller">
    ...
    </property>
    <property name="modelKey" value="command"/>
    </bean>
    
    model.addAttribute("command", mymodel);
    

    b. A better fix, IMHO could be to use the http converters in Spring, this way you can return your object from a request mapped method, annotate it with @ResponseBody and Spring will take care of converting the object to a wire reprsentation(xml or json etc), you will just have to register the correct converter:

    @RequestMapping(...)
    public @ResponseBody User myMethod(Model model){
        return user;
    }
    
    <mvc:annotation-driven conversion-service="conversionService"> 
       <mvc:message-converters register-defaults="false"> <!-- you may have to explicitly register other converters though-->
           <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
               <property name="marshaller">
                   <bean class="org.springframework.oxm.xstream.XStreamMarshaller"/>
               </property>
           </bean>
       </mvc:message-converters>