Hi Christian,
On 1/4/19 1:36 AM, Christian Kaltepoth
wrote:
The problem you are describing seems to be very
specific to the native JAX-RS dependency injection via
@Context, which we are planning to deprecate soon in favor of
CDI. And CDI handles this situation much better, because it
automatically injects proxies.
But would the CDI proxy be aware of the difference between
"servlet application scope" and "JAX-RS application scope"? That
seems to be the source of our problem. Quoting myself from
earlier,
The complication arises when CDI is
activated. With respect to CDI, the
application scope of FooReader means that a single instance of
FooReader
will be created for the lifetime of the WAR, and injection
into the
application field will occur only once. Whichever value is
injected will
be correct some of the time and incorrect some of the time.
Actually, I think it's worth mentioning that the JAX-RS spec is a
little murky on this subject. When it says, "By default a single
instance of each provider class is instantiated for each JAX-RS
application", it seems to be indirectly defining "JAX-RS
application scope" as being the time during which a resource from
a particular Application is running, which would be
different than the servlet notion of application scope. In the
discussion in https://issues.jboss.org/browse/RESTEASY-1709
"Same JAX-RS Application instance injected across applications",
someone questioned whether it was even legal to have two
Applications in a single WAR. It does seem to be legal, but it
would be good if the spec were clearer.
Maybe that should be clarified first.
Also, it feels weird to add an interface which is
basically the same as the existing Application class. This
doesn't bring any benefit for the user from an API
perspective. It looks like it just addresses an
implementation concern.
Yeah, fair enough. Really, I'm thinking that Application should
have been defined as an interface in the first place, which would
make it consistent with all of the other @Context injectible
types. Clearly, it's too late to turn Application into an
interface, so I was just thinking of a possible solution.
And actually using Javassist in these situations is very
common. Therefore, I'm unsure if we should really address
this on the spec level.
Ok, I cant argue against that. It's just that all of our @Context
injections are done with java proxies, and then there's a
completely differently treatment for Applications. Like Warren
Zevon said, "It ain't that pretty at all".
-Ron
This
issue came up in the context of
https://issues.jboss.org/browse/RESTEASY-1709
"Same JAX-RS Application
instance injected across applications".
Consider a WAR with two Application classes, Application1 and
Application2, both derived from ApplicationAbstract and both
of which
reference a provider such as
@Provider
public class FooReader implements MessageBodyReader<Foo>
{
@Context
ApplicationAbstract application;
...
}
The value of application should be either Application1 or
Application2,
depending on the resource being called. In accordance with
Section 4.1
"Lifecycle and Environment" of the JAX-RS 2.1 spec, which
says, "By
default a single instance of each provider class is
instantiated for
each JAX-RS application", RESTEasy creates two copies of
FooReader at
initialization time and injects the appropriate Application.
The complication arises when CDI is activated. With respect to
CDI, the
application scope of FooReader means that a single instance of
FooReader
will be created for the lifetime of the WAR, and injection
into the
application field will occur only once. Whichever value is
injected will
be correct some of the time and incorrect some of the time.
The natural solution would be to inject a proxy which
retrieves the
currently relevant Application, but, unfortunately, unlike all
of the
other @Context injectable types, Application is a class
instead of an
interface. In RESTEasy, we worked around that by using
Javassist, which
is able to create proxies for classes. It would be preferable,
though,
if it were possible to use pure Java proxies.
We propose something like
public interface ApplicationInt {
public Set<Class<?>> getClasses();
public Set<Object> getSingletons();
public Map<String, Object> getProperties();
}
public class Application implements ApplicationInt {
...
}
-Ron Sigal
_______________________________________________
jaxrs-dev mailing list
jaxrs-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or
unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jaxrs-dev
--
_______________________________________________
jaxrs-dev mailing list
jaxrs-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/jaxrs-dev
--
My company's smarter than your company (unless you work for Red Hat)
|