Well, I’m talking about hot.. deployment, obviously.
In the last months, it happened to me quite a few times to talk with different people about the possibility of being able, in a Java Web Application, to dynamically add/start/stop plugins.
The usual example that comes to my mind is Wordpress: you can download, add and start plugins, and they’re immediately available, without the need of restarting the web server. And if you don’t need a plugin anymore, you can just stop and delete it.
That’s fairly obvious for a HTML/PHP/scripting guy: however, the average Java kid will immediately remark that it’s not doable in a Servlet container, due to the caching mechanisms inside the Java Classloader, and the way Application Servers/Servlet Containers are built.
That’s all true, but technology, even Java technology ;-), advances; and my point in these discussions was that there are now quite a few techniques and tools that should make it possible. And today I took a couple of hours to try to prove it.
I turned out it was extremely simple.
My tool of choice was Apache Felix, an open source implementation of OSGi. As the website states:
…[Apache Felix] is ideally suited for any project that is interested in principles of modularity, component-oriented, and/or service-orientation. OSGi technology combines aspects of these aforementioned principles to define a dynamic service deployment framework that is amenable to remote management. As an example of a simple use case, Felix can be easily embedded into other projects and used as a plugin or dynamic extension mechanism; it serves this purpose much better than other systems that are used for similar purposes, such as Java Management Extensions (JMX).
Simply put, Apache Felix provides the developer a container where services (”bundles”) can be deployed/started/stopped and made available to an application (or to other services). Felix’ API is really simple and clean, and I was able to write a whopping-126-lines-of-code-class-imports-and-logs-included that provides all the basic functionalities to start hot deploying plugins in your web application. That’s the code (disclaimer: I’m not an expert at all. That’s just a code sample built in a couple of hours. If you have any problems, please ask in the project mailing list)
public class OsgiContainer
{
private static Map map = new StringMap();
private static List list = new ArrayList();
private static Felix container;
public static void start() throws BundleException, InterruptedException,
InvalidSyntaxException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException {
map.put(FelixConstants.EMBEDDED_EXECUTION_PROP, “true”);
map.put(Constants.FRAMEWORK_SYSTEMPACKAGES,
“org.osgi.framework; version=1.3.0,” +
“org.osgi.service.packageadmin; version=1.2.0,” +
“org.osgi.service.startlevel; version=1.0.0,” +
“org.osgi.service.url; version=1.0.0,”+
“com.diotalevi.osgi.felix.interfaces; version=1.0.0″);
map.put(BundleCache.CACHE_PROFILE_DIR_PROP, “cache”);
container = new Felix(new Logger(), map, list);
container.start();
}
public static void stop() throws BundleException {
container.stop();
}
public static void installBundle(String filePath) throws BundleException {
container.getBundleContext().installBundle(filePath);
}
public static void startBundle(String filePath) throws BundleException {
if (container.getBundleContext().getBundles() == null ||
container.getBundleContext().getBundles().length == 0)
return;
for (Bundle b : container.getBundleContext().getBundles())
if (filePath.equals(b.getLocation()))
b.start();
}
public static void stopBundle(String filePath) throws BundleException {
if (container.getBundleContext().getBundles() == null ||
container.getBundleContext().getBundles().length == 0)
return;
for (Bundle b : container.getBundleContext().getBundles())
if (filePath.equals(b.getLocation()))
b.stop();
}
public static <T> List<T> getServices(Class<T> prototype) throws InvalidSyntaxException {
ServiceReference[] srs = container.getBundleContext().getServiceReferences(prototype.getName(), null);
ArrayList resultList = new ArrayList();
if (srs == null || srs.length == 0)
return resultList;
else {
for (ServiceReference sr : srs) {
if (sr!=null) {
resultList.add((T)container.getBundleContext().getService(sr));
}
}
return resultList;
}
}
}
What else you need? Well, first of all, some Java interfaces to define your services. If you look above in my OsgiContainer class, the “map” configuration map, under the key Constants.FRAMEWORK_SYSTEMPACKAGES, defines a package called “com.diotalevi.osgi.felix.interfaces”. That’s the Java package where I defined the services I want my bundles to implement.
Secondly, I need a way to load my bundles in the web application. I obviously used my beloved Grails to create a CRUD interface to define a bundle and upload it (it’s a jar file).


I won’t go into further details on how to create a bundle. It’s, in essence, a regular jar archive with
- a manifest.mf file defining dependencies and services provided
- a special Java class, called Activator, implementing the org.osgi.framework.BundleActivator interface
The final result, after these few steps and no more than 120 minutes of coding, is that I can dinamically add jars to my web application, and use the services provided by these jars. All I need to do is to use the OsgiContainer.getServices(Class c) method, passing the Java interface defining the service I need.
And of course I can always start/stop/restart the bundles/jars, or remove them.
And guess what, I can deploy multiple versions of the same bundle! Since bundles are independent on each other, and live in different classloaders, there’re no class name clashes.
What’s next?
Everything it’s easy and clean, working with Java classes; however, I’d like my bundles to have other kind of resources (most importantly: jsps). It’s obviously doable (jsps are, at the end of the day, java classes…), but I’m still wondering what’s the cleaner way to achieve that. I’m sure someone is working in this direction (don’t forget that the new Spring Application Platform is heavily based on OSGi), but still I haven’t had the opportunity to study this topic further.
Finally, I’m looking for examples of web applications using OSGi for dynamic deployments of plugins/services… Google hasn’t helped me much in this research. Any idea?