Last week I had a great time in Stockholm working two days at ComActivity AB. They are reworking their applications so they can take advantage of OSGi in their server applications. In this process they are investigating lots of technologies. And as is so often the case, one runs in modularity problems while using legacy libraries. Ok, they are not all legacy libraries, they are often brand new and provide valuable functionality, and so often for free as well. What a world!
However, integrating libraries into an OSGi based system is often fraud with class loader problems. In this case we took an in-depth look at the Cinnamon library from www.spicefactory.org. This library is a Remote Procedure Call (RPC) library for Flex based applications using the AMF protocol. AMF is an Adobe (publicized) standard for serializing ActionScript objects from Flash.
At the start of the visit I was shown a very nice demo of the application. Fast, powerful, and looking good despite the austere theme they were using. As can be expected, the application took advantage of the OSGi architecture. A top level application used the service registry to discover modules that implemented a specific application functionality. This module provided the Flex flash SWF file and provided the receiving end of the RPC interface. It was kind of cool to see how they made new bundles with bnd, deployed them with File Install and during the whole morning never restarted their Tomcat that was hosting their OSGi WAR file.
During the demo we went through the design by looking at the source code, modifying things, and then testing it. One thing I noticed was the large amount of configuration and specialized classes to make this application work with Cinnamon. I once write a tiny webrpc application and did not think it had to be that hard. (I am an optimist).
One of the key issues was configuration. The Cinnamon library had two types of configuration: Spring based and a private XML configuration format. The key problem is that these text based configuration files are forced to use dynamic class loading. If these classes must come from other bundles, then OSGi (rightfully) barks. The whole purpose of the OSGi modularity is to have controlled class loading, taking care of versions and other constraints. Doing Class.forName blissfully ignores such mundane details. A large part of the custom code was necessary to find the right classes at the right time.
Obviously, this was working. However, cruft frustrates me and I convinced them we should try to get rid of it. So at the last two hours of the second day we created a new project and started from scratch. No Spring XML and no Cinnamon XML. It was already at the end of the second day so we had little time but it turned out to be surprisingly simple to use the Cinnamon library from Java only, taking advantage of the facilities of the service registry (and that without even reading the manual or javadoc). Still, by getting rid of the XML configuration things became significantly easier. All of the class loading problems disappeared as by magic because from the Java code we had direct access to the right types without requiring dynamic loading.
By single-stepping through the Cinnamon library I also noticed how much code was spent on making the library flexible and adaptable. As so many libraries today, it was doing impressive class loader gymnastics to implement yet another plugin system. I think the library could be significantly simplified if it had been using OSGi to provide this plugin mechanism with bundles and services. It is sad to see how many time the same wheels are invented over and over again.
Anyway, I also remembered how I had a similar experience with Hibernate last year. In an effort to use Hibernate from an OSGi based system, I switched from the XML configuration to do the configuration in Java code. Also in that case, a lot of things that caused class loading issues just disappeared because classes could be manipulated as classes (with the proper versioning) and not as strings.
Different, but still related, the day before we had another experience where we significantly simplified life. They had used Spring to define global configuration for database connections. This is obviously highly specific information for each of their customers. With Spring they could provide this configuration through a bundle. However, if they wanted to change the configuration, they had to update this bundle. Looking closer at the configuration file it was clear that they were specifying several connections to databases. This looked like a clear case for the Configuration Admin's Managed Service Factory. We modified their pool manager to use the Configuration Admin by registering a Managed Service Factory service. This was only a few lines of code. They were already using File Install, and File Install makes it easy to set new configurations by placing a property file in the watched directory. It was kind of sad to see how small and readable the property file was in comparison with the XML configuration it replaced.
Now do not get me wrong. I am very impressed with the Spring, Cinnamon, and Hibernate libraries and I do see the value of centralizing configuration files. Maybe OSGi changes the rules a bit and this XML based model works better in monolithic applications. Lets face it, what is the difference of changing XML or Java code in Eclipse? However, last weeks experience makes me wonder if we should not be a little bit more critical before using XML to solve problems that are much cleaner and better solved in plain old Java?