Welcome to the Joint-Venture Blog from Fabio Cortesi and Stefan Jäger.
In this post, I will cover again the topic JiBX. This time, I will focus on a very special case, the bidirectional mapping with JiBX. To realize that without affecting a currently used domain model (as it will happen if we use pre-set, as described in http://jibx.sourceforge.net/tutorial/binding-extend.html), we need to implement an JiBX Marshaller and an JiBX Unmarshaller.
But let me start with the simple problem. We do have two simple POJOs, Customer and Person, which do know each other. If you are using for example Hibernate, bidirectional linking is not a rarity. With the JiBX binding XML we used in our last examples, the bidirectional linking is not set. To demonstrate this, I added these two lines of code in the main application:
System.out.println(customer.toString()); System.out.println(customer.getPerson().getCustomer().toString());
The second line will result in a NullPointerException, because JiBX is not setting this bidirectional linking. To get that working without affecting the two classes Customer and Person (!), we have to create our own Marshaller and Unmarshaller.
First of all, we have to prepare our mapping file. The best way for a bidirectional mapping is to define an own mapping section for the class Person (which was previously part of the Customer mapping part).
The reason for this step is simple, but important. Our customized Unmarshaller should let JiBX unmarshal the Person into an object and our Unmarshaller should only extend the object with the bidirectional mapping to the Customer. For this reason, JiBX needs an own mapping section for this class.
After preparing the JiBX mapping, our next step is to create a Marshaller and Unmarshaller class. For the bidirectional mapping, we will just need an Unmarshaller. But because we do have a JiBX mapping file for both directions, we do have to define a Marshaller and a Unmarshaller.
We create for this example a new class with the name BidirectionalMapper, which implements the interfaces IMarshaller, IUnmarshaller and IAliasable. These Interfaces are delivered with the JiBX libraries. In the implementation, there are two remarkable parts in the method unmarshal. The first one just forwards the real unmarshalling action to the JiBX context and the second one creates the bidirectional linking.
Object unmarshalledObject = ctx.unmarshalElement(); Person person = (Person) unmarshalledObject; ... Object parent = ctx.getStackObject(0); person.setCustomer((Customer) parent);
In the marshal method, we also let JiBX marshal our person. Because the bidirectional linking has no affect to this method, this method is just simple.
ctx.marshalCollection(listOfElements);
After we created our Mapper, we need to define the marshallers in the JiBX mapping file. For this reason, we expand the element structure with the marshaller and unmarshaller class path.
If we run now our application again, there is no NullPointerException anymore and we can use our previously used domain model without changing anything at these classes.
If you are interested, you can download the whole eclipse project with all the sources from here.