From 2bc759a279af962b17c16d98f879640b59104490 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 16 Dec 2010 09:22:43 -0500 Subject: [PATCH] INT-1689 added fix to properly configure service proxy when Gateway service interface is a hierarchical structure --- spring-integration-core/.springBeans | 1 + .../gateway/GatewayProxyFactoryBean.java | 18 +-- .../gateway/GatewayInterfaceTest-context.xml | 17 ++ .../gateway/GatewayInterfaceTest.java | 149 ++++++++++++++++++ 4 files changed, 176 insertions(+), 9 deletions(-) create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest-context.xml create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest.java diff --git a/spring-integration-core/.springBeans b/spring-integration-core/.springBeans index 6c6cb5a284..9087afb06f 100644 --- a/spring-integration-core/.springBeans +++ b/spring-integration-core/.springBeans @@ -7,6 +7,7 @@ + src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest-context.xml diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 83435a82e5..fdcfe951ff 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -54,6 +54,7 @@ import org.springframework.integration.support.channel.ChannelResolver; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; /** @@ -216,7 +217,8 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Trackab this.channelResolver = new BeanFactoryChannelResolver(beanFactory); } Class proxyInterface = this.determineServiceInterface(); - Method[] methods = proxyInterface.getDeclaredMethods(); + + Method[] methods = ReflectionUtils.getAllDeclaredMethods(proxyInterface); for (Method method : methods) { MethodInvocationGateway gateway = this.createGatewayForMethod(method); this.gatewayMap.put(method, gateway); @@ -262,15 +264,13 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Trackab if (AopUtils.isToStringMethod(method)) { return "gateway proxy for service interface [" + this.serviceInterface + "]"; } - if (method.getDeclaringClass().equals(this.serviceInterface)) { - try { - return this.invokeGatewayMethod(invocation); - } - catch (Exception e) { - rethrowExceptionInThrowsClauseIfPossible(e, invocation.getMethod()); - } + try { + return this.invokeGatewayMethod(invocation); } - return invocation.proceed(); + catch (Throwable e) { + this.rethrowExceptionInThrowsClauseIfPossible(e, invocation.getMethod()); + } + return null; } private Object invokeGatewayMethod(MethodInvocation invocation) throws Exception { diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest-context.xml new file mode 100644 index 0000000000..29c64b7d4d --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest-context.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest.java new file mode 100644 index 0000000000..65582ca88d --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInterfaceTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.gateway; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.Test; +import org.mockito.Mockito; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.Message; +import org.springframework.integration.annotation.Gateway; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.MessageHandler; + +/** + * @author Oleg Zhurakousky + * + */ +public class GatewayInterfaceTest { + + @Test + public void testWithServiceSuperclassAnnotatedMethod(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Bar bar = ac.getBean(Bar.class); + bar.foo("hello"); + verify(handler, times(1)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceAnnotatedMethod(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelBar", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Bar bar = ac.getBean(Bar.class); + bar.bar("hello"); + verify(handler, times(1)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceSuperclassUnAnnotatedMethod(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Bar bar = ac.getBean(Bar.class); + bar.baz("hello"); + verify(handler, times(1)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceCastAsSuperclassAnnotatedMethod(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelFoo", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Foo foo = ac.getBean(Foo.class); + foo.foo("hello"); + verify(handler, times(1)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceCastAsSuperclassUnAnnotatedMethod(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Foo foo = ac.getBean(Foo.class); + foo.baz("hello"); + verify(handler, times(1)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceHashcode(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Bar bar = ac.getBean(Bar.class); + bar.hashCode(); + verify(handler, times(0)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceToString(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Bar bar = ac.getBean(Bar.class); + bar.toString(); + verify(handler, times(0)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceEquals(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Bar bar = ac.getBean(Bar.class); + bar.equals(""); + verify(handler, times(0)).handleMessage(Mockito.any(Message.class)); + } + + @Test + public void testWithServiceGetClass(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTest-context.xml", this.getClass()); + DirectChannel channel = ac.getBean("requestChannelBaz", DirectChannel.class); + MessageHandler handler = mock(MessageHandler.class); + channel.subscribe(handler); + Bar bar = ac.getBean(Bar.class); + bar.getClass(); + verify(handler, times(0)).handleMessage(Mockito.any(Message.class)); + } + + + public interface Foo { + @Gateway(requestChannel="requestChannelFoo") + public void foo(String payload); + + public void baz(String payload); + } + + public static interface Bar extends Foo{ + @Gateway(requestChannel="requestChannelBar") + public void bar(String payload); + } +}