EclipseLink/Examples/MOXy/Dynamic/JAXBContextFromXMLSchema
Contents
Overview
In this example you will learn how to bootstrap a dynamic JAXBContext from an XML Schema.
Bootstrap from an XML Schema
The DynamicJAXBContextFactory is used to create a dynamic JAXBContext. The createContextFromXSD method can be used to bootstrap a DynamicJAXBContext from an XML Schema. The first parameter represents the XML schema itself and must be in one of the following forms: java.io.InputStream, org.w3c.dom.Node, or javax.xml.transform.Source.
import java.io.FileInputStream; import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory; public class Demo { public static void main(String[] args) throws Exception { FileInputStream xsdInputStream = new FileInputStream("src/example/customer.xsd"); DynamicJAXBContext jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(xsdInputStream, null, null, null); } }
XML Schema
The following XML schema represents the metadata for this JAXBContext.
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.org" targetNamespace="http://www.example.org" elementFormDefault="qualified"> <xsd:complexType name="address"> <xsd:sequence> <xsd:element name="street" type="xsd:string" minOccurs="0"/> <xsd:element name="city" type="xsd:string" minOccurs="0"/> </xsd:sequence> </xsd:complexType> <xsd:element name="customer"> <xsd:complexType> <xsd:sequence> <xsd:element name="name" type="xsd:string" minOccurs="0"/> <xsd:element name="address" type="address" minOccurs="0"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
Handling Schema Import/Includes
If the XML Schema that you wish to use to bootstrap contains imports of other schemas, then you must configure an org.xml.sax.EntityResolver that will resolve the locations of the imported schemas, and pass the EntityResolver to DynamicJAXBContextFactory.
Taking our Customer / Address example, let's say that we wish to define these two types in their own schemas:
<!-- customer.xsd --> <?xml version="1.0" encoding="UTF-8"?> xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:add="http://www.example.org/address" xmlns="http://www.example.org/customer" targetNamespace="http://www.example.org/customer" elementFormDefault="qualified"> <xsd:import namespace="http://www.example.org/address" schemaLocation="address.xsd"/> <xsd:element name="customer"> <xsd:complexType> <xsd:sequence> <xsd:element name="name" type="xsd:string" minOccurs="0"/> <xsd:element name="address" type="add:address" minOccurs="0"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
<!-- address.xsd --> <?xml version="1.0" encoding="UTF-8"?> xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.example.org/address" targetNamespace="http://www.example.org/address" elementFormDefault="qualified"> <xsd:complexType name="address"> <xs:sequence> <xs:element name="street" type="xs:string"/> <xs:element name="city" type="xs:string"/> </xs:sequence> </xsd:complexType> </xsd:schema>
In this case, we must supply an EntityResolver implementation which will be able to resolve the location of the imported schema. First, the EntityResolver code:
class MyEntityResolver implements EntityResolver { public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { // Imported schemas are located in ext\appdata\xsd\ // Grab only the filename part from the full path String filename = new File(systemId).getName(); // Now prepend the correct path String correctedId = "ext/appdata/xsd/" + filename; InputSource is = new InputSource(ClassLoader.getSystemResourceAsStream(correctedId)); is.setSystemId(correctedId); return is; } }
Now, when you create your DynamicJAXBContext, you can pass your EntityResolver in as well:
FileInputStream xsdInputStream = new FileInputStream("src/example/customer.xsd"); DynamicJAXBContext jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(xsdInputStream, new MyEntityResolver(), null, null);
Specifying a ClassLoader
The classLoader parameter is your application's current class loader, and will be used to first lookup classes to see if they exist before new DynamicTypes are generated. In most cases null can be passed for this parameter, and Thread.currentThread().getContextClassLoader() will be used instead.
Configuration Options
This is where you specify the standard EclipseLink MOXy options. One such option is the externalize metadata, see Using EclipseLink MOXy's XML Mapping (eclipselink-oxm.xml).
Next Steps
Next we will use this metadata to load instances of DynamicEntity from XML, see XML to DynamicEntity.