[ 
https://issues.apache.org/jira/browse/CXF-2828?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Daniel Kulp reassigned CXF-2828:
--------------------------------

    Assignee: Daniel Kulp

> JSR 250 @Resource annotation on field does not work for proxied service 
> implementations
> ---------------------------------------------------------------------------------------
>
>                 Key: CXF-2828
>                 URL: https://issues.apache.org/jira/browse/CXF-2828
>             Project: CXF
>          Issue Type: Bug
>          Components: JAX-WS Runtime
>    Affects Versions: 2.2.8
>            Reporter: Oliver Geisser
>            Assignee: Daniel Kulp
>
> h2. Description
> A JAX-WS service implementation class has a private {{WebServiceContext}} 
> field which is annotated with the JSR-250 {...@resource}} annotation. It has 
> also some annotation - for example {...@transactional}} - which will make 
> Spring wrapping it with a proxy. See the following code for an example:
> {code:title=SomeServiceImpl.java|borderStyle=solid}
> @Transactional
> @WebService(endpointInterface = "com.example.ISomeService")
> public class SomeServiceImpl implements SomeService {
>     @Resource
>     private WebServiceContext context;
>     ...
> {code}
> In the current release (2.2.8) this does not work and throws an 
> {{IllegalArgumentException}}.
> BTW There is the workaround to annotate a setter method instead of annotating 
> the field.
> h2. Background of the bug
> Because the Spring {{CommonAnnotationBeanPostProcessor}} which will normally 
> handle JSR-250 annotations ignores {{WebServiceContext}} {...@ressource}} 
> annotations (see the Javadoc of 
> [{{CommonAnnotationBeanPostProcessor}}|http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.html#ignoreResourceType%28java.lang.String%29])
>   there needs to be a special handling inside of CXF. This special handling 
> happens in the 
> {{org.apache.cxf.jaxws.JaxWsServerFactoryBean.injectResources(Object 
> instance)}} method:
> {code:title=JaxWsServerFactoryBean.injectResources(Object 
> instance)|borderStyle=solid}
> /**
>      * inject resources into servant.  The resources are injected
>      * according to @Resource annotations.  See JSR 250 for more
>      * information.
>      */
>     /**
>      * @param instance
>      */
>     protected void injectResources(Object instance) {
>         if (instance != null) {
>             ResourceManager resourceManager = 
> getBus().getExtension(ResourceManager.class);
>             List<ResourceResolver> resolvers = 
> resourceManager.getResourceResolvers();
>             resourceManager = new DefaultResourceManager(resolvers); 
>             resourceManager.addResourceResolver(new 
> WebServiceContextResourceResolver());
>             ResourceInjector injector = new ResourceInjector(resourceManager);
>             if (Proxy.isProxyClass(instance.getClass()) && getServiceClass() 
> != null) {
>                 injector.inject(instance, getServiceClass());
>                 injector.construct(instance, getServiceClass());
>             } else {
>                 injector.inject(instance);
>                 injector.construct(instance);
>             }
>         }
>     }  
> {code}
> h2. Bug
> As you can see there is already a special case to detect a proxy 
> ({{Proxy.isProxyClass()}}). The bug is that even in the case of a proxy the 
> code tries to inject into the field of the proxy. But the proxy does not have 
> the field and this gives an {{IllegalArgumentException}} inside of 
> {{ResourceInjector.injectField(Field field, Object resource)}}.
> h2. Fix
> In the case of a proxied object find the "wrapped" (target) object and inject 
> into this object. This is possible because the proxy will be a Spring proxy 
> and Spring has a special Interface ({{Advised}}) which will allow to access 
> the target object. See the following code:
> {code:title=JaxWsServerFactoryBean.injectResources(Object instance) - 
> Fixed|borderStyle=solid}
> /**
>      * inject resources into servant.  The resources are injected
>      * according to @Resource annotations.  See JSR 250 for more
>      * information.
>      */
>     /**
>      * @param instance
>      */
>     protected void injectResources(Object instance) {
>         if (instance != null) {
>             ResourceManager resourceManager = 
> getBus().getExtension(ResourceManager.class);
>             List<ResourceResolver> resolvers = 
> resourceManager.getResourceResolvers();
>             resourceManager = new DefaultResourceManager(resolvers); 
>             resourceManager.addResourceResolver(new 
> WebServiceContextResourceResolver());
>             ResourceInjector injector = new ResourceInjector(resourceManager);
>             if (Proxy.isProxyClass(instance.getClass()) && getServiceClass() 
> != null) {
>                 // FIXED: find and inject into the proxy target
>                 Object proxyTarget = 
> ((org.springframework.aop.framework.Advised)instance).getTargetSource().getTarget();
>                 injector.inject(proxyTarget, getServiceClass());
>                 injector.construct(instance, getServiceClass());
>             } else {
>                 injector.inject(instance);
>                 injector.construct(instance);
>             }
>         }
>     }  
> {code}

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to