Thursday, 11 February 2010

In Bed with Vaadin and OSGi

In this post I will show how to create a modular rich internet application that will run on any browser using Java, Vaadin and OSGi. I'll make all sources and binaries available for download at the end of the post.

Background

I've been working with Flex and combining it with OSGi (on the server) at Arum for the last couple of years and while Flash, especially using Flex as a development tool, is a fantastic platform with great penetration, I have found that I still yearn for solutions which require no plugins. In the last few weeks this has become even more important to me with the announcement of the (Flashless) iPad and embarking on a personal project that needs to run on every browser, not just a browser with a Flash Player plugin installed.

Before starting at Arum I had investigated creating modular RIAs using GWT and OSGi. GWT lets you write your UI code as Java then as part of another build step spits out HTML and JavaScript that works across browsers. Most importantly for me was the fact that converting the Java to HTML/JS was a build step, and not done at runtime. As a result, it is impossible to create modular applications with GWT, though that might change with GWT 2.0. However, even if they add GWT modularity, it will still require a build step to convert Java to HTML/JS.

Having spent a great deal more effort looking for a solution to this problem (how to create a plugin free, cross browser RIA using Java and OSGi) I finally discovered Vaadin.


Vaadin is a suite of HTML UI components that have already been built using GWT, then are composed in to a running application using Java... at runtime.

A "Hello World" Vaadin application looks like this:

Vaadin and OSGi

I was particularly interested to learn that someone had considered using Vaadin with OSGi, though I personally do not like the concept of wrapping it in a J2EE style web application (WAR), nesting the OSGi container inside:


It is understandable that people would assume that if a developer that wants to create an RIA with Java they will want to deploy it as a WAR. However, I generally don't use application servers anymore. They tend to be bloated and have a large footprint soaking up much of a VM's heap space just to get started, and as a result tend to have a fairly long startup cycle (from several seconds to over a minute in some cases). Using an OSGi container *as* an application server gives you a much more lightweight application that doesn't require as much memory and starts up almost instantly and out of everything in the J2EE spec, the only thing I regularly come back to is servlets. Everything else seems to be an exercise in telling developers how to build applications with the view of scaling up hardware - obviously a winning approach for Sun in the old days, but not so useful for people wishing to get away with minimum footprint these days (for example by creating a cloud architecture which uses the minimum resources required and scaling up as demand dictates, not the software architecture).


Right out of the box (from at least version 6.2.2 onwards anyway) the Vaadin jar file is already configured as an OSGi bundle which means I can write other bundles which use those APIs.

