diff --git a/jaxrs/resteasy-spring/src/main/java/org/jboss/resteasy/plugins/spring/SpringBeanProcessor.java b/jaxrs/resteasy-spring/src/main/java/org/jboss/resteasy/plugins/spring/SpringBeanProcessor.java index 5557638499f..fb09d37f85e 100644 --- a/jaxrs/resteasy-spring/src/main/java/org/jboss/resteasy/plugins/spring/SpringBeanProcessor.java +++ b/jaxrs/resteasy-spring/src/main/java/org/jboss/resteasy/plugins/spring/SpringBeanProcessor.java @@ -1,37 +1,17 @@ package org.jboss.resteasy.plugins.spring; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ws.rs.ext.MessageBodyReader; -import javax.ws.rs.ext.MessageBodyWriter; -import javax.ws.rs.ext.Provider; - import org.jboss.resteasy.core.Dispatcher; -import org.jboss.resteasy.spi.HttpRequest; -import org.jboss.resteasy.spi.HttpResponse; -import org.jboss.resteasy.spi.PropertyInjector; -import org.jboss.resteasy.spi.Registry; -import org.jboss.resteasy.spi.ResteasyDeployment; -import org.jboss.resteasy.spi.ResteasyProviderFactory; +import org.jboss.resteasy.spi.*; import org.jboss.resteasy.util.GetRestful; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; +import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.annotation.Required; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.factory.config.BeanReference; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.*; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; @@ -39,6 +19,12 @@ import org.springframework.context.event.SmartApplicationListener; import org.springframework.util.ClassUtils; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; +import java.lang.reflect.Method; +import java.util.*; + /** *

* The processor will register any bean annotated with @Path or @Provider into @@ -425,13 +411,46 @@ private static Class getBeanClass(String name, BeanDefinition beanDef, } } - for (Method method : getBeanClass(factoryClassName).getDeclaredMethods()) - { - if (method.getName().equals(factoryMethodName)) - { - return method.getReturnType(); - } - } + final Class beanClass = getBeanClass(factoryClassName); + final Method[] methods = beanClass.getDeclaredMethods(); + for (Method method : methods) { + if (method.getName().equals(factoryMethodName)) { + return method.getReturnType(); + } + } + + /* + https://github.com/resteasy/Resteasy/issues/585 + + If we haven't found the correct factoryMethod using the previous method, + fallback to the default FactoryBean getObject method. + + Case in which this tends to happen: + + 1. A bean (Bean A) exists which provides factoryMethods for retrieving 1 or more other beans (Bean B, Bean C, ...) + example: + 2. Bean B is retrieved by telling Spring that the Factory-Bean is Bean A and that there is a method X to retrieve Bean B. + example: + 3. When resteasy has to inject Bean B it tries to lookup method X on Bean A instead of Bean B using the above code. + + As a fix for this, we retrieve the return type for Bean A from the FactoryBean, which later on can be used to retrieve the other beans. + + */ + if (FactoryBean.class.isAssignableFrom(beanClass)) { + String defaultFactoryMethod = "getObject"; + Class returnType = null; + for (Method method : methods) { + if (method.getName().equals(defaultFactoryMethod)) { + returnType = method.getReturnType(); + if (returnType != Object.class) { + break; + } + } + } + if (returnType != null) { + return returnType; + } + } } throw new IllegalStateException("could not find the type for bean named " + name); diff --git a/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyBean.java b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyBean.java new file mode 100644 index 00000000000..ad2441d627c --- /dev/null +++ b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyBean.java @@ -0,0 +1,14 @@ +package org.jboss.resteasy.spring.beanprocessor; + +/** + * Created with IntelliJ IDEA. + * User: sgv + * Date: 23/10/14 + * Time: 16:16 + */ +public class MyBean { + + public MyInnerBean getMyInnerBean() { + return new MyInnerBeanImpl(); + } +} diff --git a/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyBeanFactoryBean.java b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyBeanFactoryBean.java new file mode 100644 index 00000000000..9690442661d --- /dev/null +++ b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyBeanFactoryBean.java @@ -0,0 +1,27 @@ +package org.jboss.resteasy.spring.beanprocessor; + +import org.springframework.beans.factory.FactoryBean; + +/** + * Created with IntelliJ IDEA. + * User: sgv + * Date: 23/10/14 + * Time: 16:15 + */ +public class MyBeanFactoryBean implements FactoryBean { + + @Override + public MyBean getObject() throws Exception { + return new MyBean(); + } + + @Override + public Class getObjectType() { + return MyBean.class; + } + + @Override + public boolean isSingleton() { + return true; + } +} diff --git a/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyInnerBean.java b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyInnerBean.java new file mode 100644 index 00000000000..6321c5443fe --- /dev/null +++ b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyInnerBean.java @@ -0,0 +1,10 @@ +package org.jboss.resteasy.spring.beanprocessor; + +/** + * Created with IntelliJ IDEA. + * User: sgv + * Date: 24/10/14 + * Time: 8:44 + */ +public interface MyInnerBean { +} diff --git a/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyInnerBeanImpl.java b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyInnerBeanImpl.java new file mode 100644 index 00000000000..2cb313f6b09 --- /dev/null +++ b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/spring/beanprocessor/MyInnerBeanImpl.java @@ -0,0 +1,10 @@ +package org.jboss.resteasy.spring.beanprocessor; + +/** + * Created with IntelliJ IDEA. + * User: sgv + * Date: 24/10/14 + * Time: 8:45 + */ +public class MyInnerBeanImpl implements MyInnerBean { +} diff --git a/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/springmvc/test/spring/RequestScopedBeanTest.java b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/springmvc/test/spring/RequestScopedBeanTest.java index 9e1afa66c25..60c1f3a267b 100644 --- a/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/springmvc/test/spring/RequestScopedBeanTest.java +++ b/jaxrs/resteasy-spring/src/test/java/org/jboss/resteasy/springmvc/test/spring/RequestScopedBeanTest.java @@ -5,10 +5,9 @@ import org.jboss.resteasy.core.ValueInjector; import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpResponse; -import org.jboss.resteasy.spi.PropertyInjector; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.metadata.Parameter; -import org.jboss.resteasy.spi.metadata.ResourceClass; +import org.jboss.resteasy.spring.beanprocessor.MyInnerBean; import org.jboss.resteasy.springmvc.tjws.TJWSEmbeddedSpringMVCServer; import org.jboss.resteasy.test.TestPortProvider; import org.jboss.resteasy.util.FindAnnotation; @@ -18,6 +17,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import javax.ws.rs.GET; @@ -110,6 +110,9 @@ public void setConfigured(String configured) } } + @Autowired + private MyInnerBean myInnerBean; + @Path("/") public static class TestBeanResource { diff --git a/jaxrs/resteasy-spring/src/test/resources/spring-request-scope-test-server.xml b/jaxrs/resteasy-spring/src/test/resources/spring-request-scope-test-server.xml index b6874da1fe6..de5eb2d8eb7 100644 --- a/jaxrs/resteasy-spring/src/test/resources/spring-request-scope-test-server.xml +++ b/jaxrs/resteasy-spring/src/test/resources/spring-request-scope-test-server.xml @@ -2,15 +2,20 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + - + - + + + + +