Difference between revisions of "EclipseLink/Examples/MOXy/JAXB"

From Eclipsepedia

Jump to: navigation, search
m (Creating a JAXBContext using jaxb.properties)
(Unmarshalling the XML Document)
Line 84: Line 84:
 
With a JAXBContext created, we can now unmarshal an XML document using the statically generated classes:
 
With a JAXBContext created, we can now unmarshal an XML document using the statically generated classes:
  
<pre>
+
<source lang="java">
 
File file = new File("Customer-data.xml");
 
File file = new File("Customer-data.xml");
 
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
 
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Line 90: Line 90:
 
JAXBElement customerElement = unmarshaller.unmarshal(source, CustomerType.class);
 
JAXBElement customerElement = unmarshaller.unmarshal(source, CustomerType.class);
 
CustomerType customer = (CustomerType) customerElement.getValue();
 
CustomerType customer = (CustomerType) customerElement.getValue();
</pre>
+
</source>
  
 
==Modify the Objects==
 
==Modify the Objects==

Revision as of 17:54, 11 February 2009

Contents

Overview

The following example will demonstrate how to use EclipseLink's JAXB functionality to:

  • Generate JAXB-annotated Java classes from an XML Schema using the JAXB Compiler
  • Unmarshal an XML Document
  • Modify the XML data using the interfaces generated by the compiler
  • Marshal the modified data to XML

Setup

  1. Ensure that you have EclipseLink correctly installed and configured for your environment. Please see EclipseLink/Installing and Configuring EclipseLink for more information.
  2. Ensure that you have ANT correctly installed and configured.
  3. Unzip the Example ZIP file to a new directory.
  4. Edit the env.properties file in the root directory of the example and specify the path to your EclipseLink jlib directory:
...
# Edit eclipselink.jlib to point to your EclipseLink jlib directory
eclipselink.jlib=C:/EclipseLink-1.0/eclipselink/jlib
...

You can compile and run the Example at any time by typing ant from the Example directory.

For Eclipse IDE users, a .project file is included in the Example directory. To setup this project in Eclipse:

  1. From the "File" menu, choose "Import..."
  2. In the Import dialog, choose "General > Existing Projects into Workspace", and click "Next".
  3. Click "Browse" to select a root directory, and point to the folder containing this example. After selecting the directory, you should see the project name in the "Projects" list. Click "Finish".

This project is configured to use a classpath variable, ECLIPSELINK_JLIB, to point to the required JAR files. After the project is imported, you should define a variable called ECLIPSELINK_JLIB to point to your EclipseLink jlib directory.

Running the JAXB Compiler

The JAXB compiler can be run to generate JAXB-annotated Java classes from an XML Schema:

<ECLIPSELINK_HOME>/eclipselink/bin/jaxb-compiler.sh <source-file.xsd> [-options]
<ECLIPSELINK_HOME>\eclipselink\bin\jaxb-compiler.cmd <source-file.xsd> [-options]
 
Options include:
   -d <dir>                     Specifies the output directory for generated files
   -p <pkg>                     Specifies the target package
   -classpath <arg>             Specifies where to find user class files
   -verbose                     Enable verbose output
   -quiet                       Suppress compiler output
   -version                     Display version information
 
For a complete list of compiler options:
   jaxb-compiler.sh -help
 
Example:
   jaxb-compiler.sh -d jaxb-compiler-output config/Customer.xsd

In this example, the JAXB Compiler is run from the "run.jaxb.compiler" task in the ANT build file.

Creating a JAXBContext using jaxb.properties

The standard way to specify which JAXB implementation should be used is through a file called jaxb.properties, which contains a single property, javax.xml.bind.context.factory. This file must be available on the classpath in the corresponding package (in this example, "org.example.customer_example"). To specify that the EclipseLink JAXB implementation should be used, your jaxb.properties file should have the following content:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

In our example, we create the JAXBContext as follows:

JAXBContext jaxbContext = JAXBContext.newInstance("org.example.customer_example");

An alternate way to create a new JAXBContext is to supply an array of Class objects. Again, the jaxb.properties file must be available on the classpath in the corresponding package:

Class[] classes = new Class[4]; 
classes[0] = org.example.customer_example.AddressType.class; 
classes[1] = org.example.customer_example.ContactInfo.class; 
classes[2] = org.example.customer_example.CustomerType.class; 
classes[3] = org.example.customer_example.PhoneNumber.class; 
JAXBContext jaxbContext = JAXBContext.newInstance(classes);

Unmarshalling the XML Document

With a JAXBContext created, we can now unmarshal an XML document using the statically generated classes:

File file = new File("Customer-data.xml");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StreamSource source = new StreamSource(file);
JAXBElement customerElement = unmarshaller.unmarshal(source, CustomerType.class);
CustomerType customer = (CustomerType) customerElement.getValue();

Modify the Objects

Below are examples of manipulating the XML data using the JAXB-generated static classes. Note that there are JavaBean-type accessors on the static interfaces.

Modifying the ShippingAddress ZipCode:

customer.getContactInfo().getShippingAddress().setZipCode("27601");

Adding a new PhoneNumber:

PhoneNumber homePhoneNumber  = new ObjectFactory().createPhoneNumber();
homePhoneNumber.setType("home");
homePhoneNumber.setValue("(613) 555-3333");
customer.getContactInfo().getPhoneNumber().add(homePhoneNumber);

Note the use of the ObjectFactory class to create a new PhoneNumber object. In addition to generating the model classes used in this example, the JAXB compiler also generates an ObjectFactory class that can be used to create any of the generated types.

Removing all "cell" PhoneNumbers:

ArrayList phoneNumbersToRemove = new ArrayList();
List phoneNumbers = customer.getContactInfo().getPhoneNumber();
Iterator it = phoneNumbers.iterator();
while (it.hasNext()) {
    PhoneNumber phoneNumber = (PhoneNumber) it.next();
    if (phoneNumber.getType().equals("cell")) {
        phoneNumbersToRemove.add(phoneNumber);
    }
}
phoneNumbers.removeAll(phoneNumbersToRemove);

Marshalling the Objects to XML

The following code segment demonstrates how to marshal Customer objects back to XML. In this example the stream we are saving to is System.out, so the XML text will be printed to the console.

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(customerElement, System.out);

Using JAXBContext to Generate an XML Schema

First you must create a class that extends javax.xml.bind.SchemaOutputResolver.

private class MySchemaOutputResolver extends SchemaOutputResolver {

    public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
        File file = new File(suggestedFileName);
        StreamResult result = new StreamResult(file);
        result.setSystemId(file.toURI().toURL().toString());
        return result;
    }

}

Then use an instance of this class with JAXBContext to capture the generated XML Schema.

Class[] classes = new Class[4]; 
classes[0] = org.example.customer_example.AddressType.class; 
classes[1] = org.example.customer_example.ContactInfo.class; 
classes[2] = org.example.customer_example.CustomerType.class; 
classes[3] = org.example.customer_example.PhoneNumber.class; 
JAXBContext jaxbContext = JAXBContext.newInstance(classes);

SchemaOutputResolver sor = new MySchemaOutputResolver();
jaxbContext.generateSchema(sor);

Download

Download the "Examples Zip" from the EclipseLink Downloads page. Code for this example will be found in the org.eclipse.persistence.example.jaxb.zip file.