users@jersey.java.net

Re: [Jersey] Simplifying Jersey life-cycle and IoC integration

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 27 Oct 2008 14:19:05 +0100

On Oct 27, 2008, at 2:08 PM, Martin Grotzke wrote:

> On Mon, 2008-10-27 at 12:40 +0100, Paul Sandoz wrote:
>> On Oct 27, 2008, at 12:14 PM, Martin Grotzke wrote:
>>
>>> Hi Paul,
>>>
>>> sounds good to me. Do you plan to change the spring-stuff together
>>> with
>>> the api/interface changes, or can I help in this area?
>>>
>>
>> Yes, just committed the code :-) no test failures.
> Great! I'll have a look at your implementation this evening - to
> keep in
> touch :)
>
>
>> I don't recall if
>> we have any tests for AOP-based stuff, if we do not it might be
>> useful
>> to add something.
> IIRC we don't have any test related to this, as this is a feature of
> spring and we shouldn't need to test this.
>

But we do require to get the injectable instance, so there is some
aspects of the code to test:

     private static Object getInjectableInstance(Object o) {
         if (AopUtils.isAopProxy(o)) {
             final Advised aopResource = (Advised)o;
             try {
                 return aopResource.getTargetSource().getTarget();
             } catch (Exception e) {
                 LOGGER.log(Level.SEVERE, "Could not get target object
from proxy.", e);
                 throw new RuntimeException("Could not get target
object from proxy.", e);
             }
         } else {
             return o;
         }
     }

to make sure injection happens correctly on singleton and per-request
AOP'ed resources.


> However, we could add a sample that shows how spring-AOP can be used
> (using the ResourceContext to get subresource instances). As soon as I
> find the time I can do this.
>

Great! i think it can be part of the existing spring example.


>
>>
>> One area that could be improved is this:
>>
>> if (springContext.isSingleton(beanName)) {
>> return new
>> SpringManagedComponentProvider(ComponentScope.Singleton, beanName,
>> c);
>> } else if (springContext.isPrototype(beanName)) {
>> return new
>> SpringManagedComponentProvider(ComponentScope.PerRequest, beanName,
>> c);
>> } else {
>> return new
>> SpringManagedComponentProvider(ComponentScope.Undefined, beanName,
>> c);
>> }
>>
>> For the ComponentScope.PerRequest we could support Spring "prototype"
>> or the Spring "per-request" scope. I seem to recall that you
>> defined a
>> mapping from Jersey scopes and Spring scopes that allowed for the
>> "per-
>> request" inclusion. Was that right?
> Correct, it looked like this:
>
> enum SupportedSpringScopes {
>
> /**
> * Maps the spring scope "singleton" to the {_at_link
> SingletonProvider}
> */
> SINGLETON("singleton", SingletonProvider.class),
> /**
> * Maps the spring scope "prototype" to the {_at_link
> PerRequestProvider}
> */
> PROTOTYPE("prototype", PerRequestProvider.class),
> /**
> * Maps the spring scope "request" to the {_at_link
> PerRequestProvider}
> */
> REQUEST("request", PerRequestProvider.class),
> /**
> * Maps the spring scope "session" to the {_at_link
> PerSessionProvider}
> */
> SESSION("session", PerSessionProvider.class);
>
> private final String _springScope;
>
> private final Class<? extends ResourceProvider>
> _resourceProviderClass;
>
> private SupportedSpringScopes(String springScope,
> Class<? extends ResourceProvider>
> resourceProviderClass) {
> _springScope = springScope;
> _resourceProviderClass = resourceProviderClass;
> }
>
> /**
> * Get the resource provider.
> *
> * @return the resource provider.
> */
> public Class<? extends ResourceProvider>
> getResourceProviderClass() {
> return _resourceProviderClass;
> }
>
> /**
> * Get the Spring scope.
> *
> * @return the Spring scope.
> */
> public String getSpringScope() {
> return _springScope;
> }
>
> /**
> * Get the default support scope.
> *
> * @return the default supported scope.
> */
> public static SupportedSpringScopes defaultSpringScope() {
> return SINGLETON;
> }
>
> /**
> * Select the matching supported scope item.
> *
> * @param springScope the Spring scope
> *
> * @return the matching supported scope, or <code>null</code>
> if
> * the scope could not be matched.
> */
> public static SupportedSpringScopes valueOfSpringScope(String
> springScope) {
> for (SupportedSpringScopes scope : values()) {
> if (scope.getSpringScope().equals(springScope)) {
> return scope;
> }
> }
> return null;
> }
>
> }
>
> It could be used like this:
>
> final Scope scope = resourceClass.getAnnotation(Scope.class);
> if (scope != null) {
> final SupportedSpringScopes springScope =
> SupportedSpringScopes.valueOfSpringScope(scope.value());
> if (springScope != null) {
> resourceProviderClass = springScope.getResourceProviderClass();
> } else {
> throw new RuntimeException("No jersey lifecycle annotation
> specified on" +
> " resource class " + resourceClass.getName() +
> " and also no valid spring scope (valid scopes: " +
> SupportedSpringScopes.getSpringScopesAsCSV() + ")");
> }
> } else {
> resourceProviderClass =
> SupportedSpringScopes.defaultSpringScope().getResourceProviderClass();
> }
>

Ah, that was different to what i expected. We need a programatic way
to get access to the scope of a spring bean independently of whether
the bean is Spring auto-wiring or not. I will have a closer look at
the Spring API.

Paul.