Posts Tagged ‘JiBX’

Bind XML message to Java objects using JiBX – JiBX binding tutorial

JiBX binding tutorial

 Companies are moving more and more towards service oriented architecture (SOA) and SOA services communicate with well formatted XML message. If you are working in an SOA Java environment one of your development goal is to bind XML message to Java objects. Jibx is a great open source tool for binding XML data to Java objects. Two main components of Jibx are Binding compiler and Binding runtime. Binding Compiler use binding definition document to specify how Java objects are converted to or from XML. Binding compiler can be linked to your Ant build script and executing the build script does bytecode enhancements on already compiled java classes. Enhanced class files generated by Binding Compiler user Binding Runtime to build objects from XML document and vice versa.

 This is a code block from my ant build script that executes jibx binding compiler on complied java classes. Order-Request.xml and Order-Reply.xml are the binding definition documents  i have used for XML messages of a request reply messaging pattern.

 <path>

<pathelement location=”${basedir}/lib/lib/jibx-run.jar”/>

<pathelement location=”${basedir}/lib/jibx-bind.jar”/>

</path>

<target depends=”compile” description=”Run Binding Compiler on compiled java class”>

<echo message=”Running binding compiler…”/>

<java classname=”org.jibx.binding.Compile” fork=”yes” classpathref=”binding-classpath” failonerror=”true”>

<classpath>

<pathelement location=”${project.classes.dir}”/>

 </classpath>

<arg value=”${project.classes.dir}/com/dj/bookorder/Order-Request.xml”/>

<arg value=”${project.classes.dir}/com/dj/bookorder/Order-Reply.xml”/>      

</java>

</target>

Runtime uses Jibx BindngFactory to construct Marshalling and Unmarshalling contexts , which can be used to convert XML message to Java object or vice versa. Jibx BindingFactory is obtained by passing any of the classes defined by the mapping in your binding definition document using methods defined in the Jibx BindingDirectory class.

 Unmarshalling example:

 public BookOrder getUnMarshalledBookOrderRequest(String xmlMsg)throws Exception{

        BookOrder bookOrder = null;

        IBindingFactory bfact = BindingDirectory.getFactory(BookOrder.class);

        IUnmarshallingContext uctx = bfact.createUnmarshallingContext();

        Object obj = uctx.unmarshalDocument( new ByteArrayInputStream(xmlMsg.getBytes()), null);

        if(obj instanceof BookOrder)bookOrder =(BookOrder)obj;

        return bookOrder;

    }

Marshalling example:

 public String getMarshalledBookOrderReply(Object obj)throws Exception{

        IBindingFactory bfact = BindingDirectory.getFactory(BookOrderReply.class);

        IMarshallingContext mctx = bfact.createMarshallingContext();

        StringWriter writer = new StringWriter();

        mctx.setOutput(writer);

        mctx.marshalDocument(obj);

        return writer.toString();

    }

 Jibx Binding Definition: Jibx Binding definition document is the core part of using Jibx and let’s see how do we write binding definition document for the following XML.

 <?xml version=”1.0″ encoding=”UTF-8″?>

<book-order>

<books>

<book>

            <isbn>45127833211</isbn>

            <book-name>Cooking for Dummies</book-name>

            <order-date>20090912</order-date>

            <order-amount>20.56</order-amount>

            <shipping-date>20090922</shipping-date>

            <payment-type>

                        <card-payment>

                                    <auth-code>98</auth-code>

                                    <expire-date>20130925</expire-date>

                        </card-payment>

            </payment-type>

            <billing-address>

                        <address>200 Links Dr</address>

                <city>Dardenne Prairie</city>

                <state>MO</state>

            <zip-code>63368</zip-code>

                <country>US</country>

            </billing-address>

</book>

<book>

            <isbn>95127833211</isbn>

            <book-name>Art for Dummies</book-name>

            <order-date>20090912</order-date>

            <order-amount>10.56</order-amount>

            <shipping-date>20090922</shipping-date>

            <payment-type>

                        <check-payment>

                                    <check-number>123456783621</check-number>

                        </check-payment>

            </payment-type>

            <billing-address>

                        <address>200 Links Dr</address>

                <city>Dardenne Prairie</city>

                <state>MO</state>

            <zip-code>63368</zip-code>

                <country>US</country>

            </billing-address>

</book>

</books>

</book-order>

 Following is the binding definition I am using for the above XML. We will come to the elements in a while.

 <binding package=”com.dj.bookorder”>

<mapping>

            <collection field=”bookList” usage=”optional”>

                        <structure  flexible=”true” ordered=”false”>

                                                <value field=”isbn”/>

                                                <value field=”bookName”/>

                                                <value field=”orderDate” deserializer=”com.dj.bookorder.binding.util.JibxHelper.deserializeDate”/>

                                                <value field=”orderAmount”/>

                                                <value field=”shippingDate” deserializer=”com.dj.bookorder.binding.util.JibxHelper.deserializeDate”/>

                                                <structure field=”paymentType”/>

                                                <structure field=”billingAddress”/>

                                    </structure>

            </collection>