My next activity was to make Vaadin not just OSGi friendly, but OSGi's "best friend forever". To do this I wanted to achieve the follow things:
- Allow bundles to register Vaadin Applications (whiteboard pattern - it's easier to register services than look them up) and automatically create a http resource for them.
- Allow bundles to register static resources (themes, widgetsets, etc)
- Make no changes to the core Vaadin jar file that you can download from their site

The result is three classes which are built in to a separate bundle that I currently call com.vaadin.osgi.

- StaticResources runs as an OSGi component and serves the themes and widgetsets directly from the core Vaadin bundle.

To add your own theme or widget set create a fragment which contains your theme/widgetset files and export those as packages. The Fragment-Host should be set to the Vaadin core bundle. The fragment containing your theme/widgetset resources will be added to the core Vaadin bundle dynamically.

Of course static resources should really be deployed separately to a web server that proxies servlet requests on to the container, so I wouldn't recommend this for use in a production environment.

- VaadinOSGiApplicationManager also runs as an OSGi component and looks for OSGi component factories with their component.factory property set to vaadin.app.

The component factory name (specified as component.name) is used as the alias to register an instance of VaadinOSGiServlet which then uses the component factory to create an instance of Application. For example, if component.name was set to myapp, the servlet would be registered at http://localhost:8080/myapp

- VaadinOSGiServlet creates instances of applications that have been registered with the container via a component factory.

This is what is registered by the VaadinOSGiApplicationManager.

Creating an OSGi Vaadin Hello World Application

To get the hello world application shown near the beginning of this post up and running we need to create a bundle which registers the application as a component factory. There is no additional Java code required for this step and by far the easiest way to do this is by describing the bundle with a bnd file.


To create the bundle simply run bnd. I used the following command on my system:

java -jar ~/Downloads/bnd-0.0.384.jar helloworld.bnd

More about bnd and how to get it can be found here:


The result is a bundle that uses declarative services to register your application as a component factory. This is the cool part - if you want to access other OSGi services just create binding methods for them in your application and update the bnd file. Declarative services then injects your application with the services automatically when an instance of the application is created.

Vaadin has this great concept of 'production mode'. When an application is not in production mode, you can append ?debug to your application's URL in order to see a debug console that shows you all kind of useful information such as the traffic between the browser and server, how long requests take, the JSON that has been passed backwards and forward and also gives you a useful 'restart application' button which forces the creation of a new application instance. Obviously, you will want your application to be in production mode at some point so to do this you need to pass "productionMode=true" as a property to the VaadinOSGiApplicationManager and because it is running as a component you can do this using configuration admin. With Apache Felix Fileinstall this is as easy as creating a file called com.vaadin.osgi.VaadinOSGiApplicationManager.cfg and specifying productionMode=true as a line in the file.

Every application will no doubt want it's own theme, right? To do that, again we're going to use bnd to create a bundle which simply adds our theme to the resources in the core Vaadin bundle, a using a useful and under-used feature of OSGi known as Fragments.

Create a folder called etc/theme under which create your theme assets. For example, etc/theme/VAADIN/themes/helloworld/styles.css. The following bnd file would then create a fragment.


Install the fragment and update the core Vaadin bundle and your theme is now available (delivered via the StaticResources component). With the theme installed the hello world application now looks like this:


Again, using bnd to create my bundle:

java -jar ~/Downloads/bnd-0.0.384.jar helloworld.theme.bnd

And that is that; a themed hello world application that is primed for dynamic modularity.

Downloads

[Edit 10th September 2010]

Since writing this I've published an add-on to the Vaadin Directory that contains the bundles you need to run your apps as OSGi apps and a simple example. You can find that here:

http://vaadin.com/directory#addon/vaadin-osgi


Thanks

Lastly, I have to thank Neil Bartlett for mentoring me through some of the OSGi concepts I've used here. Thanks Neil! You can find Neil's website full of useful OSGi information here:



14 comments:

robinndi said...

I have just completed something very similar - running Vaadin on bare httpservice with no web container. I got as far as running the SimpleAddress book example. Now I am porting the 3 tab panels example.
I did not yet compare closely with yours, but I shall.

Chris Brind said...

Thanks for the comment. You might be interested in this Google group we created. It's a bit quiet just now, but I'm sure there'll be more activity as members join.

Feel free to update the group with your progress. :)

http://groups.google.com/group/vaadin-osgi

robinndi said...

I joined the group, I will continue there.

babbata said...

hey chris,
nice one, intend to try it. first hurdle however is that your dropbox links don't work.
cheers!
babbata

Chris Brind said...

Oops! Well spotted. Since then I've published to the Vaadin Directory, take a look here:
http://vaadin.com/directory#addon/vaadin-osgi

babbata said...

chris,
got the jars from the vaadin site, everything works fine, thanks. will try to build up on top of that.
one more broken link, though - neil's blog has moved to http://njbartlett.name/ - you may want to correct that.
cheers!
babbata

Kai said...

Chris,

I am playing around with Vaadin, Equinox & Jetty. When I try to use your org.vaadin.osgi bundle I get an Wiget in the browser saying: Failed to load the widgetset: /VAADIN/widgetsets/com.vaadin.terminal.gwt.DefaultWidgetSet/com.vaadin.terminal.gwt.DefaultWidgetSet.nocache.js?1293530932935

Any hints?

Thx

Kai

Kai said...

Now it is working :) One of the OSGi bundles I needed was not installed...

Chris Brind said...

glad you got it working :)

Kai said...

works great, I just blogged about it: http://www.toedter.com/blog/?p=412

aluedeke said...
This comment has been removed by the author.
ekkescorner said...

Hi Chris,
I like your way to combine vaadin and osgi. I started based on Kai's tutorial and all workled well until I tried to add some Vaadin add-on's.
Is there anywhere a guide or some doc how to solve this ?
tried it with a very small add-on 'QRCode', copied the jar to an Eclipse EE+Vaadin installation, compiled the widgetsets and then copied the VAADIN.widgetsets to a Fragment Bundle in my Eclipse-OSGI installation. tried different ways where and how to add and export the qrcode.jar, but getting always error in browser
fi.jasoft.qrcode.QRCode(NO CLIENT IMPLEMENTATION FOUND)
any idea what could be wrong ?
thx for your helpful bundles !

ekkescorner said...

found it:
copying widgetsets to and exporting from fragment bundle isn't all that must be done:
you have to add an argument like
-Dorg.vaadin.osgi.widgetset=your_custom_widgetset_from_VAADIN.widgetsets

floriansblog said...

Thanks for this very nice post!
Was really helpful.

Florian