I'm using the Restlet library in an OSGi Execution Environment and i have found the SPI Factory to be currently unsuitable for this type of work. The reason for this is that the Factory currently uses the current thread's context ClassLoader. When using the Restlet library as a library bundle that exports the public interfaces for other classes to use, this becomes a problem because when they try to create an instance of any of the classes in the API, the Factory will try and locate the API Implementation on the class loader of the thread doing the calling, which will resolve to the bundle that is using the API and not the one that is providing it.
Now i don't have a perfect solution where the API and Implementation are separate, but if you bundle both of them together into a Restlet bundle (which i'm doing) then the Factory should resolve against its own classloader and not that of the calling thread. This works for me, and i think the change is general enough that it provides more robustness and isn't specifically a fix for any single usecase. All i have done is optional try and locate the Provider Resources via the Factory class's ClassLoader if it could not be found in the thread context ClassLoader. In the case of an OSGi bundle where the API and NRE implementation are in a single bundle, this works very well.
Do you have any thoughts on this subject? Currently the whole SPI model is not very OSGi friendly, so providing the API and the Implementation (such as NRE) in seperate bundles is not something i can see doing very easily. If you think my workaround is suitable, can you add it (or a modified version that meets your taste) in.
--- plugins/internal/org.restlet/src/org/restlet/spi/Factory.java (revision 1057)
+++ plugins/internal/org.restlet/src/org/restlet/spi/Factory.java (working copy)
@@ -66,6 +66,9 @@
/** The registered factory. */
private static Factory instance = null;
+ /** Provider resource. */
+ private static String providerResource = "META-INF/services/org.restlet.spi.Factory";
+
/**
* Returns the factory of the Restlet implementation.
* @return The factory of the Restlet implementation.
@@ -81,7 +84,12 @@
// Find the factory class name
ClassLoader cl = Thread.currentThread
().getContextClassLoader();
- URL configURL = cl.getResource("META-INF/services/org.restlet.spi.Factory");
+ URL configURL = cl.getResource(providerResource);
+ if(configURL == null)
+ {
+ cl = Factory.class.getClassLoader();
+ configURL = cl.getResource(providerResource);
+ }
if(configURL != null)
{
try
- SPI Factory + OSGi Kabe
- Re: SPI Factory + OSGi Kabe
- RE: SPI Factory + OSGi Jerome Louvel
- RE: SPI Factory + OSGi Jerome Louvel

