views:

418

answers:

3

I'm working in a JEE Environment in which each application is in a war file of its own. In the WEB-INF/lib of each application war file there is a common jar that is shared by all applications. This common jar contains several Singletons which are accessed from many points in the code. Because of the war-file boundaries each application has its own instances of the Singletons. Which is how we operate today, since we want to configure some of the singletons differently in each application.

Now we are moving towards an OSGi environment, where this solution will no longer work since each bundle has its own class loader, so if I try to access MySingleton which resides in bundle "common.jar" from bundle "appA.jar" or from bundle "appB.jar" I will get the same instance.

Remember I "want" a different instance of a singleton per bundle. (as ironic as it sounds)

Now I realize the ideal solution would be to fix the code to not rely on those singletons, however due to a tight schedule I was wondering if you guys can suggest some sort of a migration solution that would allow me to use bundle-wide singletons so each of them could be configured per bundle.

+1  A: 

I can think of a few options:

  1. Include a copy of all the classes in common.jar directly in the WAR bundle.
  2. Nest common.jar in each WAR bundle, then modify the bundle class path in MANIFEST.MF to include the nested jar: Bundle-ClassPath: ., common.jar
  3. Modify the singleton to use OSGi services, and use a ServiceFactory to ensure that each requesting bundle receives its own instance of that service. You'll need to cache the service instance (don't get/use/unget) to avoid getting a new instance on each access.
bkail
Regarding option 2, does OSGi work with war-files?I thought OSGi bundles are simply jar files.
There's nothing in the OSGi spec that limits a bundle to an instance of a JAR file. See Spring DM and OPS4J for examples of WAR support.
hbunny
+2  A: 

Your singleton will be a service in OSGi.

Then you need to create a ManagedServiceFactory (see for instance this article) responsible of registering different instances of this service; each service will be registered with different properties (f.i. application="appA" and application="appB")

After that, you will access the right service from any application doing a normal service lookup specifying the correct properties.

Filippo Diotalevi
Or hack the getter of the singleton to take an arbitrary key (such as the bundle context) that allows you to return a singleton per key.
hbunny
+1  A: 

Singletons indeed map to services. If the applications (appA, appB) are actually bundles, then implement your service as a ServiceFactory. This will allow you to return a separate instance for every invoking bundle automatically. That will be easier than a ManagedServiceFactory (which needs explicit configuration for each instance) or hacking getters.

Marcel Offermans