Travelling, and not Arriving

          ... a good traveler has no fixed plans and is not intent upon arriving... (Lao Tzu)
Chicago - HarbourChicago RiverChicagoChicago - Gehry BandshellChicago - Navy PierChicago - HarbourFung Wah Bus crash - Chinatown, NYCFung Wah Bus crash - Chinatown, NYCRhein - BenrathSchloss Benrath

OSGi, a month later

Exactly a month ago I posted my first experiences with OSGi, and my attempts to come up with a real, hot-updatable, web application.

Unfortunately I haven’t had any time to work at that prototype lately, but in the meantime I discovered some impressive resources on OSGi available on the net; the most interesting is Neil Bartlett’s OSGi in Practice, a book-in-progress freely donwloadable under the terms of the Creative Commons License.

The availability of this step-by-step book has convinced me to start from scratch with OSGi, and to try to learn it following a more regular path, instead of the usual hopping from a blog post to a mailing list, from a bug report to a cvs repository.

I’ve just opened an OsgiTutorials google project to collect all my code, demos and examples with OSGi; a first example is already available: the code of the first chapter of Osgi in Practice, and my solution for the proposed exercises.

Any feedback or contribution is appreciated!


[jugmilano] The JavaFX Circle

Jugmilano

A quick post to advertise a new, nice initiative of my good friends of the Java User Group Milano: The JavaFX circle.

For four weeks, they’re going to have a meeting every Wednesday night to explore JavaFX, and try to understand how (and… if) this technology is going to change the Java desktop landscape.

For more details check this wiki page.


The hottest Java Web application… ever

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).

FirefoxScreenSnapz001.png

FirefoxScreenSnapz002.png

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?


Dangerous habits

(… having fun with Toonlet ;-) )


Google App Engine opensource porting

Interesting piece of news this morning

One of the biggest criticisms of Google’s App Engine have been cries of lock-in, that the applications developed for the platform won’t be portable to any other service. This morning, Chris Anderson, the Portland-based cofounder of the Grabb.it MP3 blog service, just released AppDrop — an elegant hack proving that’s not true.

Reed the complete Andy Baio report here and check out the official website.


Fun with Railtrackr

In these days I’m rediscovering Linkedin to get in touch with old colleagues and do some good-old networking.
So, going through some connections I discovered Railtrackr, a nice and free Flickr visualization tool written in Rails. The author is Riccardo Govoni an italian guy working with Google in Dublin.
Check it out!

railtracker.png

Nice, indeed. That’s my personal page on Railtrackr: as you can see, if you, like me, have a gazillion of photosets, the interface is maybe a bit too crowded :-)


JavaOne: free for students

JavaOne 2008, the bigger and most spectacular Java conference worldwide (and probably one of the most expensive) is going to be free for students.
If you are interested, check out all the details at developers.sun.com/events/studentprogram/, and don’t miss the opportunity and enroll now. There’s a limited number of free passes.


What is a career in Engineering all about?

A career in Engineering

(Posting here, so you can use it as a future reference)


← Before