Recently I have discussed support for extensible models in EclipseLink JAXB (MOXy) 2.3. The metadata for the extensions is supplied via MOXy's mapping document. In this post I will demonstrate how to leverage MOXy's support for multiple mapping documents to keep your metadata organized.
XML Metadata
I have demonstrated MOXy's mapping documents in previous posts. In EclipseLink 2.3 we've added the ability this metadata via multiple mapping documents. This could be leveraged in the following ways:
Real Properties (static-binding.xml)
This set of mappings corresponds to real properties in our domain model.
Virtual Properties (virtual-binding-v1.xml)
This set of mappings corresponds to the virtual properties that were added to our application in the first version.
Virtual Properties (virtual-binding-v2.xml)
This mapping document corresponds to the virtual properties that were added in the second version of the application.
Demo
The mapping documents are passed in when creating the JAXBContext via the properties Map. This properties accepts the mapping documents in many different formats (String, URL, Node, InputStream, XMLStreamReader, etc), and now in EclipseLink 2.3 you can pass in a list of mapping documents.
Output
Below is the output from the demo code:
XML Metadata
I have demonstrated MOXy's mapping documents in previous posts. In EclipseLink 2.3 we've added the ability this metadata via multiple mapping documents. This could be leveraged in the following ways:
- Maintain separate mapping documents for static and virtual properties
- Each version of your application could isolate its metadata changes in a separate mapping document.
Real Properties (static-binding.xml)
This set of mappings corresponds to real properties in our domain model.
<?xml version="1.0"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="blog.metadatasource.multiple"> <xml-schema namespace="http://www.example.com/customer" element-form-default="QUALIFIED"/> <java-types> <java-type name="Customer"> <xml-virtual-access-methods/> <xml-root-element/> <xml-type prop-order="firstName lastName address"/> <java-attributes> <xml-element java-attribute="firstName" name="first-name"/> <xml-element java-attribute="lastName" name="last-name"/> <xml-element java-attribute="billingAddress" name="billing-address"/> </java-attributes> </java-type> </java-types> </xml-bindings>
Virtual Properties (virtual-binding-v1.xml)
This set of mappings corresponds to the virtual properties that were added to our application in the first version.
<?xml version="1.0"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="blog.metadatasource.multiple"> <java-types> <java-type name="Customer"> <java-attributes> <xml-element java-attribute="middleName" name="middle-name" type="java.lang.String"/> <xml-element java-attribute="shippingAddress" name="shipping-address" type="blog.metadatasource.multiple.Address"/> </java-attributes> </java-type> </java-types> </xml-bindings>
Virtual Properties (virtual-binding-v2.xml)
This mapping document corresponds to the virtual properties that were added in the second version of the application.
<?xml version="1.0"?> <xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="blog.metadatasource.multiple"> <java-types> <java-type name="Customer"> <java-attributes> <xml-attribute java-attribute="id" type="java.lang.Integer"/> </java-attributes> </java-type> </java-types> </xml-bindings>
Demo
The mapping documents are passed in when creating the JAXBContext via the properties Map. This properties accepts the mapping documents in many different formats (String, URL, Node, InputStream, XMLStreamReader, etc), and now in EclipseLink 2.3 you can pass in a list of mapping documents.
package blog.metadatasource.multiple; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import org.eclipse.persistence.jaxb.JAXBContextFactory; public class Demo { public static void main(String[] args) throws Exception { Map<String, Object> properties = new HashMap<String, Object>(1); List<String> bindings = new ArrayList<String>(3); bindings.add("blog/metadatasource/multiple/static-binding.xml"); bindings.add("blog/metadatasource/multiple/virtual-binding-v1.xml"); bindings.add("blog/metadatasource/multiple/virtual-binding-v2.xml"); properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, bindings); JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, properties); Customer customer = new Customer(); customer.set("id", 100); customer.setFirstName("Jane"); customer.set("middleName", "Anne"); customer.setLastName("Doe"); Address billingAddress = new Address(); billingAddress.setStreet("123 A Street"); customer.setBillingAddress(billingAddress); Address shippingAddress = new Address(); shippingAddress.setStreet("456 B Road"); customer.set("shippingAddress", shippingAddress); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } }
Output
Below is the output from the demo code:
<?xml version="1.0" encoding="UTF-8"?> <customer xmlns="http://www.example.com/customer" id="100"> <first-name>Jane</first-name> <last-name>Doe</last-name> <billing-address> <street>123 A Street</street> </billing-address> <middle-name>Anne</middle-name> <shipping-address> <street>456 B Road</street> </shipping-address> </customer>
Java Model
The following domain model is used in this example.
Customer
package blog.metadatasource.refresh; import java.util.HashMap; import java.util.Map; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.eclipse.persistence.oxm.annotations.XmlVirtualAccessMethods; @XmlRootElement @XmlType(propOrder={"firstName", "lastName", "address"}) @XmlVirtualAccessMethods public class Customer { private String firstName; private String lastName; private Address billingAddress; private Map<String, Object> extensions = new HashMap<String, Object>(); public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Address getBillingAddress() { return billingAddress; } public void setBillingAddress(Address billingAddress) { this.billingAddress = billingAddress; } public Object get(String key) { return extensions.get(key); } public void set(String key, Object value) { extensions.put(key, value); } }
Address
package blog.metadatasource.refresh; public class Address { private String street; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } }
Further Reading
If you enjoyed this post you may also be interested in:
Other articles related to new MOXy features in EclipseLink 2.3:
Other articles related to new MOXy features in EclipseLink 2.3:
Hi Blaise,
ReplyDeleteI am developing a POC for mutitenat application that enables flexi fields.The technologies used are Eclipselink,spirng and apache cxf.To enable the multi-tenat feature i am setting the tenant context property on entity manager(injected using @PersistentContext), as of now no issues.If am enabling flexing fields then per-tenant the entity meta-data would be different.So i should go for pertenant EMF.I am using @Transactional annotations for managing transactions.How can i use spring configurations to get per tenant EMF with a transaction manager attached to it......
Hi Prasobh,
ReplyDeleteWould you mind asking this question on the EclipseLink forum or EclipseLink users mailing list (eclipselink-users@eclipse.org)? That way we can get the EclipseLink JPA folks in on the discussion too.
-Blaise