users@jersey.java.net

Re: [Jersey] Guice injection does not support field/method injection without forcing you to bind the Resource class to the module...

From: James Strachan <james.strachan_at_gmail.com>
Date: Fri, 30 Apr 2010 17:24:39 +0100

On 30 April 2010 17:18, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>
> On Apr 30, 2010, at 5:41 PM, James Strachan wrote:
>
>> On 30 April 2010 16:36, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>>>
>>> Hi James,
>>>
>>> You beat me to it :-)
>>>
>>> I think we may be able to refine things as i got the following to work:
>>>
>>>   @Path("unbound/perrequest")
>>>   public static class InjectedPerRequestResource {
>>>
>>>       @Context UriInfo ui;
>>>
>>>       String x;
>>>
>>>       @Inject
>>>       GuiceManagedClass gmc;
>>>
>>>       public InjectedPerRequestResource(@QueryParam("x") String x) {
>>>           this.x = x;
>>>       }
>>>
>>>       @GET
>>>       @Produces("text/plain")
>>>       public String getIt() {
>>>           assertEquals("unbound/perrequest", ui.getPath());
>>>           assertEquals("x", x);
>>>
>>>           return gmc.toString();
>>>       }
>>>   }
>>>
>>> Thus we can also support the case when Jersey instantiates and Guice
>>> injects
>>> too i.e. when there are constructors with no @Inject with @Injected
>>> fields/methods.
>>
>> Great!
>>
>
> Refined.
>
> Note that when you use GuiceManagedComponentProvider there is no need to
> call the injectMembers because Guice is already instantiating.

Ah sorry - my bad. We maybe need a GuiceInjectMembersComponentProvider
that just does injector.injectMembers - letting Jersey create it.




> So i have a
> question about that. The updated code does the following:
>
>            } else if (isGuiceFieldOrMethodInjected(clazz)) {
>                // If there is a constructor with arguments then let Jersey
>                // instantiate and manage the scope, let Guice inject
>                if (hasConstructorWithArguments(clazz)) {
>                    LOGGER.info("Binding " + clazz.getName() + " to
> GuiceInjectedComponentProvider");
>                    return new GuiceInjectedComponentProvider(injector);
>                } else {
>                    // TODO should Jersey manage or Guice manage, perhaps it
>                    // depends if the component is not in the Guice NO_SCOPE
> ?
>                    ComponentScope componentScope = getComponentScope(key,
> injector);
>                    LOGGER.info("Binding " + clazz.getName() +
>                            " to GuiceManagedComponentProvider with the scope
> \"" +
>                            componentScope + "\"");
>                    return new GuiceManagedComponentProvider(injector,
> componentScope, clazz);
>                }
>            } else {
>
> The current logic will check if there is a constructor with args, if so we
> let Jersey instantiate and Guice inject. Otherwise there is no constructor
> or a no-arg constructor. In this case we are currently letting guice
> instantiate. But i wonder if for the case of Guice NO_SCOPE Jersey should
> instantiate? i.e. it may be likely in this case that Jersey-based scope
> annotations are used. I think given the other cases Jersey is managing it
> may make sense to be consistent.

Yeah. Guice is pretty strict, it'll only construct objects with a
constructor with parameters which has @Inject; so I'd say use that to
determine if Guice should instantiate it or not. Then if not, just do
the injector.injectMembers call.

BTW I wonder if we can support this too...

https://jersey.dev.java.net/issues/show_bug.cgi?id=513

so if a user constructs a sub resource by hand, let Guice inject
members? (Only if this feature is enabled I guess)


-- 
James
-------
http://macstrac.blogspot.com/
Open Source Integration
http://fusesource.com/