Tuesday, 27 July 2010

Comparing approaches to Vaadin and OSGi

Some time ago, inspired by an attempt I saw on their forums, I set about enabling Vaadin (a pretty amazing RIA derivative of GWT) so that it would work in an OSGi container. You can read about that here.

As it happens Peter Kriens and Neil Bartlett both set about doing the same thing, all our efforts completely independent of each other. In this post, I'll compare and contrast the three approaches.

Firstly, Peter and I both decided to use Declarative Services (DS), where as Neil decided to create a light-weight service driven API.

In that regard, the approaches fragment and it becomes difficult to compare Neil's approach with the approach taken by Peter and myself. The main advantage of the service driven approach is that you don't need to use DS. You create an instance of the service interface and register it, then the rest of Neil's code makes that implementation available as a Vaadin application. This is a great approach if you might not want to use DS and doesn't stop you from using it if you want. The main disadvantage here is that there is an extra dependency on the API that Neil has created.

With the DS approach there's no additional hard-dependency, though there is a dependency on DS implied. In both Peter's approach and mine, we simply extend com.vaadin.Application and mark the implementation as a component factory. After this, things differ slightly between my approach and Peter's.

My code looks for components with the property "component.factory=vaadin.app" and once I find matching component factories I take the "component.name" of the factory and use that for the HTTP alias against which to register the servlet that does the work. Peter's approach is to look for "component.factory=com.vaadin.Application/*" and take the name from the part represented by the wildcard. This seems like a more sensible approach, as the component name tends to be more unique and use a domain name type structure, if not the component classname, period. A classname is not really an appropriate HTTP alias.

Vaadin uses a fair amount of static resources. My view here is that in most cases a dedicated web-server should be used to handle static resources (e.g. Apache), in a classic n-tier setup where static content web servers sit in front of 'application servers'. As such I've created a second bundle called staticres which will proxy static resources from the Vaadin bundle, but the recommended approach is to use a web-server. Further more, if your app has additional static resources that are not in the Vaadin bundle then these can be added by creating a fragment containing those resources and setting the host to the Vaadin bundle. My "staticres" bundle won't know the difference.

However, this highlights another major difference between my approach and Peter's. In Peter's approach, he expects wraps the Vaadin jar and turns it in to an internal library, exporting it's packages to the container. However, the Vaadin is already a bundle, so this seems unnecessary to me. The additional downside of this is that if the Vaadin jar is updated by the Vaadin folks, then people using Peter's bundle will either need to rebuild it for themselves, or wait for Peter to release a new version. The approach I have taken allows people to update the Vaadin bundle independently of the OSGi code I've written.

The remaining differences between my approach and Peter's are at the code level. Peter's experience shines through showing much better concurrency handling and support for multiple HttpService implementations, where as mine only supports a single HttpService.

So in Conclusion, Vaadin must be an interesting technology (personally I love it) for three individuals to decide to skin that cat in their own way. While the DS approach I've taken is considerably different from Neil's service approach, there are definitely enhancements to what I have produced that I can make based on Peter's code. To summarise the pros and cons of all three:

Neil's approach:
+ no dependency on DS and does not preclude it either
+ not coupled to any specific version of Vaadin
+ lightweight easy to use API
- additional dependency on non-standard API
- no clear way to handle additional static resources
- may end up using DS anyway

Peter's approach:
+ well defined and sensible use of DS
+ high quality implementation
- no clear way to handle additional static resources
- tight coupling to a specific version of Vaadin

Brindy's approach:
+ not coupled to any specific version of Vaadin
+ additional static resources easily handled
- limited to one HttpService
- use of DS needs to be better defined
- needs better concurrency handling

If you're interested in working with Vaadin and OSGi and want a forum in which to discuss your ideas or get help feel free to join our Google Group.

12 comments:

Neil Bartlett said...

Thanks for the helpful write-up Chris.

