users@jersey.java.net

Re: [Jersey] Enhanced Guice-Jersey integration

From: Richard Wallace <rwallace1979_at_gmail.com>
Date: Tue, 23 Jun 2009 17:25:23 -0700

On Tue, Jun 23, 2009 at 2:14 AM, Paul Sandoz<Paul.Sandoz_at_sun.com> wrote:
> Hi Richard,
>
> We could modify WebApplication to have a method getProviders().
>
> Jersey holds information on all the injectable stuff registered (whether it
> be Jersey or JAX-RS specific, or added by the developer). I am wondering if
> it might be best to expose that. In fact that will be the best way to expose
> the @*Param stuff because there is logic in the Injectable instances to
> extract stuff from the HttpContext, e.g. see the source in jersey-server
> for:
>
>  com.sun.jersey.server.impl.model.parameter.QueryParamInjectableProvider
>
> I wonder if we could write code to loop through the injectables that are
> registered and explicitly bind them?
>
>  bind(c).to(cProvider).in(scope);
>
> At least for those within the singleton scope.
>

That would definitely work.

>
> It is a shame we cannot use the Matchers.any() for bind:
>
>  bind(Matchers.any()).annotatedWith(QueryParam.class).to(qProvider).in(RequestScoped.class)
>
> ?

No, the other problem with that, AFAIK, is that the annotations you
bind with have to be annotated with the Guice BindingAnnotation.

>
> I cannot recall if James got this to work with GuiceyFruit. (Also not that
> the Guice/Jersey integration supports injection onto fields of Guice-managed
> classes).
>
>
> The following:
>
>    @Provides public UriInfo uriInfo(HttpContext httpContext) {
>        return httpContext.getUriInfo();
>    }
>
> returns a request-scoped value, the httpContext is thread local but the
> values it returns are not. Is that an issue?
>

Some of the values it returns are request-scoped, such as the request
and response. I would have used some globally accessible value for
UriInfo but couldn't find a way to access it. That would certainly be
a far better alternative.

> Jersey registers thread local proxies for UriInfo etc to be injected onto
> singletons and the actual instances to be injected on per-request resources.
> It tries to optimize as much as possible to avoid the repeated use of thread
> locals when the request is available directly.
>

That's the advantage of being directly wired into the request
processing lifecycle. With a proper hook we could create a child
injector to be used for that request, and that would avoid any of the
thread local stuff. But that's the only way I can think of. Even
using the Guice servlet integration and putting that stuff in the
RequestScope would mean storing it in the ServletRequest attributes.
But the ServletRequest itself is accessed via a thread local. So, no
matter what you have to have at least a single thread local. I'm not
sure if that or creating a child injector would be more performant.
Probably depends on the number of objects that are going to be created
in a single request that will be injected with request data.

Rich

> Paul.
>
> On Jun 23, 2009, at 7:17 AM, Richard Wallace wrote:
>
>> Hey all,
>>
>> I'm working on improving the Guice-Jersey integration.  To do that I'm
>> making use of the Guice 2.0 ability to do custom injections
>>
>> <http://code.google.com/docreader/#p=google-guice&s=google-guice&t=CustomInjections>.
>> I've got most of the @Context annotations working, so you can do
>>
>> @Path("resource")
>> class MyResource {
>>   @Inject
>>   public MyResource(HttpHeaders headers, Request request,
>> SecurityContext securityContext, UriInfo uriInfo) {
>>       // ... assign them locally
>>   }
>> }
>>
>> or
>>
>> @Path("resource")
>> class MyResource {
>>   @Context HttpHeaders headers;
>>   @Context Request request
>>   @Context SecurityContext securityContext;
>>   @Context UriInfo uriInfo;
>> }
>>
>> The biggest problem I'm having is trying to figure out how to do the
>> injection for the Providers type.  I do the implementation of the
>> getMessageBodyReader and getMessageBodyWriter, but am unsure what to
>> do for getExceptionMapper and getContextResolver as they seem to only
>> be available internally to the WebApplicationImpl.
>>
>> Here's the code so far. <http://pastie.org/521175>
>>
>> I also haven't tackled how to inject the @HeaderParam, @CookieParam,
>> @MatrixParam, @QueryParam or @PathParam values.  But from what I've
>> seen so far it seems those values are all only available internally in
>> WebApplicationImpl as well.  So I'm not quite sure how I'm going to
>> get at them.
>>
>> Another unfortunate limitation is that only injectables that have
>> actual hard types like HttpHeaders, Request, etc. will be able to be
>> injected via the constructor.  The others will have to be injected
>> into the fields themselves.  This is something that James Strachan has
>> talked about patching so it may be possible in the future.
>>
>> Any ideas how I can access the fields that I need?
>>
>> Thanks,
>> Rich
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>