Question

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?

Was it helpful?

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>

OTHER TIPS

I had the same error with XStream and it was solved by applying the following change:

Instead of adding modelKey, you can add "supportedClasses" property to Marshaller bean:


<bean class="org.springframework.oxm.xstream.XStreamMarshaller">
    <property name="autodetectAnnotations" value="true"/>
    <property name="supportedClasses">
        <list>
            <value>com.rest.example.model.User</value>
        </list>
    </property>
</bean>

Second, class User should be annotated with XStream alias, otherwise you'll get the full package name in the XML - for example: <com.rest.example.model.User> instead of <user> - the way to fix it is:

@XStreamAlias("user")
public class User {
...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top