For what it's worth, I'm quite dissatisfied with my code and would like to adopt more of a hybrid approach. The problem is that I must define an IApplicationFactory as a service, but when I need to track (i.e. reference) multiple instances of services then I end up building a mini-registry of service references versus Application instances. This is very easy to get wrong especially when concurrency is involved, whereas a DS ComponentFactory handles all this automatically.

On the other hand I think a solution is needed that does absolutely require DS. Perhaps a Blueprint user would like to get involved at this point and help to define something that is useful in both environments.

Neil Bartlett said...

Oops I mean, a solution that does NOT absolutely require DS...

Chris Brind said...

Something else I just noticed (correct me if I'm wrong Neil) is that neither Neil's or Peter's implementation deal with "production mode".

By default Vaadin runs with production mode off, which means you can append ?debug to the URL to get a debug console. My implementation allows production mode to be turned on by specifying productionMode=true as a component property of the VaadinOSGiApplicationManager class.

Of course this means production mode applies to all applications that have been registered, but it's better than nothing.

Chris Brind said...

In fact, didn't understand my own code! The properties associated to component factory are passed in to the servlet as init parameters so each app can have it's production mode specified individually.

Chris Brind said...

No, I was right the first time. Right, this code needs a good tidy up!

Peter Kriens said...

The reason I wrapped the bundle is because it was exporting too much. In a modular environment you want to minimize exports and not show implementation. I also added a component that tracks the appropriate services.

However, the problem I got stuck on, and you seem to have solved, is how to add new widgets? The big missing piece in Vaadin for me was how to have a bundle contribute widgets. Do you see an opportunity for this?

Peter Kriens

Chris Brind said...

Hi Peter,

Adding widgets isn't easy as it requires an extra step at development time to generate some static resources using GWT.

The best I've come up with (so far) is making additional extra static resources available as a fragment of the Vaadin bundle, which my "StaticRes" servlet kind of acts as a proxy for, but like I say, I think static resources should be being served by a proper web server anyway so I'm not putting too much importance on this aspect of my implementation.

The Java part of the widget however, can be wrapped directly in your own bundle(s) or imported in the usual OSGi way (if packaged correctly). I need to play with this some more in an OSGi environment though, as so far I've only used 3rd party widgets when creating a WAR file.

I understand your motivations for wrapping the bundle. The developer/deployer could re-wrap / re-package the Vaadin bundle to minimise exports if they wanted and my approach would still work. :)

What are the downsides of exporting too much in to the container at runtime (even if you don't use it at development time)?

Cheers,
Chris

John said...

Thats wonderful.

http://buy-tools.blogspot.com/

Furykid said...

If in multi tier environments statics can easily be handled by apache without the need of having several bundles like staticRes by just using mod_expires.
This would be a more transparent approach

Dr.Drane said...

Very interesting article! Will join the Google group too. (but I'm still a Vaadin n00b though)

grts

erik said...

Hi Chris,

thanks for your approach to bring together Vaadin and OSGI.
I'm using you Vaadin Addon (1.0.1) within Eclipse and Equinox, which runs fine.

Is there any reason, why the AddOn version is 1.0.1, but the repository contains 2.0.0 for quit a lot of months now?
I'm currently do some testings with v2.0.0 but with no luck. I thought, the only thing to change is the factory name, which has to look like in Peter Kriens implementation (component.factory=com.vaadin.Application/myAppName)?!

After debugging a while (I'm not much of an OSGI guy) I found out that the component gets registered
-> context.registerService(ManagedService.class.getName(), config, properties);
but the Vaadin application is never called.

Any hints or tricks?

Besides, the property isn't set correctly, because of using the full alias which is set to (/myAppName).
-> properties.put(Constants.SERVICE_PID, "com.vaadin.Application." + alias);
I've fixed it by setting
alias.substring(1).

Best regards,
Erik

erik said...

P.S.:
AppRegistration.update(Dictionary properties) is never called, but don't know why and when it should be called.