[Lab] JAXB 2 Marshaling and Unmarshaling with XSD to Java Binding

JAXB 2.x support bidirectional binding between xml schema (XSD) and java classes - binding from XML schema (XSD) to create java classes and binding of Java classes to create XML Schema components.

Here we will see binding from XML schema (XSD) to create JAXB classes and and then do marshalling and unmarshalling. 

To bind from XML schema (XSD) to create JAXB classes, first we need to create an XSD and provide this as the input to the JAXB compiler, wihch creates the required JAXB classes.

In this example, we will first create a sample xml and then write (or generate) an xsd for it, then using the xsd, we will create the java stub code corresponding to the xsd and finally do marshaling and unmarshaling using the generated code.

 

Generating JAXB classes

Step 1: Setting-Up the environment

You need to have a java jee eclipse (indigo or above) with Java SE 6 or above. JAXB 2.x is now part of Java SE 6 and above; and hence we won’t need to import any jaxb related jars for this example.

 

Step 2: Create an XSD

Create or copy paste an xsd in the project folder.

I will use the below xml to create an xsd:

<hello>

         <greeting>Hello</greeting>

         <name title="Mr">Heartin</name>

</hello>

I have written an xsd as below based on the above xml:

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"

            xmlns:jxb="http://java.sun.com/xml/ns/jaxb"

            jxb:version="2.0">

         <xsd:element name="hello" type="helloType"/>

         <xsd:complexType name="helloType">

                 <xsd:sequence>

                          <xsd:element name="greeting" type="xsd:string"/>

                          <xsd:element name="name" type="nameType"/>

                 </xsd:sequence>

         </xsd:complexType>

         <xsd:complexType name="nameType">

                 <xsd:simpleContent>

                          <xsd:extension base="xsd:string">

                                  <xsd:attribute name="title" type="titleType">

                                  </xsd:attribute>

                          </xsd:extension>

                 </xsd:simpleContent>

         </xsd:complexType>

         <xsd:simpleType name="titleType">

                 <xsd:restriction base="xsd:string">

                          <xsd:enumeration value="Mr"/>

                          <xsd:enumeration value="Mrs"/>

                 </xsd:restriction>

         </xsd:simpleType>

</xsd:schema>   

Save it with .xsd extension.

 

Step 3: Generate the java stub code corresponding to the xsd

Traditionally we had to use the xjc schema compiler from command prompt or an ant build for generating java code from xsd. However the current Jee eclipse provide inbuilt support for generating the JAXB java classes and interfaces from input xsd. Just right click the xsd and generate jaxb classes.

In the dialog, give a package structure as below and click finish. We will leave other options as is.

 

JAXB defines a default binding rule, which we can override binding through custom binding declarations. These custom binding rules can be specified inline within the schema or in a separate XML binding declaration document. The external binding file can be included as well in the above dialog, but for this example we won’t specify any custom binding except for the generated package and use the default JAXB binding rules.

 

The java files will be generated in the specified package.

 

Marshaling an XML Document

Now, create a java class JaxbExample.java in the package com.javajee.jaxb2. We will do our marshaling and unmarshaling logic here using the generated classes.

Marshaling an XML document means to create an XML document from Java classes.  To marshal an xml document, you need to follow these steps:

1. Create a JAXBContext object with its static method newInstance(String contextPath).

2. Use the JAXBContext object to create a Marshaller object.

3. Create an instance of the generated ObjectFactory object.

4. Using the ObjectFactory object, create an object tree starting with the root object.

5. Populate these tree objects with the relevant data using the appropriate setter methods.

6. Create a JAXBElement<RootType> object of the RootType using the appropriate factory method. JAXBElement<RootType> represents the root element in XML document.

7. Finally, call the marshal method passing the JAXBElement for root and an output stream to print the result.

 

Steps in detail:

1. Create a JAXBContext object with its static method newInstance(String contextPath).

JAXBContext jaxbContext = JAXBContext.newInstance("com.javajee.jaxb2.generated");

  • In the case of xml schema to java binding, context path is the package of the generated classes.

2. Use the JAXBContext object to create a Marshaller object.

Marshaller marshaller=jaxbContext.createMarshaller();

  • The Marshaller class converts a Java object tree to an XML document.
  • The Marshaller class has overloaded marshal() methods to marshal into SAX 2 events, a DOM structure, an OutputStream, a javax.xml.transform.Result, or a java.io.Writer object.

3. Create an instance of the generated ObjectFactory object.

ObjectFactory factory = new ObjectFactory();

4. Using the ObjectFactory object, create an object tree starting with the root object.

HelloType hello = factory.createHelloType();

NameType name=factory.createNameType();

5. Populate these tree objects with the relevant data using the appropriate setter methods.

hello.setGreeting("Hello");

TitleType title=TitleType.MR;

name.setValue("Heartin");

name.setTitle(title);

hello.setName(name);

  • Note that I had created an enumeration for the Title and restricted its values. I could have also made it a simple xsd:string, in which case there would not have been a TitleType class and would just have a string variable setter for NameType.

6. Create a JAXBElement<RootType> using the factory method.

JAXBElement<HelloType> helloElement = factory.createHello(hello);

JAXBElement represents the root element in XML document.

7. Finally, call the marshal method passing the JAXBElement for root and an output stream to print the result.

marshaller.marshal(helloElement,System.out);

 

