Developing applications that use JAXB on Liberty profile

A short tutorial to develop a sample application that uses JAXB on Liberty profile.

JAXB is the Java EE standard for XML binding. JAX-WS and JAX-RS standards intrinsically use JAXB (Java Architecture for XML Bindings) for marshalling and un-marshalling operations. It’s a very simple API that can be used to convert Java objects to XML and XML to Java. You can develop applications that use JAXB on Liberty profile which supports JAXB 2.2.

JAXB is an annotation-driven framework which provides simple annotations for managing JAXB artifacts. In most cases, simple annotations are enough for writing applications. It also supports schema validation against marshalling and un-marshalling activities. Validation should be used with care because it can be a significant performance concern.

Liberty profile ships with the tools for JAXB application development. In <wlp.intall.dir>\bin\jaxb there are two scripts: xjc and schemagen. Xjc is used for generating Java artifacts from a schema source (contract first) and schemagen is used for generating a schema from Java source (code first).

Before you start

  1. Install the Java Architecture for XML Bindings feature into your Liberty runtime installation.
  2. Create a Liberty profile server.

The following instructions assume that you are using the WebSphere Developer Tools for Eclipse Juno.

Creating the application using JAXB on Liberty profile

The sample application shows how to marshal Java objects to XML and demonstrates schema validation as well. We’ll generate a Book class from the BookSchema.xsd schema using the xjc tool. The BookSchema.xsd specifies the schema definition with a restriction on the title field which we’ll use to demonstrate validation.

    1. Create a Dynamic Web Project called JAXB_Liberty_Test (clear the Add project to an EAR check box):New Project Developing applications that use JAXB on Liberty profile
    2. Create a Liberty profile server.
    3. Enable the jaxb-2.2 feature. In the server.xml file, add <feature>jaxb-2.2</feature> (if you have enabled other features that depend on the JAXB feature, it might already be enabled). For example:
      <server description="new server">
      
          <!-- Enable features -->
          <featureManager>
              <feature>jsp-2.2</feature>
              <feature>jaxb-2.2</feature>
          </featureManager>
      
          <httpEndpoint id="defaultHttpEndpoint"
                        host="localhost"
                        httpPort="9080"
                        httpsPort="9443" />
      </server>
      
    4. Create an HTML web page called index.html in the project and paste the following HTML into it. Users will enter data into the web page which will capture the data as form variables, or XML, for each book entry:
      <!DOCTYPE HTML>
      <html>
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>Welcome to JAXB Test with Liberty</title>
      </head>
      <body>
      <h1 align="center">Welcome to JAXB Test with Liberty</h1><br>
      <h2>With this Application we'll demo JAXB marshalling and un-marshalling usage using Liberty.</h2>
      <br>
      <h3>Please enter book information below:</h3>
      <br>
      <form action="./servlet/JAXBTest?operation=marshal" method="POST" id="JAXBMarshalForm">
      <table>
      <tr>
          <td>Enter Book ISBN</td>    <td><input type="text" name="isbn" id="isbn" value="I39939B93" size="30"></td>
      </tr>
      <tr>
          <td>Enter Book Title</td>   <td><input type="text" name="title" id="title" value="Liberty Profile" size="30"></td>
      </tr>
      <tr>
          <td>Enter Book Author</td>  <td><input type="text" name="author" id="author" value="Amol Deshpande" size="30"></td>
      </tr>
      <tr>
          <td>Enter Book Category</td>
          <td><SELECT name="category" id="category">
                  <option>Computer Science Engineering</option>
                  <option>Physics</option>
                  <option>Mathematics</option>
              </SELECT>
          </td>
      </tr>
      <tr>
          <td>Enter Book Price</td><td><input type="text" name="price" id="price" value="333" size="30" /></td>
      </tr>
      <tr>
          <td><input type="Submit" value="Post Book"></td>
      </tr>
      </table>
      </form>
      <form action="./servlet/JAXBTest?operation=unmarshal" method="POST" id="JAXBUnmarshallForm">
      <h3>Enter XML to convert to Book Object</h3>
      <textarea name = "bookXML" id="bookXML" cols="66" rows="15"><?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
      <book bookIsbn="I39939B93" xmlns="http://model.jaxbtest.com/">
      	<bookTitle>Liberty Profile</bookTitle>
      	<author>Amol Deshpande</author>
      	<price>333.0</price>
      	<category>Computer Science Engineering</category>
      </book></textarea>
      <br><input type="Submit" value="Post Book XML">
      </form>
      </body>
      </html>
      
    5. Create an XML Schema file called BookSchema.xsd in the WebContent folder of the project. The BookSchema.xsd file specifies the schema that Book XML should follow. Copy the following XML code into the file. Notice that there is a minLength restriction on the bookTitle field.
      <?xml version="1.0" encoding="UTF-8"?>
      <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://model.jaxbtest.com/"
      xmlns:tns="http://model.jaxbtest.com/"
      elementFormDefault="qualified">
      
      <complexType name="Book">
              <sequence>
      <element name="bookTitle" type="tns:MinTitle" nillable="false"></element>
                  <element name="author" type="string"></element>
                  <element name="price" type="double"></element>
                  <element name="category" type="string"></element>
              </sequence>
              <attribute name="bookIsbn" type="string"></attribute>
          </complexType>
          <simpleType name="MinTitle">
              <restriction base="string">
                  <minLength value="5"></minLength>
              </restriction>
          </simpleType>
          <element name="book" type="tns:Book" />
      
      </schema>
      
    6. From the command line, create the JAXB model class Book.java using the xjc tool:
      1. Change to the project directory in your Eclipse workspace.
      2. Run the following command (or the equivalent on Linux or Mac):
        <install_dir>\bin\jaxb\xjc -target 2.1 -d src .\WebContent\BookSchema.xsd

        Where <install_dir> is the location of the Liberty runtime installation.

      The command generates three assets in the src directory of the project:

      • Book.java model file
      • ObjectFactory.java file, a factory for creating JAXB Book elements
      • package-info.java file for specific package level annotations
    7. Edit the Book.java file to add the toString implementation:
      public String toString() {
      
              return " ISBN : " + bookIsbn
                      + ", Title : " + bookTitle
                      + ", author : " + author
                      + ", price : " + price;
          }
      
      
    8. Create the JAXBTest servlet class, which does all the magic of marshalling and un-marshalling. The servlet first creates the Book object from request parameters. Based on the value of the operation parameter, the servlet does the marshalling or un-marshalling.
      response.setCharacterEncoding("UTF-8");
          String operation = request.getParameter("operation");
          PrintWriter pw = response.getWriter();
          BufferedWriter bw = new BufferedWriter(pw);
      
          if(operation!=null && operation.equalsIgnoreCase("marshal")){
              // Marshalling code here
      }else if (operation!=null && operation.equalsIgnoreCase("unmarshal")){
          // Un-marshalling code here
      }
      
    9. Create the JAXB marshaller, which primarily converts the JAXB model instance book:Book and marshals it into the equivalent XML:
      /*
      * Takes a Book object and marshalls it into an XML string return.
      * Takes Validation XSD into account by
      * feeding into the marshaller.
      *
      */
      private String getBookAsXML(Book book,String path) {
      
      String bookAsXML = "";
          try {
          JAXBContext ctx = JAXBContext.newInstance("com.jaxbtest.model");
          StringWriter writer = new StringWriter();
          Marshaller marshaller = ctx.createMarshaller();
      marshaller.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(new File(path +"/BookSchema.xsd")));
                  marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
          ObjectFactory objectFactory = new ObjectFactory();
          JAXBElement<Book> bookElement = objectFactory.createBook(book);
          marshaller.marshal(bookElement, writer);
          bookAsXML = writer.getBuffer().toString();
      
          } catch (JAXBException e) {
              e.printStackTrace();
      bookAsXML = "<error><errorCode>100</errorCode><errorDescription>" + e.getCause().getMessage()+"</errorDescription></error>";
      
          } catch (SAXException sax){
              sax.printStackTrace();
      bookAsXML = "<error><errorCode>101</errorCode><errorDescription>" + sax.getCause().getMessage()+"</errorDescription></error>";
          }
          return bookAsXML;
      }
      
      

      If there is an exception, the class picks the error code and prints the error in XML format to the browser.

    10. Create the JAXB unmarshaller, which does the reverse job of taking an XML and converting to a Java object:
      /**
       *
       * Takes book as XML string and returns an object.
       * @param bookXML
       * @param path
       * @return
       */
      
      private Book getBookAsObject(String bookXML,String path)
      {
          Book book = null;
          try{
          JAXBContext ctx = JAXBContext.newInstance("com.jaxbtest.model");
          Unmarshaller unMarshaller = ctx.createUnmarshaller();
      unMarshaller.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(new File(path +"/BookSchema.xsd")));
      
      JAXBElement<Book> bookElement = (JAXBElement<Book>)unMarshaller.unmarshal(new StringReader(bookXML));
      
          book = bookElement.getValue();
      
          }catch(JAXBException e){
              e.printStackTrace();
              book=null;
      } catch (Exception e) {
              e.printStackTrace();
              book=null;
          }
      
      return book;
      }
      

