Also it is frustrating to see that the "Restlet API" is not really a thin API as such, where i would expect to see every single element as an Interface, but rather a set of classes that use the SPI model to delegate work to a single implementation.
In short, what i want to be able to do is create instances of various classes and use Dependency Injection to define my wiring as, and when, i need it. So for example, i want to create an instance of a connector backed by the "simple framework" implementation and use DI to provide it as a connection for my container. However the Container and all of the rest of the Restlet API classes use a delegation model for all of their work that delegates to an SPI Factory that then requires all implementations of the API classes also use the SPI model and be available at Factory creation time. This prevents me from creating connectors at runtime and adding them to the container.
1) Create Context
2) Create Container, setContext on Container
3) Create SimpleServer
4) Set/Add SimpleServer to Container
5) Create Restlet
6) Add Restlet as target in the Container (other routers/apps would exist as well)
Note that #1, #2, #3, and #5 could (and will) all be done in different class loaders and at various times in the lifecycle of the server/process.
The only thing i can think of doing right now is creating a new implementation of Factory that does not itself (although locating it would) use the SPI model. I think this is going to be a lot of work, and it feels like i'm working around something that many others will also face when they try to use the Restlet library in anything other then the monolithic way it is done now.
Can you give me some insight into the reasons you chose the SPI model, and what requirments you have/had that lead to that choice. Also, are you open to changes that would give users options to use Dependency Injection rather then SPI Delegation?
....
Kabe
On 10/28/06, Kabe <[EMAIL PROTECTED]> wrote:
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

