Skip to main content

Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Development/2.1/DynamicMOXy/296967/Documentation

Dynamic MOXy - JAXB with Dynamically Generated Java Classes

EclipseLink Dynamic MOXy introduces a new concept in JAXB development - the freedom to bootstrap a JAXBContext from a variety of metadata sources and use familiar JAXB APIs to marshal and unmarshal data, all without having actual compiled Java class files on the classpath. This gives the user the flexibility to alter their metadata and not have to worry about updating and recompiling the previously-generated Java source code.

Dynamic Entities

Instead of actual Java classes (e.g. Customer.class, Address.class, etc), the "domain" objects used in Dynamic MOXy will be subclasses of DynamicEntity. DynamicEntities offer a simple get(propertyName) / set(propertyName, propertyValue) API to manipulate their data:

DynamicEntity dCustomer = (DynamicEntity) dContext.createUnmarshaller().unmarshal(instanceDoc);
 
String firstName = dCustomer.get("fname");
List orders = dCustomer.get("orders");
 
...
 
dCustomer.set("lname", "Duggar");
 
DynamicEntity dAddress = dContext.newDynamicEntity("mynamespace.Address");
dAddress.set("street", "1001 Duggar Ranch Way");
 
dynamicEmployee.set("address", dAddress);

DynamicTypes are analogous to Java Classes, whereas DynamicEntities are instances of a DynamicType.

Getting Started

As with conventional JAXB, the first step is to create a JAXBContext. This is achieved by use of the DynamicJAXBContextFactory class. DynamicJAXBContexts cannot be instantiated directly, they must be created through the factory API.

Currently, a DynamicJAXBContext can be created with metadata from an XML Schema file (XSD), or from an EclipseLink Project specified in the EclipseLink sessions.xml file.

Bootstrapping from XML Schema (XSD)

There are three ways that you can pass your XML Schema metadata to DynamicJAXBContextFactory - using an InputStream, Node, or Source:

/**
 * Create a DynamicJAXBContext, using XML Schema as the metadata source.
 *
 * @param schemaStream
 *      java.io.InputStream from which to read the XML Schema.
 * @param resolver
 *      An org.xml.sax.EntityResolver, used to resolve schema imports.  Can be null.
 * @param classLoader
 *      The application's current class loader, which will be used to first lookup
 *      classes to see if they exist before new DynamicTypes are generated.  Can be
 *      null, in which case Thread.currentThread().getContextClassLoader() will be used.
 * @param properties
 *      Map of properties to use when creating a new DynamicJAXBContext.  Can be null.
 *
 * @return
 *      A new instance of DynamicJAXBContext.
 *
 * @throws JAXBException
 *      if an error was encountered while creating the DynamicJAXBContext.
 */
public static DynamicJAXBContext createContextFromXSD(java.io.InputStream schemaStream, EntityResolver resolver,
   ClassLoader classLoader, Map<String, ?> properties) throws JAXBException
 
public static DynamicJAXBContext createContextFromXSD(org.w3c.dom.Node schemaDOM, EntityResolver resolver,
   ClassLoader classLoader, Map<String, ?> properties) throws JAXBException
 
public static DynamicJAXBContext createContextFromXSD(javax.xml.transform.Source schemaSource, EntityResolver resolver,
   ClassLoader classLoader, Map<String, ?> properties) throws JAXBException

Using the following example schema, we will show an example of how to create and marshall a new object using Dynamic MOXy:

Example Schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="myNamespace" xmlns:myns="myNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    attributeFormDefault="qualified" elementFormDefault="qualified">
 
    <xs:element name="customer" type="myns:customer"/>
 
    <xs:complexType name="customer">
        <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="address" type="myns:address"/>
        </xs:sequence>
    </xs:complexType>
 
    <xs:complexType name="address">
        <xs:sequence>
            <xs:element name="street" type="xs:string"/>
            <xs:element name="city" type="xs:string"/>
            <xs:element name="province" type="xs:string"/>
            <xs:element name="postal-code" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
 
</xs:schema>

Example Code:

InputStream inputStream = ClassLoader.getSystemResourceAsStream("com/foo/sales/xsd/customer.xsd");
DynamicJAXBContext dContext = DynamicJAXBContextFactory.createContextFromXSD(inputStream, null, null, null);
 
DynamicEntity newCustomer = dContext.newDynamicEntity("mynamespace.Customer");
newCustomer.set("name", "George Jones");
 
DynamicEntity newAddress = dContext.newDynamicEntity("mynamespace.Address");
newAddress.set("street", "227 Main St.");
newAddress.set("city", "Toronto");
newAddress.set("province", "Ontario");
newAddress.set("postalCode", "M5V1E6");
 
newCustomer.set("address", address);
 
dContext.createMarshaller().marshal(newCustomer, System.out);

Bootstrapping from an EclipseLink Project

/**
 * Create a <tt>DynamicJAXBContext</tt>, using an EclipseLink <tt>sessions.xml</tt> as the metadata source.
 * The <tt>sessionNames</tt> parameter is a colon-delimited list of session names within the
 * <tt>sessions.xml</tt> file.  <tt>Descriptors</tt> in this session's <tt>Project</tt> must <i>not</i>
 * have <tt>javaClass</tt> set, but <i>must</i> have <tt>javaClassName</tt> set.
 *
 * @param sessionNames
 *      A colon-delimited <tt>String</tt> specifying the session names from the <tt>sessions.xml</tt> file.
 * @param classLoader
 *      The application's current class loader, which will be used to first lookup
 *      classes to see if they exist before new <tt>DynamicTypes</tt> are generated.  Can be
 *      <tt>null</tt>, in which case <tt>Thread.currentThread().getContextClassLoader()</tt> will be used.
 * @param properties
 *      Map of properties to use when creating a new <tt>DynamicJAXBContext</tt>.  Can be null.
 *
 * @return
 *      A new instance of <tt>DynamicJAXBContext</tt>.
 *
 * @throws JAXBException
 *      if an error was encountered while creating the <tt>DynamicJAXBContext</tt>.
 */
public static DynamicJAXBContext createContext(String sessionNames, ClassLoader classLoader, 
   Map<String, ?> properties) throws JAXBException

Back to the top