XSLT + JSON-RPC as alternative to JAXB

Lately I use JSON-RPC extensively and not only for RPC communication. JSON-RPC library comes with few very useful helpers that made worth using it as standalone JSON-> Java conversion tool for really complex objects.
In one of projects I had to convert proprietary XML-formatted data to Java POJOs with number of calculations/transformation rules that made using of standard JAXB tools seamless. Each XML file comprised more than 1000 elements and resulting domain model had 20 classes organized in a tree. After some attempts to write annotation-based transformation engine(it actually worked but java code was poisoned with 2/3 of annotations. Moreover transformation rules were not changeable without recompilation) a decided to use XSLT + JSON-RPC chain.
First of all I wrote XSL templates for performing all transformation rules. Have to admit that it was mach easier to define rules with XPath/XQuery than in plain java(ok, there is common-collections + bean-utiles but it is nothing comparing to XSLT). As result of XSLT I had text file with my objects tree defined in JSON.
Second step was converting JSON to Java. JSON-RPC library is just brilliant for that. You need to get Bridge class, define mapping hints to Java classes, get serializer and you good to go.

JSONRPCBridge bridge = JSONRPCBridge.getGlobalBridge();
bridge.registerClass("com.maersk.tpd.domain.Route", com.maersk.tpd.domain.Route.class);
bridge.registerClass("com.maersk.tpd.domain.RouteLeg", com.maersk.tpd.domain.RouteLeg.class);
bridge.registerClass("com.maersk.tpd.domain.RoutePoint", com.maersk.tpd.domain.RoutePoint.class);
bridge.registerClass("com.maersk.tpd.domain.RoutePointRole", com.maersk.tpd.domain.RoutePointRole.class);
JSONSerializer serialiser = bridge.getSerializer();


Nice part that JSONRPCBridge has number of predefined serializers for various Java classes like Date, Float, Boolean, etc. However sometimes you need to add you own serialisers for custom types. The JSON-RPC guys definitely anticipated it so you can register you own serialiser on bridge with registerSerializer(Serializer s) method. Fair enough unless you want to redefine serialiser that handles already mapped class. Let say you execute myBridge.registerSerializer(new MyDateSerialiser()). What you get is “different serializer already registered” exception. No comments here. It is probably has some explanation.. So if you steel want to do it (I did) you have to add one more function to JSONSerialiser:

public void registerOrReplaceSerializer(Serializer s) throws Exception {
  Class classes[] = s.getSerializableClasses();
  synchronized (serializerSet) {
    if(!serializerSet.contains(s)) {
      if(isDebug())
        log.info("registered serializer " + s.getClass().getName());
      for(int i=0; i < classes.length; i++) {
        serializableMap.put(classes[i], s);
      }
      s.setOwner(this);
      serializerSet.add(s);
      serializerList.add(0, s);
    }
  }
}


So now you might add your own serialisers and see the whole beast working:

serialiser.registerOrReplaceSerializer(new GcssDataSerialiser());
serialiser.registerOrReplaceSerializer(new GcssBooleanSerialiser());
Object obj = serialiser.fromJSON(jsonString);


Need to mention that both transformations XML-JSON and JSON->Java work extremely fast. So when the time to optimization came the transformation part was out of questions. Hibernate batches were most time consuming thing. But it is another story for next post.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: