Monday, May 21, 2007

Spring-OSGi hello world application

The problem

OK, I need dependency injection in my cool Eclipse/OSGi applications. I plan to wrap actual Platform{UI].get*(..) method within Spring-OSGi service beans (that is, Spring beans exported as OSGi services). I want my n-tier applications to communicate through services. Ad I want them to add new features and update existing ones on the fly.

So I downloaded the actual sources, built them and copied all the jars in a directory which I made as additional extension to the JDT. This is good for me since I can play with Spring-OSGi from within eclipse without bothering with maven stuff (maven-eclipse integration is not helpful here).

I created a sample "Hello world" bundle which publishes the spring beans (one implementing a salute in Italian, the other in plain English) and an OSGi Greeter service that could be user by other services.

Spring-OSGi hints

A few things must be remembered:
  • You can have bundle-scoped beans (they are only visible within the application context associated to that bundle and no else!)
  • You can publish some beans as OSGi services (so making them available to the other bundles through the usual OSGi mechanisms, such as the service trackers).
  • You must put your XML files declaring the application context under META-INF/spring directory in your project classpath: *.xml files will be loaded automatically by the Spring Extender service.
  • The Spring Extender bundle must be activated as early as possible in your application's start-up and you cannot use the beans in the BundleActivator.{start,stop} lifecycle methods (the extender will take sometime to load the xmls and publish beans/services)
Keeping this in mind, we have all the usual Spring and OSGi concepts merged together :)

A last question: what is the minimum set of bundle for such a minimal application (no databases, no GUI, just plain OSGi+Spring+Console output) ? Here they are:

id State Bundle
0 ACTIVE system.bundle_3.2.2.R32x_v20070118
163 ACTIVE org.aopalliance_1.0.0
164 ACTIVE org.apache.commons_logging_1.0.4.v200608011657
168 ACTIVE org.aspectj.runtime_1.5.4.200701151324
169 ACTIVE org.aspectj.weaver_1.5.4.200701151324
203 ACTIVE org.springframework.osgi.backport-util-concurrent_3.0.0.SNAPSHOT
208 ACTIVE org.springframework.osgi.spring-aop_2.0.5.osgi_m3_SNAPSHOT
209 ACTIVE org.springframework.osgi.spring-beans_2.0.5.osgi_m3_SNAPSHOT
210 ACTIVE org.springframework.osgi.spring-context_2.0.5.osgi_m3_SNAPSHOT
211 ACTIVE org.springframework.osgi.spring-core_2.0.5.osgi_m3_SNAPSHOT
212 ACTIVE org.springframework.osgi.spring-osgi-core_1.0.0.m3_SNAPSHOT
213 ACTIVE org.springframework.osgi.spring-osgi-extender_1.0.0.m3_SNAPSHOT
214 ACTIVE org.springframework.osgi.spring-osgi-io_1.0.0.m3_SNAPSHOT
219 ACTIVE org.springframework.osgi.spring-osgi-mock_1.0.0.m3_SNAPSHOT

Obviously more will be needed for transactions and persistence frameworks. But for now I'm satisfied since I've breached within this new world!

Next steps
  • testing (unit and integration practices)
  • smoothing out the code and find the right time when to use the published services (for now I just use the service in a addingService() implemented in a custom service tracker of mine.