Categories
Software Development

JiBX Binding Tutorial

Tagged with: , ,

Companies are moving more and more toward service-oriented architecture (SOA), and SOA services communicate with a well-formatted XML message. If you are working in an SOA Java environment, one of your development goals is to bind XML messages to Java objects. JiBX is a great open-source tool for binding XML data to Java objects.

The two main components of JiBX are the Binding compiler and Binding runtime. The binding Compiler uses a binding definition document to specify how Java objects are converted to or from XML. The 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 the XML document and vice versa. 

Order-Request.xml and Order-Reply.xml are the binding definition documents used for XML messages of a request-reply messaging pattern.

The following is a code block from an Ant build script that executes the JiBX binding compiler on compiled Java classes: 

<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>

The runtime uses JiBX BindingFactory to construct marshalling and unmarshalling contexts, which can convert XML messages to Java objects 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.

This example shows how to write a binding definition document for the XML below:

<?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>

The following is the binding definition used for the above XML:

<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>

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 the characteristics of the whole definition document.
<mapping> element: The mapping element defines the binding used for every object 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 linked to an object property of a containing object. In the example binding definition document, the billing address is mapped to <billing-address> element bound to BillingAddress property containing object Book. Another variation is where the <structure> element is linked to an object of a  collection. In the example, book structure is linked to the Book object of the books collection. 

Custom serializer and deserializer: For more control over JiBX binding behavior, you can write a custom serializer and deserializer code for conversion. The code below allows you to convert a date to any date format you like with 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 definition is given at the section titled ‘Marshalling example:’ in this blog.
System.out.println(“Reply Message :”+util.getMarshalledBookOrderReply(orderReply));

The above example parses an XML string, converts it to a Java object, iterates through a collection, and prints the Book name. Also, converts an object to an XML string, which can be passed as the reply to the incoming request message. This example generates the output given below.

Cooking for Dummies

Art for Dummies

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

The following is the Java object definition 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 to https://jibx.sourceforge.net/index.html for more information on JiBX. Contact our team for additional questions!