users@jersey.java.net

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

From: Cameron Jones <cmhjones_at_gmail.com>
Date: Tue, 29 Oct 2013 15:21:55 +0000

On Mon, Oct 28, 2013 at 11:24 PM, cowwoc <cowwoc_at_bbs.darktech.org> wrote:

> On 28/10/2013 1:36 PM, Cameron Jones wrote:
>
>> JSR-330 is a bit light-weight and doesn't specify how applications are
>> configured. This would mean that Jersey would have to integrate with every
>> DI container to configure itself.
>>
>
> Jersey 1.0 exposed a DI abstraction layer for functionality it
> depended upon. Guice and Spring then implemented those interfaces, and
> everything worked well (this was before JSR 330 even existed). Jersey 1.0
> never needed to "configure" the DI. It just exposed providers for the
> built-in types (like UriInfo) and the DI implementation used them to inject
> those types.
>
>
Jersey 1.0 essentially provided it's own DI container and the hooks into it
for integration with other containers, but it did not require these to
operate and was a standalone product.

The changes in Jersey 2 has been to remove the custom DI container and
replace it with HK2, as a library.

With JEE servers now providing DI features,it makes sense to use common
libraries to avoid duplication of functionality.

There is not much difference in the approach, other than the complexity in
the deployment environment and that every DI container wants to 'take
control' of the construction phase.

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.



> 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.
>>
>
> What do you mean? Can you give an example?
>
>
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.



> 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 :)

Are you asking more of HK2 than you expect of Guice/Spring?

Isn't what you really want a (C)DI abstraction layer?

I'm guessing that mixing DI containers is probably a bad idea, hence the
technical difficulties. I've not resolved this either.


>
>
> JAX-RS DI was discussed by the JSR expert group, and they found the
>> options available to either be lacking in features (JSR-330) or overkill
>> with redundant features (JSR-299), see slide 59:
>>
>> http://www.slideshare.net/**arungupta1/jax-rs20<http://www.slideshare.net/arungupta1/jax-rs20>
>>
>
> I advocate using as much of JSR330 as possible, and filling the
> remaining gaps using a thin abstraction layer. Then we implement the DI
> interface once per DI framework and we're done. Jersey codes against a DI
> abstraction. Users code against Guice/Spring directly (lower learning
> curve!). Everyone is happy. We would also be able to leverage the existing
> Spring/Guice implementations from Jersey 1.0.
>
> Gili
>

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.

Thanks,
Cameron Jones