Difference between revisions of "EclipseLink/Examples/MOXy/Dynamic/JAXBContextFromXMLSchema"

From Eclipsepedia

< EclipseLink‎ | Examples‎ | MOXy‎ | Dynamic
Jump to: navigation, search
(Handling Schema Import/Includes)
(Configuration Options)
 
(3 intermediate revisions by one user not shown)
Line 153: Line 153:
 
-Dcom.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.noCorrectnessCheck=true
 
-Dcom.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.noCorrectnessCheck=true
 
</source>}}
 
</source>}}
 +
 +
==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[[EclipseLink/Examples/MOXy/EclipseLink-OXM.XML | 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 [[EclipseLink/Examples/MOXy/Dynamic/XmlToDynamicEntity|XML to DynamicEntity]].

Latest revision as of 12:23, 24 June 2010

Contents

[edit] Overview

In this example you will learn how to bootstrap a dynamic JAXBContext from an XML Schema.

[edit] 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);
    }
 
}

[edit] 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>

[edit] 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);
Warning2.png
If, when importing another schema, you see the following exception:
Internal Exception: org.xml.sax.SAXParseException: schema_reference.4: Failed to read schema
document '<imported-schema-name>', because 1) could not find the document; 2) the document could
not be read; 3) the root element of the document is not <xsd:schema>.

then you should try disabling XJC's "schema correctness check" by setting the following Java property:

In Code:

System.setProperty("com.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.noCorrectnessCheck", "true")

Command Line:

-Dcom.sun.tools.xjc.api.impl.s2j.SchemaCompilerImpl.noCorrectnessCheck=true


[edit] 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.

[edit] 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).

[edit] Next Steps

Next we will use this metadata to load instances of DynamicEntity from XML, see XML to DynamicEntity.