</mapping>

 <mapping choice=”true” ordered=”false”>

            <structure field=”cardPayment”  usage=”optional”/>

            <structure field=”checkPayment”  usage=”optional”/>

</mapping>

 <mapping>

<value field=”authCode” />

<value field=”expireDate”  deserializer=”com.dj.bookorder.binding.util.JibxHelper.deserializeDate”/>

</mapping>

 <mapping>

<value field=”checkNumber” />

</mapping>

 <mapping>

<value field=”address” />

 <value field=”city” />

 <value field=”state” />

<value field=”zipCode” /

<value field=”country” />

</mapping>

</binding>

Given below is the reply xml message and binding definition

 Reply xml message:

<book-order-reply><process-date>20091112</process-date></book-order-reply>

Binding definition for reply message:

<binding package=”com.dj.bookorder”>

<mapping>

<value  field=”orderProcessDate” serializer=”com.dj.bookorder.binding.util.JibxHelper.serializeDate”/>

</mapping>

</binding>

 Jibx binding definition  elements:

<binding> element: This element is the root of a binding definition document and defines characteristics of the whole definition document.

<mapping> element: Mapping element defines the binding used for every objects within the context.

<collection> element: Collection element defines binding for a Java collection. In the example XML <book-order> can have any number of <book> elements inside a <books> element. In the binding definition document <books> element is bound to a java collection bookList.

<structure> element: This element can take various forms. One is where the structure is an xml element which is linked to an object property of a containing  object. In the example binding definition document , structure billing Address is mapped to <billing-address> element which is bound to BillingAddress property of containing object Book. Another variation is where <structure> element is linked to an object of a  collection. In the example book structure is linked to Book object of books collection.

 Custom serializer and deserializer:

For more control over JiBX binding behavior you can write custom serializer and deserializer code for conversion. Given below code gives you flexibility of converting a date to any date format you like public class JibxHelper.

{ public static Date deserializeDate (String value) throws ParseException

{  return new SimpleDateFormat(“yyyyMMdd”).parse(value);  

    } 

public static String serializeDate(Date value) throws ParseException { 

return new SimpleDateFormat(“yyyyMMdd”).format(value);  

    } 

}

 Here is an example implementation of Jibx marshalling and unmarshalling

  // getBookRequest() get xml String message – This can be from the SOAP request , JMS message or from a file in your hard disk

                String xmlMsg = getBookRequest();

            MessageUtil util = new MessageUtil();

                //      getUnMarshalledBookOrderRequest method defenition is given at the section titled ‘Unmarshalling example:’ in this blog.

            BookOrder order = util.getUnMarshalledBookOrderRequest(xmlMsg);

            for(Iterator it=order.getBookList().iterator();it.hasNext();){

                System.out.println(((Book)it.next()).getBookName());

            }

            BookOrderReply orderReply = new BookOrderReply();

            orderReply.setOrderProcessDate(new Date());

                //      getMarshalledBookOrderReply method defenition is given at the section titled ‘Marshalling example:’ in this blog.

            System.out.println(“Reply Message :”+util.getMarshalledBookOrderReply(orderReply));

 Above example parse an XML string , convert to Java object , iterate through a collection and print Book name. Also convertes object to an XML string as well, which can be passed as the reply to incoming request message. Example generates the given below out put.

Cooking for Dummies

Art for Dummies

Reply Message :<book-order-reply><process-date>20090917</process-date></book-order-reply>

Given below is Java object defenition of BookOrder and Book classes used in this example.

public class BookOrder implements java.io.Serializable

{

private ArrayList bookList = new ArrayList();

    // To Do – Add setter and getter methods

}

 public class Book implements java.io.Serializable

{

 private String isbn;

private String bookName;

private BillingAddress billingAddress;

private Date orderDate;

 private BigDecimal orderAmount;

private Date shippingDate;

private PaymentType paymentType;

// To Do – Add setter and getter methods

}

 Please refer http://jibx.sourceforge.net/index.html for more information on Jibx.

Bidirectional Associations and JiBX

I recently needed to use JiBX to parse a XML document into domain objects that contained bidirectional associations with collections.  The issue started out as a simple NullPointerException since each child object did not have a reference back to its parent. 

After some searching on Google, the only suggestions that I came across had to do with using the post-set attribute, which gets called after the class has been unmarshalled.  For various reasons, most of which I did not want the domain classes tied to JiBX, I sought out a different solution.

The solution I came up with was to use a set-method for the collection instead of field.  So I replaced field=”fieldName” with set-method=”setFieldName”.  This set method ensures that the bidirectional association is properly defined. 

There is an argument to be made that I should be doing this anyway.  After all, the domain class probably should not let it be up to the caller to ensure the bidirectional association is properly defined, regardless if it is being called from JiBX or some other caller.

However there was one unintentional side affect.  The project is also using Hibernate.  The same domain classes were mapped using lazy associations.  This change to the set method in affect turned off the laziness.  The solution for this was to change the Hibernate mappings to use field access to bypass the set method.