cxf-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Oliver Geisser (JIRA)" <j...@apache.org>
Subject [jira] Created: (CXF-2828) JSR 250 @Resource annotation on field does not work for proxied service implementations
Date Thu, 27 May 2010 09:05:36 GMT
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


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.


Mime
View raw message