Hello,
I'm trying to use the sisu extender
in an OSGi application, but I it does not seem to work as expected. I am
using M5.
Here is my configuration. I have two
bundles, B1 and B2, where B2 depends on B1. The Sisu extender is started
before B1 and B2.
B1 bootstraps the Injector with a custom
module "someModule" as follows:
injector
= Guice.createInjector(new
WireModule(someModule, new
SpaceModule(new
BundleClassSpace(FrameworkUtil.getBundle(getClass())))));
B2 declares an additional module via
META-INF/services/com.google.inject.Module
In debug I see that SisuActivator is
starting and that is starts tracking bundles and services.
I also stepped into the code that instantiates
the module declared by B2, creates a new Injector out of it and registers
the Injector in the DefaultBeanLocator.
The OSGi console also shows that the
SisuActivator has registered a BundleInjector service on behalf of B2.
Now, if I write code in B2 that uses
the same injector instance that was created by B1, I can succesfully instantiate
objects and have their fields injected with classes that are bound by "someModule".
But if I try to do the same with objects
that would require injections that are bound by the module declared in
B2, Guice complaints that no implementation could be found.
If the objects that you are trying to instantiate were defined in B2 then you should use their defining injector as this would contain both their bindings and the necessary bindings to fetch the required dependencies from B1's injector. Think of injectors as loosely-coupled sources of bindings, with any missing (local) dependencies routed through the BeanLocator. Also how are you using the injector, are you relying on the getInstance method? The WireModule uses the Guice SPI to analyze declared bindings for missing dependencies, so if you use the getInstance method programatically then this won't be observed by the WireModule and it won't add a binding that instead delegates to the BeanLocator.
Alternatively you could always use the BeanLocator to programatically query and instantiate objects:
beanLocator.locate( Key.get( myType ) ).iterator().next().getValue()
This could be hidden behind a utility method to limit dependency of your code to Sisu-specific types.
What am I missing? I believe I should
tell the Injector to use the bean locator created by SisuActivator. How
can I do that?
To use a given locator in a new injector, add an instance binding to it when defining the bindings:
bind( DefaultBeanLocator.class ).toInstance( locator );
This will also auto-register the injector with the locator, then you just need to wrap a WireModule around your modules to add any missing links.
BTW, is your code available somewhere? I'm always interested in how people use and extend Sisu :)
GianMaria.
_______________________________________________
sisu-users mailing list
sisu-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/sisu-users