Monthly Archives: January 2015

Demystifying JINI: Dynamic Code Download

In the 1st part of the Demystifying JINI series, we had explored how to write a bare bones non secured client/server: http://palashray.com/demystifying-jini-non-secure-server-part-1/

In the 2nd part, we had shown how to Spring-ify it: http://palashray.com/demystifying-jini-non-secure-server-part-2/

In the latest increment, we will explore how to handle dynamic code download.

I have been working with JINI for the past couple of years. And the more I explore its features, its versatility, the more I come across new ones. This project was built with the famous “Eight Fallacies of Distributed Computing”. So, needless to say, it does not disappoint in terms of scalability or reliability.

Why need dynamic code download?

At the heart of JINI lies its flexibility. It decouples the interface from the implementation (of the Proxy), and makes it independent of the transport protocol as well. All these details are transparent to the end user.

However, there needs to be a way in which the Stubs are downloaded. These stubs will actually help the remote client to connect to the server, and make calls on the remote JVM. This is where dynamic code download is needed. And this comes out of the box with JINI.

Why should I care about dynamic code download?

The dynamic code download is a very powerful feature. In normal client/server distributed architecture, the client and the server agrees on a common API. This is commonly known as the shared module, be it JEE or RMI. And it is mandatory for us to bundle the shared module with the server as well as the client modules. Otherwise, the application will blow up with hosts of NoClassDefFoundError-s.

But, with this interesting feature in JINI, the client does not even have to depend on this shared module at all. The reason is, it can be downloaded when doing the lookup. Of course, every feature comes with its costs, and in this case, the only downside to this is, we need to use reflection to query the remote service. Either that, or use a scripting language like Groovy.

How does it work?

To enable dynamic code download, we need to specify the code base property (similar to the Applet’s) on the JINI server. When the client connects to the server via lookup, this will be available to the JINI client. In its simplest form, it can be as below:

System.setProperty(“java.rmi.server.codebase”, http://localhost:8080/rmi-service-api-1.0.jar);

This should be called while starting the JINI server.

Getting started

Download the folder: https://github.com/paawak/blog/tree/master/code/jini/unsecure/jini-services

cd into it and first start up the reggie by using the ./start-reggie.sh

Then, again, we need to start a http server to serve the jars for dynamic code download. Use the ./httpd.sh to start that server. This server starts at port 8080 and makes any jar placed inside of the service-interface directory, available over http://localhost:8080. This is a small utility provided y JINI, in production, we would need a more secured web server.

The Service API

The API jar is built and put in the service-interface directory above to make it available for dynamic downloads. Note that it is bundled with the Server, but not with the Client.

The Server

We have built this on top of the Spring-ified server that we saw in part 2.

Note that its is almost similar, just has the extra line setting the rmi-codebase property.

The Client

Since the client does not have the API as its dependency, we have to use reflection. But remember to use the RMIClassLoader to load classes from the API jar. Let us demo a Swing app which uses the remote BankDetailService to fetch data to be displayed on the JtreeTable.

The Main Class

The Method to Query the Remote Service

Sources

The sources for the server be found here:

https://github.com/paawak/blog/tree/master/code/jini/unsecure/dynamic-code-download/spring-rmi-server

The sources for the client be found here:

https://github.com/paawak/blog/tree/master/code/jini/unsecure/dynamic-code-download/rmi-client-dynamic-code-download

You can download the sources and then run:

mvn clean install -P create_dist

This will create the distribution inside the target/appassembler directory. You can go inside the appassembler/bin directory and run the ./launch_swing_app to launch the application.

Reference

http://www.softwarematters.org/jini-intro.html

Jan Newmarch’s Guide to Jini Technologies

Using Jaxb To Serialize Java-Objects To Xml

Recently, I had a requirement of serializing some Java objects to xml. Though I had assumed it to be fairly straight forward, during implementation, I found out the hard way that it is not at all intuitive. The following are the ground rules:

  1. You need to decorate the class which you want to serialize with the @XmlRootElement annotation. This rules out having the flexibility of serializing a List or a Map directly. It has to be wrapped within a class having the @XmlRootElement annotation.

  2. Jaxb needs a default constructor. So if you have an immutable class with all fields set through the constructor, you need to provide a default constructor and set all the final fields to null.

  3. Though Jaxb works well with the List, it needs a custom adapter to serialize a Map with the @XmlJavaTypeAdapter annotation, as we will see. This is the single most pain point in using Jaxb.

The serializer code

I am using the O/X Mappers from Spring (http://docs.spring.io/spring-ws/site/reference/html/oxm.html) for marshalling. I found it very convenient, specially if I want to switch from Jaxb to say, Xstream. The code is pretty simple:

This is the version using plain Jaxb:

The POJO to be serialized

The POJO looks like:

Attempt 1

When I try to generate xml, I get a blank document:

 

The possible cause might be that since the object is immutable without any setters for the fields, Jaxb cannot figure out the fields to serialize. So, this time we will try to explicitly ask Jaxb to serialize the fields by adding the @XmlAccessorType(XmlAccessType.FIELD) annotation to the EmployeeGroups.

Attempt 2

The POJO looks like:

The 2nd attempt gives rise to the following exception:

Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.util.List is an interface, and JAXB can’t handle interfaces.
    this problem is related to the following location:
        at java.util.List
        at private final java.util.Map com.swayam.demo.xml.EmployeeGroups.employeeGroups
        at com.swayam.demo.xml.EmployeeGroups

This message is actually misleading. What it means is that its high time for us to write our custom adapter for handling the Map.

Attempt 3

The adapter would extend the XmlAdapter. It would consume a Map<EmployeeRole, List<Employee>> and return a concrete POJO, in our case a ListWrapper<SimpleMapEntry>.

The SimpleMapEntry represents an Entry in the Map, customized to our needs.

The ListWrapper is just a wrapper around a List, as Jaxb cannot handle a List, and needs a POJO to serialize.

At the end of it, the test runs without error, giving the following output:

 

Attempt 4

The adapter works fine, but since the members are immutable, we have to explicitly declare the fields to be picked up by Jaxb.

The test errors out:

ERROR [main] PlainJaxbSerializer.serialize(46) | could not convert rmi output to xml
javax.xml.bind.MarshalException
 – with linked exception:
[com.sun.istack.internal.SAXException2: class com.swayam.demo.xml.jaxb.SimpleMapEntry nor any of its super class is known to this context.
javax.xml.bind.JAXBException: class com.swayam.demo.xml.jaxb.SimpleMapEntry nor any of its super class is known to this context.]
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311)

Attempt 5

This simply means that when creating the Jaxb context, pass in the SimpleMapEntry as an argument:

All is good, and this is the output:

Attempt 6

Note that the employee node is still empty. We need to explicitly set the @XmlAccessorType(XmlAccessType.FIELD) annotation:

And everything comes as expected:

Attempt 7

The only problem as I see now is this:

It should be within an <employee>. The following is the modification needed:

With this, we get the following output:

Sources

The sources can be found here: https://github.com/paawak/blog/tree/master/code/jaxb-demo

Reference

https://jaxb.java.net/tutorial/

http://docs.spring.io/spring-ws/site/reference/html/oxm.html