Reputation: 21356
PicoContainer seems to indicate that it supports JSR-330 @Inject
and @Named
. (No, this other question doesn't seem to help, as it doesn't address the fact that the PicoContainer site says that some support for JSR-330 has been added.)
I add something to the container like this:
container.addComponent(Foo.class);
container.addComponent("myBar", new MySpecialBar());
container.addComponent("decoy", new SomeOtherBar());
I mark constructor parameters with @Named
:
public class Foo(@Named("myBar") Bar bar) { ...
But when I try to get a Foo
instance, PicoContainer complains that it has too many Bar
instances to choose from.
Question 1: How do I get PicoContainer to work with @Named
for constructor injection?
Then I try to use field injection inside Foo.java
:
@Inject
@Named("myBar")
Bar bar;
That doesn't work either.
Question 2: How do I get PicoContainer to work with @Inject
and @Named
for constructor injection?
Or is the PicoContainer news page wrong, and there simply isn't any PicoContainer 2.x support for JSR-330 at all?
Upvotes: 0
Views: 582
Reputation: 1256
Looks like I'm the only person on stackoverflow who answers pico questions but I'm not the pico team member, so for the final answer you may need to visit their mailing list :)
While looking at the framework sources (2.10 ... 2.15) I can't see any support for javax.inject.Named and @Inject is supported as pico annotation, not as javax.inject.Inject
As for solving ambiguous dependencies pico offers several ways: http://picocontainer.codehaus.org/ambiguous-injectable-help.html (using parameter names, IMHO a bit weird but it may be ok for you) and http://picocontainer.codehaus.org/disambiguation.html (using Parameter object -- not bad, but verbose, another one using binding annotations as in Guice, IMHO even more weird) and if none of the above suits you, you can take Parameter object idea and make you little disambiguation adapter, with IMHO cleaner look
class DisambiguationAdapter<T> extends AbstractAdapter<T> {
private final Object[] params;
public DisambiguationAdapter(Object componentKey, Class<T> componentImplementation, Object... params) {
super(componentKey, componentImplementation);
this.params = params;
}
// the idea is to make child container that overrides ambiguos deps using the parameters hints
@Override
public T getComponentInstance(PicoContainer container, Type into) throws PicoCompositionException {
MutablePicoContainer tmpContainer = new DefaultPicoContainer(container);
tmpContainer.addComponent(getComponentKey(), getComponentImplementation());
for (Object param : params) {
tmpContainer.addComponent(container.getComponent(param));
}
T instance = tmpContainer.getComponent(getComponentImplementation());
tmpContainer.dispose();
return instance;
}
@Override
public void verify(PicoContainer container) throws PicoCompositionException {
for (Object param : params) {
if(container.getComponent(param) == null) {
throw new PicoCompositionException("Can't resolve param-key=" + param + " to satisfy dependencies for " + getDescriptor());
}
}
}
@Override
public String getDescriptor() {
return getComponentImplementation().getCanonicalName();
}
}
then you declare this method to add components that require ambiguous deps:
public void register(Object key, Class<?> component, Object... params) {
container.addAdapter(new DisambiguationAdapter<>(key, component, params));
}
and then you use it like this:
// constructor for some class requiring ambig deps
public ProfileFinder(/* ambig param */ ProfileDao dao, /* any other params */ Param1 param1, Param1 param2)......
// container composition
// hint key, impl class
c.addComponent(ProfileDaoSelector.SLAVE, jdbi.onDemand(ProfileDao.class));
c.addComponent(ProfileDaoSelector.MASTER, jdbiMaster.onDemand(ProfileDao.class));
// impl class, hint keys array
c.register(ProfileService.class, new Object[] {ProfileDaoSelector.MASTER});
c.register(ProfileFinder.class, new Object[] {ProfileDaoSelector.SLAVE});
Upvotes: 1