Supporting ServiceLoader in Standalone Mode
bosschaert Jan 11, 2011 9:21 AMWhile I was implementing URL Handler support as per the OSGi core specification I did this by plugging into the ModularURLStreamHandlerFactory that is provided by JBoss Modules.
This works when running inside AS7 (but: MODULES-44 and MODULES-66) but there are a number of issues that still need to be worked out for standalone mode. My commit (https://github.com/jbosgi/jbosgi-framework/commit/01e9741c296f4849bd48b091c5e53cd5cf6f56af) contains a number of hacks for standalone mode simply to get it working, but I'm hoping that we find a better solution for this.
Some of the things that I had to work through...
Making the System Module Loader aware of the OSGi Framework Module
The ModularURLStreamHandlerFactory looks up modules by calling Module.getSystemModuleLoader().loadModule(identifier). When running in standalone mode the framework module loader is the OSGi Module Loader. However this module loader isn't known to the System Module loader. At the following location I put in a hack to set the OSGi Module Loader in the System Module Loader:
https://github.com/jbosgi/jbosgi-framework/commit/01e9741c296f4849bd48b091c5e53cd5cf6f56af#L10R77
This is clearly not the way to go. An alternative might be to set the System Property "system.module.loader" to the OSGiModuleLoader class name before booting the system. This works to a certain degree, but since the instance is stored in a static final SystemModuleLoaderHolder.INSTANCE variable, it can only be initialized once. This is a problem for the unit tests in JBoss OSGi as they initialize the system repeatedly (e.g. to test various initialization options). This can probably be worked around by putting a holder in there instead of the real instance, but that's a workaround...
Another potential problem with the system property approach is that the system module loader instance has to be created by JBoss Modules using a noarg constructor, which limits the initialization options. Both issues could be resolved by providing an API to set and reset the System Module Loader (MODULES-67).
Using the ServiceLoader with the classloaders as set up in Standalone Mode
The ModularURLStreamHandlerFactory at some point uses the java.util.ServiceLoader on the OSGi Framework module classloader to load the resource META-INF/services/java.net.URLStreamHandlerFactory. It then loads the classes found in there (i.e. org.jboss.osgi.framework.plugin.internal.URLHandlerFactory) using that classloader and instantiates them. This is isolated in the FrameworkServiceLoaderTestCase. This didn't work in standalone mode. To make this work I had to export META-INF/services and org.jboss.osgi.framework.plugin.internal locations from the framework. This is done in SystemPackagesPluginImpl.getInternalFrameworkPackages() together with changes in FrameworkLocalLoader, SystemLocalLoader and ModuleManagerPlugin which I'm not very happy with. Hopefully there is a cleaner solution to this. None of these changes are needed when running in AS7.
org.jboss.osgi.framework.plugin.internal