Welcome to the Joint-Venture Blog from Fabio Cortesi and Stefan Jäger.
JiBX is one of the fastest XML object mapping frameworks out there (check out this performance test). Furthermore, it is very flexible in binding XML structures to objects. In this blog post I will describe, how a basic JiBX project can be set up with Maven2. The focus of this entry is on getting in touch with JiBX (and a little bit with Maven).
To use JiBX in our project, we just have to add the dependency to our pom.xml. JiBX is fast, but to get it’s high performance, it uses byte code enhancement. For this reason, the byte code need’s to be edited by JiBX after the compilation phase. This is done with a Maven JiBX plugin, which is executed in the build phase “process-classes”.
Besides, I also wanted a JAR file, which contains all dependencies and has a defined main class (to which I will come to later). The creation of the JAR file is done with the Maven Assembly.
Check out the pom.xml for this test run.
After setting up the pom.xml, we can begin to develop a mapping example with Eclipse. JiBX has two main parts on which we have to focus, binding and the runtime part.
In the binding part, JiBX enhances the byte code (based on a binding definition) to enable the mapping between Java objects and a XML files. In the runtim part, the JiBX runtime components are used to perform the marshal (objects to XML) or unmarshal (XML to objects) tasks.
As you have seen in the pom.xml, the JiBX binding files should be located in src/main/jibx. The names of the JiBX files should end with -binding.xml.
Our goal is to map an XML file, based on following schema CustomerSchema.xsd:
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://stefanjaeger.ch/CustomerSchema" xmlns:sja="http://stefanjaeger.ch/CustomerSchema" elementFormDefault="qualified"> <element name="customer"> <complexType> <sequence> <element ref="sja:person" maxOccurs="1" /> <element ref="sja:city" maxOccurs="1" /> </sequence> </complexType> </element> <element name="person"> <complexType> <sequence> <element ref="sja:first-name" maxOccurs="1" /> <element ref="sja:last-name" maxOccurs="1" /> </sequence> </complexType> </element> <element name="first-name" type="string" /> <element name="last-name" type="string" /> <element name="city" type="string" /> </schema>
Our XML Customer1.xml file looks like:
<?xml version="1.0" encoding="UTF-8"?> <customer xmlns="http://stefanjaeger.ch/CustomerSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://stefanjaeger.ch/CustomerSchema CustomerSchema.xsd"> <person> <first-name>Stefan</first-name> <last-name>Jaeger</last-name> </person> <city>Davos Dorf</city> </customer>
We want to map the XML in the two objects Customer and Person (to simplify these lines of code, the getter, setter and toString methods are not described).
public class Customer { private Person person; private String city; } public class Person { private String firstName; private String lastName; }
To map the XML file to these classes, we create following binding definition. Because we use a XML schema, we have to define the namespace. Also the fully qualified name of the mapped class Customer need’s to be used. Because the class Person is in relation with the Customer class, JiBX recognizes automatically the fully qualified name of Person.
<?xml version="1.0" encoding="UTF-8"?> <binding> <mapping name="customer" class="ch.stefanjaeger.jibx.Customer"> <namespace uri="http://stefanjaeger.ch/CustomerSchema" default="elements"/> <structure name="person" field="person"> <value name="first-name" field="firstName" /> <value name="last-name" field="lastName" /> </structure> <value name="city" field="city" /> </mapping> </binding>
Now, we have a XML file, some Java classes and a binding between them. What we now need is an application, which does the unmarshalling of the XML file.
public class JiBXDemoApplication { public static void main(String[] args) throws Exception { IBindingFactory bfact = BindingDirectory.getFactory(Customer.class); IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); Customer customer = (Customer) uctx.unmarshalDocument( new FileInputStream("Customer1.xml"), null); System.out.println(customer.toString()); } }
We are finished now. Just build the project with the command mvn package and let’s see, how the test run is working. Remember to place the XML schema and the XML file to the same location as the JAR file (after mvn package, it should be located in /target/).
The command
java -jar jibx_playground-1.0-SNAPSHOT-jar-with-dependencies.jar
results in
ch.stefanjaeger.jibx.Customer@12d03f9 [person=ch.stefanjaeger.jibx.Person@15dfd77 [firstName=Stefan,lastName=Jaeger] ,city=Davos Dorf]
I have to admit, that I did the same example with ANT. It tooks me a little bit longer… From today on, I’m a Maven fan
Download here the source code of this example. You only have to run mvn package to build the project.
Hi SteveJ,
I am able to execute example with dependency jar successfully but when I try to run the example using without dependency jar, its not working. Do I need to set the classpath(for all the jars) before running it?
Comment by Sharad — 7.7.2008 @ 15:07
Hi SteveJ,
I have requirement where I have to ignore the root element present in the data.xml and do binding only for the child elements of the root element. Can you help me on this?
Thanks in advance.]
Regards,
Sharad
Comment by Sharad — 7.7.2008 @ 15:49
Hi Sharad
1. question:
Yes, that’s right. The “maven-assembly-plugin” just put all required jar files into the newly created jar file. In our case, this is used for the commons-lang library and the JiBX library. I have done this just for the example, so that you can just run “java -jar abc.jar”.
If you have the jar files outside the created jar, you have to define the classpath with all needed jars (e.g. java -cp ./path/to/libs/*.jar -jar abc.jar)
2. question
I don’t understand your question completly. In this example, I also don’t map the root element customer directly. It’s just to define a main class, and all items in it are mapped than. It is able, that the root element contains elements, which are from another class. Just have a look at http://jibx.sourceforge.net/tutorial/binding-start.html.
Sorry for the late answers, I was in holiday…
Comment by Steve J. — 14.7.2008 @ 22:36