Migration solution for singletons in an OSGI envir

2019-07-21 14:53发布

问题:

I'm working in a Java EE 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:

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.



回答2:

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.


回答3:

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.