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?
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>