Hi Kobe,

Thanks for the detailed email. Note that the generated JARs are also Eclipse
plugins which should/could be compatible with other OSGi environments. What
OSGi environment are you actually using?

I understand the problems related to using the current thread's classloader
for any dynamic class loading. I have just changed the way the SPI selects
the classloader for dynamic loadings:
 - org.restlet.spi.Factory now has static get/setClassLoader() methods
 - by default the classloader property is set to the classloader used to
load the Factory's class, instead of the current thread
 - all dynamic class loadings (Factory implementation and connectors) are
done using this classloader set on org.restlet.spi.Factory.
 - if the loading fails, the current thread's classloader is used, then the
system's classloader.

Checked in SVN. New snapshot at:
http://www.restlet.org/downloads/current.zip 

Best regards,
Jerome  

> -----Message d'origine-----
> De : [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] De la part de Kabe
> Envoyé : samedi 28 octobre 2006 21:04
> À : [email protected]
> Objet : SPI Factory + OSGi
> 
> 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 
> 
> 
> 
> 

Reply via email to