diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 4a1bc1173f..31a696e12d 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -16,10 +16,13 @@ package org.springframework.integration.gateway; +import java.lang.reflect.Method; + import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.framework.ProxyFactory; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.SimpleTypeConverter; import org.springframework.beans.TypeConverter; import org.springframework.beans.factory.BeanClassLoaderAware; @@ -42,16 +45,23 @@ import org.springframework.util.ClassUtils; public class GatewayProxyFactoryBean extends SimpleMessagingGateway implements FactoryBean, MethodInterceptor, InitializingBean, BeanClassLoaderAware, BeanFactoryAware { - private Class serviceInterface; + private volatile Class serviceInterface; - private TypeConverter typeConverter = new SimpleTypeConverter(); + private volatile TypeConverter typeConverter = new SimpleTypeConverter(); - private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); + private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); - private Object serviceProxy; + private volatile Object serviceProxy; + + private volatile boolean initialized; + + private final Object initializationMonitor = new Object(); public void setServiceInterface(Class serviceInterface) { + if (serviceInterface != null && !serviceInterface.isInterface()) { + throw new IllegalArgumentException("'serviceInterface' must be an interface"); + } this.serviceInterface = serviceInterface; } @@ -70,7 +80,16 @@ public class GatewayProxyFactoryBean extends SimpleMessagingGateway } public void afterPropertiesSet() { - this.serviceProxy = new ProxyFactory(this.serviceInterface, this).getProxy(this.beanClassLoader); + synchronized (this.initializationMonitor) { + if (this.initialized) { + return; + } + if (this.serviceInterface == null) { + throw new IllegalArgumentException("'serviceInterface' must not be null"); + } + this.serviceProxy = new ProxyFactory(this.serviceInterface, this).getProxy(this.beanClassLoader); + this.initialized = true; + } } public Object getObject() throws Exception { @@ -86,9 +105,24 @@ public class GatewayProxyFactoryBean extends SimpleMessagingGateway } public Object invoke(MethodInvocation invocation) throws Throwable { - Class returnType = invocation.getMethod().getReturnType(); + Method method = invocation.getMethod(); + if (AopUtils.isToStringMethod(method)) { + return "gateway proxy for service interface [" + this.serviceInterface + "]"; + } + if (method.getDeclaringClass().equals(this.serviceInterface)) { + return this.invokeGatewayMethod(invocation); + } + return invocation.proceed(); + } + + private Object invokeGatewayMethod(MethodInvocation invocation) throws Throwable { + if (!this.initialized) { + this.afterPropertiesSet(); + } + Method method = invocation.getMethod(); + Class returnType = method.getReturnType(); boolean shouldReturnMessage = Message.class.isAssignableFrom(returnType); - int paramCount = invocation.getMethod().getParameterTypes().length; + int paramCount = method.getParameterTypes().length; Object response = null; if (paramCount == 0) { if (shouldReturnMessage) { diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java index c031f0c7ce..e4c5d5312f 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java @@ -145,6 +145,32 @@ public class GatewayProxyFactoryBeanTests { assertEquals("foobar", result.getPayload()); } + @Test + public void testServiceMustBeInterface() { + GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(); + int count = 0; + try { + proxyFactory.setServiceInterface(TestService.class); + count++; + proxyFactory.setServiceInterface(String.class); + count++; + } + catch (IllegalArgumentException e) { + // expected + } + assertEquals(1, count); + } + + @Test + public void testProxiedToStringMethod() throws Exception { + GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(); + proxyFactory.setServiceInterface(TestService.class); + proxyFactory.afterPropertiesSet(); + Object proxy = proxyFactory.getObject(); + String expected = "gateway proxy for"; + assertEquals(expected, proxy.toString().substring(0, expected.length())); + } + private static void startResponder(final MessageChannel requestChannel) { new Thread(new Runnable() {