users@jersey.java.net

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

From: Cameron Jones <cmhjones_at_gmail.com>
Date: Wed, 30 Oct 2013 16:19:13 +0000

On Tue, Oct 29, 2013 at 6:40 PM, cowwoc <cowwoc_at_bbs.darktech.org> 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.
>
>
I don't have experience with Guice so i can't comment on the particulars,
but my experience with DI containers suggests that they all want to be the
"one container to rule them all" so none have made any attempts to
integrate.

If you consider that for a DI container to do what it is supposed to do, it
needs access to the entire set of classes for a single pass, then is it any
wonder that containers don;t provide this functionality?

It would introduce additional complexity to construction and the potential
for runtime errors which they go to extremes to avoid.


    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?
>
>
This predates HK2 as was from JAX-RS 1.0. When you consider that when it
was developed there was no DI other than XML Spring and annotations were a
new feature for JDK5 then this requirement can probably be seen as a relic
with established ground which has since been superseded by the
establishment of alternate conventions in CDI. Much the same as @Context
wouldn't exist if @Inject were available at the time.

Given that JAX-RS chose to retain it for v2 and Jersey is the RI for
JAX-RS, the likelihood of this being repealed or willfully disregarded is
unlikely.

HK2 doesn't really do anything special compared to other DI containers,
it's just a JSR-330 container.

I'm sure it's feasible for any DI container to be configured for the JAX-RS
model, but such non-trivial configuration would require a codebase for the
task.


>
> 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.
>
>
Likewise, I think its wrong to blame HK2's - it's just comparable to a
Guice/Spring DI container.

The problem is that there has been a feature regression within Jersey
between v1 and v2.

  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

>

Sure, the furthest i got is in trying similar integration with SE CDI. I
probably got about as far as you have but had to stop to get on with some
other work.

Cam