You can try this out today by downloading one EclipseLink 2.5.0 nightly downloads starting on March 1, 2013 from:
Java Model
Below is the Java model that we will use for this example. To preserve backwards compatibility by default the @XmInverseReference annotation still acts like @XmlTransient during the marshal operation. To make it writable simply pair it with the @XmlElement annotation.
Customer
Below the @XmlInverseReference annotation is used to specify that Customer's back pointer to Address is mapped by the customer property on Address.
Below the @XmlInverseReference annotation is used to specify that Customer's back pointer to Address is mapped by the customer property on Address.
package blog.inversereference; import javax.xml.bind.annotation.*; import org.eclipse.persistence.oxm.annotations.XmlInverseReference; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { String name; @XmlElement @XmlInverseReference(mappedBy="customer") Address address; }
Address
Here the @XmlInverseReference annotation is used to specify that when the address property is populated on the Customer object, the customer property on the Address object will be set as a back pointer.
package blog.inversereference; import javax.xml.bind.annotation.*; import org.eclipse.persistence.oxm.annotations.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Address { String street; String city; @XmlElement @XmlInverseReference(mappedBy="address") Customer customer; }
jaxb.properties
When using MOXy as your JAXB (JSR-222) provider where it is not the default you need to include a file called jaxb.properties in the same package as the domain model with the following entry (see: Specifying EclipseLink MOXy as your JAXB Provider).
XML Demo
When using MOXy as your JAXB (JSR-222) provider where it is not the default you need to include a file called jaxb.properties in the same package as the domain model with the following entry (see: Specifying EclipseLink MOXy as your JAXB Provider).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
XML Demo
Input (customer.xml)
In the XML document below the Address information is nested within the Customer information.
<?xml version="1.0" encoding="UTF-8"?> <customer> <name>Jane Doe</name> <address> <street>1 A Street</street> <city>Any Town</city> </address> </customer>
Demo
package blog.inversereference; import javax.xml.bind.*; import javax.xml.transform.stream.StreamSource; public class DemoXML { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Customer.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); StreamSource xml = new StreamSource("src/blog/inversereference/customer.xml"); Customer customer = (Customer) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer.address, System.out); } }
Output
In the resulting XML output now the Customer information is nested within the Address information.
<?xml version="1.0" encoding="UTF-8"?> <address> <street>1 A Street</street> <city>Any Town</city> <customer> <name>Jane Doe</name> </customer> </address>
JSON Demo
MOXy also offers first class support for JSON-binding (see: JSON Binding with EclipseLink MOXy - Twitter Example). This means that all MOXy's XML-binding extensions also apply to its JSON-binding.
Input (address.json)
In the JSON document below the Customer information is nested within the Address information.
{ "street" : "1 A Street", "city" : "Any Town", "customer" : { "name" : "Jane Doe" } }
Demo
In the demo code below we will unmarshal a JSON document where Address is the root object. Then we will grab the nested Customer object and marshal it as the root object. This is the opposite of what we did in the XML demo.
package blog.inversereference; import java.util.*; import javax.xml.bind.*; import javax.xml.transform.stream.StreamSource; import org.eclipse.persistence.jaxb.JAXBContextProperties; public class DemoJSON { public static void main(String[] args) throws Exception { Map<String, Object> properties = new HashMap<String, Object>(2); properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jc = JAXBContext.newInstance( new Class[] {Customer.class}, properties); Unmarshaller unmarshaller = jc.createUnmarshaller(); StreamSource json = new StreamSource("src/blog/inversereference/address.json"); Address address = unmarshaller.unmarshal(json, Address.class).getValue(); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(address.customer, System.out); } }
Output
In the resulting JSON output now the Address information is nested within the Customer information.
{ "name" : "Jane Doe", "address" : { "street" : "1 A Street", "city" : "Any Town" } }
External Metadata
MOXy also offers an external binding document which allows you to provide metadata for third party objects or apply alternate mappings for your model (see: Mapping Object to Multiple XM Schemas - Weather Example). Below is the mapping document for this example.
<?xml version="1.0"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="blog.inversereference" xml-accessor-type="FIELD"> <java-types> <java-type name="Customer"> <xml-root-element/> <java-attributes> <xml-element java-attribute="address"> <xml-inverse-reference mapped-by="customer"/> </xml-element> </java-attributes> </java-type> <java-type name="Address"> <xml-root-element/> <java-attributes> <xml-element java-attribute="customer"> <xml-inverse-reference mapped-by="address"/> </xml-element> </java-attributes> </java-type> </java-types> </xml-bindings>
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.