Producing a XML view with a XStreamMarshaller Spring

user1997943 picture user1997943 · Jan 22, 2013 · Viewed 7.2k times · Source

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>[email protected]</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?

Answer

Biju Kunjummen picture Biju Kunjummen · Jan 22, 2013

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>