Unmarshaling an XML Document

Unmarshaling means creating a Java object tree from an XML document. In case of converting from an xml document to java objects, the xml document is the starting point. So first, we need to create an xml document. We will use the same xml. Save it into a file hello.xml in the eclipse project folder. To unmarshal, we need to follow these steps:

1.   Create a JAXBContext object with its static method newInstance(String contextPath)

2.   Use the JAXBContext object to create an UnMarshaller object.

3.   Create a JAXBElement object of type root using the unmarshal method of Unmarshaller.

4.   Create root object type from the JAXBElement object using its getValue() method.

5.   Use appropriate getters of root object to get its attributes and children.

 

Steps in detail:

1.   Create a JAXBContext object with its static method newInstance(String contextPath)

JAXBContext jaxbContext = JAXBContext.newInstance("com.javajee.jaxb2.generated");

2.   Use the JAXBContext object to create an UnMarshaller object.

Unmarshaller unMarshaller=jaxbContext.createUnmarshaller();

  • Unmarshaller object unmarshal an XML doc to a Java object.

3.   Create a JAXBElement object of type root using the unmarshal method of Unmarshaller.

JAXBElement<HelloType> helloElement = (JAXBElement<HelloType>) unMarshaller.unmarshal(new File("hello.xml"));

4.   Create root object type from the JAXBElement object using its getValue() method.

HelloType hello = helloElement.getValue();

5.   Use appropriate getters of root object to get its attributes and children.

String greeting=hello.getGreeting();

String name=hello.getName().getValue();

TitleType title=hello.getName().getTitle();

System.out.println(greeting+" "+title.value()+" "+name);

 

The xjc compiler

Though we are using the eclipse feature now to generate java classes from xsd, traditionally we had to use the xjc schema compiler from command prompt or from an ant build. The xjc schema compiler tool generates the required interfaces and classes from the schema. The xjc compiler takes as input the xml schema, optionally the external binding declarations file and then generates the required interfaces and classes, including the ObjectFactory class as we have seen. The xjc generated classes do all the low-level work associated with parsing, validating, element accessing, marshaling, and unmarshaling.

Important xjc Command Options are:

  • -nv
    • The strict validation of the input schema(s) is not performed.
  • -b <file>
    • Specifies the external binding file.
  • -d <dir>
    • Specifies the directory for generated files.
  • -p <pkg>
    • Specifies the target package.
  • -classpath <arg>
    • Specifies the classpath.
  • -use-runtime <pkg>
    • The impl.runtime package does not get generated. Instead, the runtime in the specified package is used.
  • -xmlschema
    • The input schema is a W3C XML Schema (the default).

 

Required Jars, Java version and Eclipse configuration

To run the JAXB 2.0, you needed JWSDP 2.0. However JAXB 2.x is now part of Java SE 6 and above; and we will use it. JAXB 2.0 requires at least Java 5.0 because JAXB 2.0 uses parameterized types and annotations. While working in eclipse, we need to make sure our Java build path shows all required JARs and if you are using java 6 or above, it is already there.  In older or non-Jee versions of Eclipse, we needed to configure xjc as an eclipse external tool as below or use an ant build.

 

However in latest Jee eclipse, you can simply right click an XSD and generate the java classes specifying package structure and bindings.

Tags: 

Quick Notes Finder Tags

Activities (1) advanced java (1) agile (3) App Servers (6) archived notes (2) Arrays (1) Best Practices (12) Best Practices (Design) (3) Best Practices (Java) (7) Best Practices (Java EE) (1) BigData (3) Chars & Encodings (6) coding problems (2) Collections (15) contests (3) Core Java (All) (55) course plan (2) Database (12) Design patterns (8) dev tools (3) downloads (2) eclipse (9) Essentials (1) examples (14) Exception (1) Exceptions (4) Exercise (1) exercises (6) Getting Started (18) Groovy (2) hadoop (4) hibernate (77) hibernate interview questions (6) History (1) Hot book (5) http monitoring (2) Inheritance (4) intellij (1) java 8 notes (4) Java 9 (1) Java Concepts (7) Java Core (9) java ee exercises (1) java ee interview questions (2) Java Elements (16) Java Environment (1) Java Features (4) java interview points (4) java interview questions (4) javajee initiatives (1) javajee thoughts (3) Java Performance (6) Java Programmer 1 (11) Java Programmer 2 (7) Javascript Frameworks (1) Java SE Professional (1) JPA 1 - Module (6) JPA 1 - Modules (1) JSP (1) Legacy Java (1) linked list (3) maven (1) Multithreading (16) NFR (1) No SQL (1) Object Oriented (9) OCPJP (4) OCPWCD (1) OOAD (3) Operators (4) Overloading (2) Overriding (2) Overviews (1) policies (1) programming (1) Quartz Scheduler (1) Quizzes (17) RabbitMQ (1) references (2) restful web service (3) Searching (1) security (10) Servlets (8) Servlets and JSP (31) Site Usage Guidelines (1) Sorting (1) source code management (1) spring (4) spring boot (3) Spring Examples (1) Spring Features (1) spring jpa (1) Stack (1) Streams & IO (3) Strings (11) SW Developer Tools (2) testing (1) troubleshooting (1) user interface (1) vxml (8) web services (1) Web Technologies (1) Web Technology Books (1) youtube (1)