Note that we provide schema BookSchema.xsd to the Marshaller to validate against it. We have provided minLength to be 5 in our schema.

Running the sample application

  1. Deploy the application to the server. The web page is automatically opened.
  2. To test the JAXB marshalling feature, type some sample values in the form in the top half of the page, then click Post Book:jaxb webpage Developing applications that use JAXB on Liberty profile
  3. If everything goes well, you should see following XML output in the browser:
    <book bookIsbn="I39939B93">
       <bookTitle>Liberty Profile</bookTitle>
       <author>Amol Deshpande</author>
       <price>333.0</price>
       <category>Computer Science Engineering</category>
    </book>
    

    Note that bookIsbn is modeled as an XML attribute.

  4. To test the JAXB schema validation feature, go to the index.html page and specify the values in form. Ensure that the value of the Title field is less than 5 characters (eg ABCD), then click Post Book button. You should see the following output in the browser:
    <error><errorCode>100</errorCode><errorDescription>cvc-minLength-valid: Value 'ABCD' with length = '4' is not facet-valid with respect to minLength '5' for type 'MinTitle'.</errorDescription></error>
    

    This demonstrates that the schema validation has raised the exception that a 4-character value is not valid.

  5. To test the JAXB unmarshalling feature for our Book example, you need the Book XML representation to convert to Java object. For example, we’ve provided the Book XML marshalling output in the text area in the bottom half of the web page. Click Post Book XML. You should see the following output:
    ISBN : I39939B93, Title : Liberty Profile, author : Amol Deshpande, price : 333.0
    

Using schemagen tool

If you prefer the code-first approach, you can also use schemagen tool from <wlp.intall.dir>\bin\jaxb with the specified parameters to generate the schema.

See also:

  • Hågen Hasle

    What if we want to do this in our Maven build? Requiring Eclipse and a server installation to be able to generate java classes from a schema is not very devops-friendly.. :)

    • Guest

      Hi,

      That’s correct. None of that is mandatory. One can use XJCTask with ANT for XJC automation. Another option with ANT is configuration with . Same goes for schemagen. One can use SchemaGenTask with ANT. -> should also work.
      Liberty has meta jars under LIBERTY_HOMEbinjaxbtools for xjc and schemagen. These point to LIBERTY_HOMElibcom.ibm.ws.jaxb.tools.2.2.3_1.0.0.jar for tooling.

    • amol333

      With Maven, there is jaxb2-maven-plugin plugin to automate.