users@jersey.java.net

[Jersey] Re: Why is JSR 330 not enough?

From: cowwoc <cowwoc_at_bbs.darktech.org>
Date: Tue, 29 Oct 2013 15:40:56 -0400

     I just noticed that RESTEasy 3.0.4 support JAX-RS 2.0, Guice and
Spring.

     Take a look at
http://docs.jboss.org/resteasy/docs/3.0.4.Final/userguide/html_single/index.html#Guice1

     Section 46.1 shows them mixing @Inject with @RequestScoped. Section
46.2 shows them exposing JAX-RS types to Guice using "JaxrsModule".

     Any idea how they are able to do this? I fairly certain they ignore
the rules you quoted in section 3.1.2 (choosing the constructor with the
most parameters).

Gili

On 29/10/2013 2:40 PM, cowwoc wrote:
> Cameron,
>
>> I would guess that for Jersey 1.0 which had a custom DI container,
>> the intent was to integrate with any other DI, but for Jersey 2 as it
>> defers responsibility to HK2 it would seem that it's HK2's
>> responsibility to integrate with other DI containers.
>
> I understand why Jersey chose to delegate DI integration to HK2
> (separation of concerns) but it turns out that was based on an
> incorrect assumption. It turns out that HK2 cannot share
> configuration/injection responsibility with 3rd-party DIs. Guice, in
> particular, does not support delegating injection for unknown types.
> This feature was requested 5 years ago but ultimately rejected due to
> insufficient demand and the extra complexity it would introduce:
> https://code.google.com/p/google-guice/issues/detail?id=49. I am
> trying to have it reintroduced, but I am fighting an uphill battle.
>
> At the same time, you bring up a good point:
>
>> Also, JAX-RS has some of it's own non-standard DI rules which
>> wouldn't be definable without customizations to injection processing.
>> This would also need to be defined per-container.
>>
>> For example, for resource constructors (JAX-RS 3.1.2 Constructors):
>>
>> "However, depending on the resource class lifecycle and concurrency,
>> per-request information may not make sense in a constructor. If more
>> than one public constructor is suitable then an implementation MUST
>> use the one with the most parameters. Choosing amongst suitable
>> constructors with the same number of parameters is implementation
>> specific, implementations SHOULD generate a warning about such
>> ambiguity."
>>
>> This isn't defined in JSR-330 and in JSR-299 multiple constructors
>> would throw an error at runtime.
>
> This is a hard requirement to meet. I am surprised that the JAX-RS
> spec mandates this (it seems out of scope to me). It virtually assures
> that no DI except HK2 would work for JAX-RS. Out of curiosity, does
> the Jersey-Spring plugin meet this requirement?
>
>>
>> At what point does JAX-RS stop and the generic definition of
>> DI containers begin?
>>
>>
>> Jersey 1.0 did a pretty good job. We should pick up where it
>> left off and take it to the next level. Depending on HK2 directly
>> shifts the burden from a small number of Jersey committers to a
>> large number of end-users. Guice/Spring weren't designed to for
>> integration into 3rd-party DI frameworks. Their design (quite
>> reasonably) assumes the use of one DI framework at a time. I have
>> tried integrating Guice and HK2 for weeks now and it doesn't look
>> like it's technically possible.
>>
>>
>> Heh, HK2 wasn't designed for integration with 3rd party DI frameworks
>> either :)
>
> It gained that requirement the moment Jersey delegating DI
> integration to it. Guice/Spring are independent libraries that have
> nothing to do with JAX-RS. The close coupling of Jersey and HK2 might
> be nice for Jersey but it isn't reasonable to expect the same from
> general DI frameworks.
>
>> Are you asking more of HK2 than you expect of Guice/Spring?
>
> Not at all. I am expecting HK2 to be one of many implementations
> that may be used with Jersey. I expect only one DI implementation to
> be active at a time.
>
>> Isn't what you really want a (C)DI abstraction layer?
>
> I am not very familiar with CDI so I can't really comment. Last
> time I scanned through it it looked overly complex.
>
>> I'm guessing that mixing DI containers is probably a bad idea, hence
>> the technical difficulties. I've not resolved this either.
>
> I agree. Which is why I'm saying we should only be using one DI
> implementation at a time, but allow users to decide which
> implementation they chose to use.
>
>
>> The problem is that JSR-330 doesn't define enough. It is a set of
>> reusable annotations, with no specification of how any system using
>> them should be implemented:
>>
>> http://atinject.googlecode.com/svn/trunk/javadoc/javax/inject/package-summary.html
>>
>> "*This package provides dependency injection annotations that enable
>> portable classes*, but it leaves external dependency configuration up
>> to the injector implementation."
>>
>> "Injector implementations can take many forms. An injector could
>> configure itself using XML, annotations, a DSL (domain-specific
>> language), or even plain Java code. An injector could rely on
>> reflection or code generation. An injector that uses compile-time
>> code generation may not even have its own run time representation.
>> Other injectors may not be able to generate code at all, neither at
>> compile nor run time. A "container", for some definition, can be an
>> injector, but this package specification aims to minimize
>> restrictions on injector implementations."
>>
>> I can see that it's feasible to do multiple Jersey modules with one
>> for each DI container, much the same as a lot of other extension
>> modules work.
>>
>> Either that or a new DI abstraction which had the features Jersey
>> requires without the bloat of CDI. I would guess that a new
>> abstraction which fulfills an implementation's requirements is harder
>> to achieve and those interested in more DI abstraction have probably
>> already invested in the CDI specification.
>
> I can't speak for others, but I'm simply interested in getting the
> same functionality I had in Jersey 1.0. I want to be able to use
> either: only HK2, only Guice or only Spring at a time. I also need to
> be able to do this outside a JavaEE container. I am running Jetty
> inside a simple JavaSE application and I really appreciate how light
> this solution feels.
>
> Another difference I wanted to point out:
>
> * I expect Jersey to speak to the DI implementation through the
> abstraction layer, but...
> * Users should speak to the DI implementation directly.
>
> The point I want to make is that users don't have to learn yet
> another DI framework. The only thing that's new is having to register
> a DI framework once at startup. Past that point they should be able to
> use the native HK2, Guice and Spring constructs they are used to.
>
> Gili