Difference between revisions of "EclipseLink/Examples/MOXy/Spring/JAXBAnnotations"

From Eclipsepedia

< EclipseLink‎ | Examples‎ | MOXy‎ | Spring
Jump to: navigation, search
(EclipseLink)
Line 3: Line 3:
  
 
In order to use EclipseLink JAXB with the Spring Framework, you simply need a <code>jaxb.properties</code> file and an <code>eclipselink.jar</code> on the classpath.  No other special configuration is required.  This document will demonstrate how to configure Spring to use EclipseLink JAXB.
 
In order to use EclipseLink JAXB with the Spring Framework, you simply need a <code>jaxb.properties</code> file and an <code>eclipselink.jar</code> on the classpath.  No other special configuration is required.  This document will demonstrate how to configure Spring to use EclipseLink JAXB.
 
== Requirements ==
 
The following are required to use EclipseLink JAXB with Spring.
 
=== EclipseLink ===
 
The latest version of EclipseLink can be found on the [http://www.eclipse.org/eclipselink/downloads EclipseLink download] page. <code>eclipselink.jar</code> must be on the classpath.
 
 
=== Spring Framework ===
 
The latest version of the Spring Framework can be found on the [http://www.springsource.org/download Spring download] page.  The JAR files in the <code>dist</code> folder of your Spring install as well as <code>commons-logging.jar</code> found in <code>/projects/spring-build/lib/ivy</code> must be on the classpath.
 
 
=== Model Classes ===
 
The following model classes make use of standard JAXB annotations as well as MOXy extensions:
 
* [http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions#Using_MOXy_Extensions Customer]
 
* [http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics#Domain_Model Address]
 
* [http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/JAXBCustomizations#Customizing_a_Property PhoneNumber]
 
  
 
== Configuration: applicationContext.xml ==
 
== Configuration: applicationContext.xml ==
Line 57: Line 43:
 
</source>
 
</source>
  
== Source/Config Files ==
+
== Example ==
 +
Here is an example of EclipseLink JAXB used with the Spring Framework.
 +
 
 +
=== Requirements ===
 +
The following are required to use EclipseLink JAXB with Spring.
 +
 
 +
==== EclipseLink ====
 +
The latest version of EclipseLink can be found on the [http://www.eclipse.org/eclipselink/downloads EclipseLink download] page. <code>eclipselink.jar</code> must be on the classpath.
 +
 
 +
==== Spring Framework ====
 +
The latest version of the Spring Framework can be found on the [http://www.springsource.org/download Spring download] page.  The JAR files in the <code>dist</code> folder of your Spring install as well as <code>commons-logging.jar</code> found in <code>/projects/spring-build/lib/ivy</code> must be on the classpath.
 +
 
 +
==== Model Classes ====
 +
The following model classes make use of standard JAXB annotations as well as MOXy extensions:
 +
* [http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions#Using_MOXy_Extensions Customer]
 +
* [http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics#Domain_Model Address]
 +
* [http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/JAXBCustomizations#Customizing_a_Property PhoneNumber]
 +
 
 +
=== Source/Config Files ===
 
This section contains the various source and configuration files for the example.
 
This section contains the various source and configuration files for the example.
  
=== example.gettingstarted.XMLHelper.java ===
+
==== example.gettingstarted.XMLHelper.java ====
 
This is the class responsible for marshal/unmarshal operations:
 
This is the class responsible for marshal/unmarshal operations:
 
<source lang="java">
 
<source lang="java">
Line 99: Line 103:
 
</source>
 
</source>
  
=== build.xml ===
 
This is the ANT build file used to run the example.
 
  
<source lang="xml">
+
==== example.gettingstarted.XMLHelperTest.java ====
<?xml version="1.0" standalone="yes"?>
+
This class demonstrates how the XMLHelper bean can be acquired, and used to perform marshal/unmarshal operations on a Customer.
<project basedir="." default="run" name="JAXB Annotation Example">
+
<source lang="java">
<property name="eclipselink.home" value="C:/spring/workspace/eclipselink"/>
+
package example.gettingstarted;
<property name="spring.home" value="C:/spring/spring-framework-3.0.2.RELEASE"/>
+
<property name="srcdir" value="src" />
+
<path id="classpath">
+
<filelist dir="${spring.home}">
+
<file name="dist/org.springframework.aop-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.asm-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.aspects-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.beans-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.context-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.context.support-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.core-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.expression-3.0.2.RELEASE.jar"/>
+
<file name="dist/org.springframework.oxm-3.0.2.RELEASE.jar"/>
+
                        <file name="dist/org.springframework.test-3.0.2.RELEASE.jar"/>
+
<file name="projects/spring-build/lib/ivy/commons-logging.jar"/>
+
</filelist>
+
<filelist dir="${eclipselink.home}/jlib">
+
<file name="eclipselink.jar"/>
+
</filelist>
+
</path>
+
  
<target name="clean">
+
import java.io.FileInputStream;
<delete dir="classes" includes="**/*" />
+
import java.io.FileOutputStream;
</target>
+
+
<target name="compile">
+
<mkdir dir="classes" />
+
<javac destdir="classes" debug="on">
+
<src path="${srcdir}"/>
+
<classpath refid="classpath" />
+
</javac>
+
<copy todir="classes" description="copy resources">
+
    <fileset dir="${srcdir}">
+
  <exclude name="**/*.java" />
+
</fileset>
+
</copy>
+
</target>
+
  
<target name="run" depends="clean, compile">
+
import javax.xml.transform.stream.StreamResult;
<echo>JAXB Annotation Example</echo>
+
import javax.xml.transform.stream.StreamSource;
<java classname="example.gettingstarted.XMLHelperTest" fork="true">
+
 
<classpath refid="classpath" />
+
import org.springframework.context.ApplicationContext;
<classpath path="classes" />
+
import org.springframework.context.support.ClassPathXmlApplicationContext;
</java>
+
 
</target>
+
public class XMLHelperTest {
</project>
+
    private static String APP_CTX = "applicationContext.xml";
 +
    private static String CUSTOMER_XML = "classes/customer.xml";
 +
    private XMLHelper xmlHelper;
 +
   
 +
    public static void main(String[] args) throws Exception {
 +
        XMLHelperTest test = new XMLHelperTest();
 +
        test.setup();
 +
        test.testLoadAndSaveCustomer();
 +
    }
 +
 
 +
    public void setup() {
 +
        // initialize IoC Container
 +
        ApplicationContext appContext = new ClassPathXmlApplicationContext(APP_CTX);
 +
        // retrieve the XMLHelper instance from the Container
 +
        xmlHelper = (XMLHelper) appContext.getBean("xmlHelper");
 +
    }
 +
   
 +
    public void testLoadAndSaveCustomer() throws Exception {
 +
        System.out.println("Beginning load and save Customer test.");
 +
        // load Customer
 +
        Customer customer = (Customer) xmlHelper.load(new StreamSource(new FileInputStream(CUSTOMER_XML)));
 +
        if (customer == null) {
 +
            System.out.println("Test failed!");
 +
            return;
 +
        }
 +
        // update Customer
 +
        int newPhoneCount = customer.getPhoneNumbers().size() + 1;
 +
        PhoneNumber pn = new PhoneNumber();
 +
        pn.setType("Additional");
 +
        pn.setValue("613-123-1234");
 +
        customer.getPhoneNumbers().add(pn);
 +
        // save Customer
 +
        xmlHelper.save(customer, new StreamResult(new FileOutputStream(CUSTOMER_XML)));
 +
        // verify Customer was saved correctly, i.e. now has an additional phone number
 +
        customer = (Customer) xmlHelper.load(new StreamSource(new FileInputStream(CUSTOMER_XML)));
 +
        if (customer == null || customer.getPhoneNumbers().size() != newPhoneCount) {
 +
            System.out.println("Test failed!");
 +
            return;
 +
        }
 +
        System.out.println("Test passed.");
 +
    }
 +
}
 +
</source>
 +
 
 +
==== customer.xml ====
 +
This is a sample instance document.
 +
<source lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<customer>
 +
  <personal-info>
 +
      <name>Jane Doe</name>
 +
  </personal-info>
 +
  <contact-info>
 +
      <address>
 +
        <city>My Town</city>
 +
        <street>123 Any Street</street>
 +
      </address>
 +
      <phone-number type="work">613-555-1111</phone-number>
 +
      <phone-number type="cell">613-555-2222</phone-number>
 +
  </contact-info>
 +
</customer>
 
</source>
 
</source>

Revision as of 09:51, 28 July 2010

In order to use EclipseLink JAXB with the Spring Framework, you simply need a jaxb.properties file and an eclipselink.jar on the classpath. No other special configuration is required. This document will demonstrate how to configure Spring to use EclipseLink JAXB.

Configuration: applicationContext.xml

The following XML file will be used to configure our beans:

<?xml version="1.0" encoding="UTF-8"?>
<beans 
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="contextPath" value="example.gettingstarted"/>
    </bean>
    <bean id="xmlHelper" class="example.gettingstarted.XMLHelper">
        <property name="marshaller" ref="jaxbMarshaller"/>
    </bean>
</beans>

Two beans are being defined here:

  • xmlHelper
    • This is the class that will do all of the work, i.e. marshal and unmarshal
    • We use the "marshaller" property to indicate that we want Spring to inject an instance of org.springframework.oxm.jaxb.Jaxb2Marshaller
  • jaxbMarshaller
    • This is an instance of the org.springframework.oxm.jaxb.Jaxb2Marshaller class that will be injected into our xmlHelper
    • We use the "contextPath" property to indicate the location of the model classes, jaxb.properties, and an ObjectFactory class or jaxb.index file

Following is the jaxb.properties file that tells Spring to use EclipseLink JAXB:

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

Bootstrapping the Application

The standard Spring bean lookup method can be used to gain access to the xmlHelper bean:

// initialize IoC Container
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// retrieve the XMLHelper instance from the Container
XMLHelper xmlHelper = (XMLHelper) appContext.getBean("xmlHelper");

Example

Here is an example of EclipseLink JAXB used with the Spring Framework.

Requirements

The following are required to use EclipseLink JAXB with Spring.

EclipseLink

The latest version of EclipseLink can be found on the EclipseLink download page. eclipselink.jar must be on the classpath.

Spring Framework

The latest version of the Spring Framework can be found on the Spring download page. The JAR files in the dist folder of your Spring install as well as commons-logging.jar found in /projects/spring-build/lib/ivy must be on the classpath.

Model Classes

The following model classes make use of standard JAXB annotations as well as MOXy extensions:

Source/Config Files

This section contains the various source and configuration files for the example.

example.gettingstarted.XMLHelper.java

This is the class responsible for marshal/unmarshal operations:

package example.gettingstarted;
 
import java.io.IOException;
 
import javax.xml.transform.Result;
import javax.xml.transform.Source;
 
import org.springframework.oxm.XmlMappingException;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
 
public class XMLHelper {
    private Jaxb2Marshaller marshaller;
 
    /**
     * Unmarshal a given source
     */
    public Object load(Source source) throws XmlMappingException, IOException {
        return marshaller.unmarshal(source);
    }
 
    /**
     * Marshal a given Object to a Result
     */
    public void save(Object obj, Result result) throws XmlMappingException, IOException {
        marshaller.marshal(obj, result);
    }
 
    /**
     * This method is used by Spring to inject an instance of Jaxb2Marshaller
     */
    public void setMarshaller(Jaxb2Marshaller marshaller) {
        this.marshaller = marshaller;
    }
}


example.gettingstarted.XMLHelperTest.java

This class demonstrates how the XMLHelper bean can be acquired, and used to perform marshal/unmarshal operations on a Customer.

package example.gettingstarted;
 
import java.io.FileInputStream;
import java.io.FileOutputStream;
 
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class XMLHelperTest {
    private static String APP_CTX = "applicationContext.xml";
    private static String CUSTOMER_XML = "classes/customer.xml";
    private XMLHelper xmlHelper;
 
    public static void main(String[] args) throws Exception {
        XMLHelperTest test = new XMLHelperTest();
        test.setup();
        test.testLoadAndSaveCustomer();
    }
 
    public void setup() {
        // initialize IoC Container
        ApplicationContext appContext = new ClassPathXmlApplicationContext(APP_CTX);
        // retrieve the XMLHelper instance from the Container
        xmlHelper = (XMLHelper) appContext.getBean("xmlHelper");
    }
 
    public void testLoadAndSaveCustomer() throws Exception {
        System.out.println("Beginning load and save Customer test.");
        // load Customer
        Customer customer = (Customer) xmlHelper.load(new StreamSource(new FileInputStream(CUSTOMER_XML)));
        if (customer == null) {
            System.out.println("Test failed!");
            return;
        }
        // update Customer
        int newPhoneCount = customer.getPhoneNumbers().size() + 1;
        PhoneNumber pn = new PhoneNumber();
        pn.setType("Additional");
        pn.setValue("613-123-1234");
        customer.getPhoneNumbers().add(pn);
        // save Customer
        xmlHelper.save(customer, new StreamResult(new FileOutputStream(CUSTOMER_XML)));
        // verify Customer was saved correctly, i.e. now has an additional phone number
        customer = (Customer) xmlHelper.load(new StreamSource(new FileInputStream(CUSTOMER_XML)));
        if (customer == null || customer.getPhoneNumbers().size() != newPhoneCount) {
            System.out.println("Test failed!");
            return;
        }
        System.out.println("Test passed.");
    }
}

customer.xml

This is a sample instance document.

<?xml version="1.0" encoding="UTF-8"?>
<customer>
   <personal-info>
      <name>Jane Doe</name>
   </personal-info>
   <contact-info>
      <address>
         <city>My Town</city>
         <street>123 Any Street</street>
      </address>
      <phone-number type="work">613-555-1111</phone-number>
      <phone-number type="cell">613-555-2222</phone-number>
   </contact-info>
</customer>