dev@jersey.java.net

Re: [Jersey] GuiceComponentProviderFactory seems to eagerly support resources that are not explicitly bound in the given Injector.

From: Jae Lee <jlee119_at_gmail.com>
Date: Wed, 23 Sep 2009 13:58:57 +0100

Hi Paul,
Yes, one specific use case of using multiple independent injectors are when
you've got two independent resources with dependency to the common interface
(in my example that will be Message), which then you might want each
resource to depend on different implementation of the common interface (in
my example that will be HelloWorld and HelloMe)

I have to say the use case mentioned above is hypothetical, and I made it up
to demonstrate the current behaviour.

A more general use case of using multiple injectors that I'm really coming
from would be when you want clear separation between group of resources
(vertical slice of application) and thus you want to manage dependencies for
those resources independently.

With my understanding, it's OK to turn off the implicit instantiation,
because those root level classes that Jersey recognises are all explicitly
bound in the given Injector anyway... then actual instantiation will be done
by Guice which then might instantiate some implicitly bound dependencies.

It's just somewhat weird to see all Injectors other than the first one are
ignored by ResourceComponentProvider, and totally different Injector is used
to construct Resource that wasn't bound within.

J

On Wed, Sep 23, 2009 at 1:26 PM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:

> Hi,
>
> What is happening is the implicit instantiation is kicking in, namely Guice
> instantiates and Jersey manages.
>
> See JavaDoc (last para):
>
>
> https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/contribs/jersey-guice/com/sun/jersey/guice/spi/container/servlet/package-summary.html
>
>
> I did not realize there would be a use case of two independent injectors
> being registered.
>
> Do you know if it is possible to use some form of injector aggregation in
> Guice? e.g. an injector that aggregates injector1 or injector2 ?
>
> The GuiceComponentProviderFactory does support deferral to parent injectors
> so if you make, say, injector2 a parent of injector1 it should work.
>
>
> Otherwise if this is not appropriate we will require a feature to turn off
> the implicit instantiation.
>
> Paul.
>
>
> On Sep 23, 2009, at 2:12 AM, Jae Lee wrote:
>
> Hi all,
>>
>> I've came across the problem with GuiceComponentProviderFactory, when
>> there are multiple of those registered in IoCResourceFactory.
>> GuiceComponentProviderFactory will always support any resource classes that
>> are not explicitly bound in the Injector that the ProviderFactory is
>> constructed with, resulting in the first GuiceComponentProviderFactory will
>> always be used to construct any resource.
>>
>> I've got two resources that are managed by two different Injectors, and
>> thus two different GuiceComponentProviderFactories. However when
>> IoCResourceFactory is constructed with those two
>> GuiceComponentProviderFactories it always use the first one to construct any
>> resources. And the test fails...
>>
>> any thought?
>>
>> public class GuiceComponentProviderFactoryForMultipleInjectorsTest {
>> public static interface Message {}
>>
>> public static class HelloWorld implements Message {}
>>
>> public static class HelloMe implements Message {}
>>
>> @Path("mail/world")
>> public static class MailWorld {
>> private Message message;
>>
>> @Inject
>> public MailWorld(Message message) {
>> this.message = message;
>> }
>> }
>>
>> @Path("mail/me")
>> public static class MailMe {
>> private Message message;
>>
>> @Inject
>> public MailMe(Message message) {
>> this.message = message;
>> }
>> }
>>
>> private ResourceFactory buildResourceFactory(Injector... injectors) {
>> ResourceConfig resourceConfig = new DefaultResourceConfig();
>>
>> List<IoCComponentProviderFactory> factories = new
>> ArrayList<IoCComponentProviderFactory>();
>> for(Injector injector : injectors) {
>> factories.add(new GuiceComponentProviderFactory(resourceConfig,
>> injector));
>> }
>>
>> return new IoCResourceFactory(resourceConfig, new
>> ServerInjectableProviderFactory(), factories);
>> }
>>
>> @Test
>> public void shouldSupportMultipleInjectors() {
>> Injector injector1 = Guice.createInjector(new AbstractModule(){
>> @Override
>> protected void configure() {
>> bind(Message.class).to(HelloWorld.class);
>> bind(MailWorld.class);
>> }
>> });
>>
>> Injector injector2 = Guice.createInjector(new AbstractModule(){
>> @Override
>> protected void configure() {
>> bind(Message.class).to(HelloMe.class);
>> bind(MailMe.class);
>> }
>> });
>>
>> HttpContext httpContext = mock(HttpContext.class);
>> ResourceComponentProvider componentProvider =
>> buildResourceFactory(injector1,
>> injector2).getComponentProvider(MailWorld.class);
>> componentProvider.init(new AbstractResource(MailWorld.class));
>>
>>
>> assertThat(((MailWorld)componentProvider.getInstance(httpContext)).message,
>> is(HelloWorld.class));
>>
>> componentProvider = buildResourceFactory(injector1,
>> injector2).getComponentProvider(MailMe.class);
>> componentProvider.init(new AbstractResource(MailMe.class));
>>
>>
>> assertThat(((MailWorld)componentProvider.getInstance(httpContext)).message,
>> is(HelloMe.class));
>> }
>> }
>>
>>
>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: dev-help_at_jersey.dev.java.net
>
>