Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Examples/MOXy/Dynamic/JAXBContextFromXMLSchema

< EclipseLink‎ | Examples‎ | MOXy‎ | Dynamic
Revision as of 11:46, 24 June 2010 by Blaise.doughan.oracle.com (Talk | contribs) (Handling Schema Import/Includes)

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);
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

Copyright © Eclipse Foundation, Inc. All Rights Reserved.