On Feb 29, 2008, at 6:51 PM, Richard Wallace wrote:
> Hello,
>
> I just updated to Jersey 0.6 and have a few thanks/gripes/questions.
>
> First of all, good job on getting rid of the requirement to put
> services in the META-INF/services/
> whatever.service.interface.your.implementing. Much better.
>
> Now for the gripe. I love that the ComponentProvider is
> responsible for instantiating everything, including
> MessageBodyReaders/Writers. The problem I have now is that my
> preferred method of injection is via constructors, but this causes
> Jersey to try and figure out what to inject and call the getInstance
> () method that takes a constructor and it's (resolved by Jersey)
> parameters. So what I've wound up having to do is toss the
> constructor and parameters in my GuiceComponentProvider and just
> return injector.getInstance(ctor.getDefiningClass()). Of course
> that means that Jersey params can't be injected into the
> constructor which leads to my question...
>
This area of constructors and who chooses what is a tricky area we
have not quite fully resolved. For portability we do require a rule
for which constructor is used. Jersey does a fair bit of work to get
the instances of the constructor parameters e.g. @*Param (@QueryParam
("q") List<Integer> v, or @DefaultValue("10") @QueryParam("q")
BigInteger v) in addition to @Context stuff that would be a fair bit
of work to implement.
Perhaps an example in Guice would help me as i don't understand when
you say "my preferred method of injection is via constructors" why
you cannot use the constructor Jersey chooses. Is it because Guice
gets to decide which constructor to use?
> I'd like to be able to have Guice inject JSR311 parameters, like
> @Context and @HttpHeaders and such. I'm pretty sure I can do it,
> it's actually quite easy with Guice I just need to implement the
> providers. The providers will just return the ThreadLocals that
> Jersey uses. The problem I have is that I have no access to those
> ThreadLocals. They're all declared as private in the
> WebApplicationImpl and their is no API to access them from
> ComponentProviders. From what I can tell, all I really need is
> access to the ThreadLocalHttpContext and from there I should be
> able to get everything I need for injection. Is that correct? How
> can I get access to this ThreadLocal?
>
I could add a method WebApplication.getThreadLocalHttpContext() but
first i would like to understand more about the issue. It may be we
need something like "given a list of types, from say a constructor,
get me the instances of those types Jersey knows about in the context
of the current request" then you would have not to re-implement a
whole bunch of logic.
> Thanks,
> Rich
>
> P.S. One more gripe for the road. I've had to add
> @SuppressWarnings("unchecked") annotations to my
> GuiceComponentProvider for the getInstance() methods because
> they're not generified. Could we get this fixed? I mean, all that
> needs to be done is to do something like declare them as
>
> <T> T getInstance(Scope scope, Class<T> type)
>
> and
>
> <T> T getInstance(Scope scope, Constructor<T> ctor, Object[] args)
>
I will make that change on Monday.
> I've noticed in going through the code that there are many other
> places where raw types are used in Jersey instead of generified types.
Could you point to other areas?
> Any reason for this?
>
Most likely laziness on my part.
Paul.