I have a rather large object tree which I want to export to XML. An object named Person is used at several places (as userCreated, userModified of many child entities, as client, etc)
Depending of the use of the Person-object I need to have different elements in the xml. Example:
<policy>
<userCreated>
<firstName>John</firstName>
<lastName>Doe</lastName>
</userCreated>
<client>
<clientId>1234</clientId>
<email>[email protected]</email>
<firstName>John</firstName>
<lastName>Doe</lastName>
</client>
</policy>
userCreated and client are instances of the same object (named Person)
How can this be set up in bindings.xml ?
You can use EclipseLink JAXB (MOXy)'s @XmlNamedObjectGraph
extension to support this use case. What @XmlNamedObjectGraph
allows you to do is create multiple views on your data.
Person
Below we will use @XmlNamedObjectGraph
to create a view on the Person
class that only exposes 2 fields (firstName
and lastName
).
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
@XmlNamedObjectGraph(
name = "simple",
attributeNodes = {
@XmlNamedAttributeNode("firstName"),
@XmlNamedAttributeNode("lastName")
}
)
@XmlAccessorType(XmlAccessType.FIELD)
public class Person {
private int clientId;
private String firstName;
private String lastName;
private String email;
public void setClientId(int clientId) {
this.clientId = clientId;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setEmail(String email) {
this.email = email;
}
}
Policy
We will also use @XmlNamedObjectGraph
on the Policy
class. It says that for the userCreated
field apply the named object graph called simple
that we defined on the Person
class.
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlNamedObjectGraph(
name = "policy",
attributeNodes = {
@XmlNamedAttributeNode(value = "userCreated", subgraph = "simple"),
@XmlNamedAttributeNode("client")
}
)
public class Policy {
private Person userCreated;
private Person client;
public void setUserCreated(Person userCreated) {
this.userCreated = userCreated;
}
public void setClient(Person client) {
this.client = client;
}
}
Demo
In the demo code below we will specify the named object graph that we want applied on the Marshaller
using the MarshallerProperties.OBJECT_GRAPH
property.
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Policy.class);
Person person = new Person();
person.setClientId(1234);
person.setFirstName("John");
person.setLastName("Doe");
person.setEmail("[email protected]");
Policy policy = new Policy();
policy.setClient(person);
policy.setUserCreated(person);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, "policy");
marshaller.marshal(policy, System.out);
}
}
Output
Below is the output from running the demo code:
<?xml version="1.0" encoding="UTF-8"?>
<policy>
<userCreated>
<firstName>John</firstName>
<lastName>Doe</lastName>
</userCreated>
<client>
<clientId>1234</clientId>
<firstName>John</firstName>
<lastName>Doe</lastName>
<email>[email protected]</email>
</client>
</policy>
For More Information