INT-4336: Fix NPE in IntegrationGraphServer
JIRA: https://jira.spring.io/browse/INT-4336 Don't add "hidden" unreachable methods to the map in the `GatewayProxyFactoryBean`. The methods can never be executed and may not have all expected properties; they should not appear in the graph at all since they are unreachable. Also add defensive coding to the `IntegrationGraphServer` to avoid NPEs when unexpected conditions arise. # Conflicts: # spring-integration-core/src/test/java/org/springframework/integration/dsl/reactivestreams/ReactiveStreamsTests.java # spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java
This commit is contained in:
committed by
Artem Bilan
parent
d8ecdce83d
commit
488ec15907
@@ -344,7 +344,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint
|
||||
this.channelResolver = new BeanFactoryChannelResolver(beanFactory);
|
||||
}
|
||||
Class<?> proxyInterface = this.determineServiceInterface();
|
||||
Method[] methods = ReflectionUtils.getAllDeclaredMethods(proxyInterface);
|
||||
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(proxyInterface);
|
||||
for (Method method : methods) {
|
||||
MethodInvocationGateway gateway = this.createGatewayForMethod(method);
|
||||
this.gatewayMap.put(method, gateway);
|
||||
|
||||
@@ -273,21 +273,24 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat
|
||||
|
||||
private MessageGatewayNode gatewayNode(String name, MessagingGatewaySupport gateway) {
|
||||
String errorChannel = gateway.getErrorChannel() != null ? gateway.getErrorChannel().toString() : null;
|
||||
String requestChannel = gateway.getRequestChannel() != null ? gateway.getRequestChannel().toString() : null;
|
||||
return new MessageGatewayNode(this.nodeId.incrementAndGet(), name, gateway,
|
||||
gateway.getRequestChannel().toString(), errorChannel);
|
||||
requestChannel, errorChannel);
|
||||
}
|
||||
|
||||
private MessageProducerNode producerNode(String name, MessageProducerSupport producer) {
|
||||
String errorChannel = producer.getErrorChannel() != null ? producer.getErrorChannel().toString() : null;
|
||||
String outputChannel = producer.getOutputChannel() != null ? producer.getOutputChannel().toString() : null;
|
||||
return new MessageProducerNode(this.nodeId.incrementAndGet(), name, producer,
|
||||
producer.getOutputChannel().toString(), errorChannel);
|
||||
outputChannel, errorChannel);
|
||||
}
|
||||
|
||||
private MessageSourceNode sourceNode(String name, SourcePollingChannelAdapter adapter) {
|
||||
String errorChannel = adapter.getDefaultErrorChannel() != null
|
||||
? adapter.getDefaultErrorChannel().toString() : null;
|
||||
String outputChannel = adapter.getOutputChannel() != null ? adapter.getOutputChannel().toString() : null;
|
||||
return new MessageSourceNode(this.nodeId.incrementAndGet(), name, adapter.getMessageSource(),
|
||||
adapter.getOutputChannel().toString(), errorChannel);
|
||||
outputChannel, errorChannel);
|
||||
}
|
||||
|
||||
private MessageHandlerNode handlerNode(String name, IntegrationConsumer consumer) {
|
||||
@@ -311,8 +314,9 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat
|
||||
outputChannelName, null, false);
|
||||
}
|
||||
else {
|
||||
String inputChannel = consumer.getInputChannel() != null ? consumer.getInputChannel().toString() : null;
|
||||
return new MessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), outputChannelName);
|
||||
inputChannel, outputChannelName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,8 +343,9 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat
|
||||
outputChannelName, errorChannel, true);
|
||||
}
|
||||
else {
|
||||
String inputChannel = consumer.getInputChannel() != null ? consumer.getInputChannel().toString() : null;
|
||||
return new ErrorCapableMessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), outputChannelName, errorChannel);
|
||||
inputChannel, outputChannelName, errorChannel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,21 +361,23 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat
|
||||
named.getComponentType()));
|
||||
}
|
||||
}
|
||||
String inputChannel = consumer.getInputChannel() != null ? consumer.getInputChannel().toString() : null;
|
||||
return polled
|
||||
? new ErrorCapableCompositeMessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, errors, innerHandlers)
|
||||
inputChannel, output, errors, innerHandlers)
|
||||
: new CompositeMessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, innerHandlers);
|
||||
inputChannel, output, innerHandlers);
|
||||
}
|
||||
|
||||
private MessageHandlerNode discardingHandler(String name, IntegrationConsumer consumer,
|
||||
DiscardingMessageHandler handler, String output, String errors, boolean polled) {
|
||||
String discards = handler.getDiscardChannel() != null ? handler.getDiscardChannel().toString() : null;
|
||||
String inputChannel = consumer.getInputChannel() != null ? consumer.getInputChannel().toString() : null;
|
||||
return polled
|
||||
? new ErrorCapableDiscardingMessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, discards, errors)
|
||||
inputChannel, output, discards, errors)
|
||||
: new DiscardingMessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, discards);
|
||||
inputChannel, output, discards);
|
||||
}
|
||||
|
||||
private MessageHandlerNode routingHandler(String name, IntegrationConsumer consumer, MessageHandler handler,
|
||||
@@ -381,11 +388,12 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat
|
||||
routes = new ArrayList<String>(routes);
|
||||
routes.addAll(dynamicChannelNames);
|
||||
}
|
||||
String inputChannel = consumer.getInputChannel() != null ? consumer.getInputChannel().toString() : null;
|
||||
return polled
|
||||
? new ErrorCapableRoutingNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, errors, routes)
|
||||
inputChannel, output, errors, routes)
|
||||
: new RoutingMessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, routes);
|
||||
inputChannel, output, routes);
|
||||
}
|
||||
|
||||
private MessageHandlerNode recipientListRoutingHandler(String name, IntegrationConsumer consumer,
|
||||
@@ -396,11 +404,12 @@ public class IntegrationGraphServer implements ApplicationContextAware, Applicat
|
||||
for (Object recipient : recipients) {
|
||||
routes.add(((Recipient) recipient).getChannel().toString());
|
||||
}
|
||||
String inputChannel = consumer.getInputChannel() != null ? consumer.getInputChannel().toString() : null;
|
||||
return polled
|
||||
? new ErrorCapableRoutingNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, errors, routes)
|
||||
inputChannel, output, errors, routes)
|
||||
: new RoutingMessageHandlerNode(this.nodeId.incrementAndGet(), name, handler,
|
||||
consumer.getInputChannel().toString(), output, routes);
|
||||
inputChannel, output, routes);
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
|
||||
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -455,6 +456,13 @@ public class GatewayProxyFactoryBeanTests {
|
||||
new ClassPathXmlApplicationContext("gatewayAutowiring.xml", GatewayProxyFactoryBeanTests.class).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverriddenMethod() {
|
||||
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean(InheritChild.class);
|
||||
gpfb.afterPropertiesSet();
|
||||
Map<Method, MessagingGatewaySupport> gateways = gpfb.getGateways();
|
||||
assertThat(gateways.size(), equalTo(2));
|
||||
}
|
||||
|
||||
public static void throwTestException() throws TestException {
|
||||
throw new TestException();
|
||||
@@ -472,6 +480,20 @@ public class GatewayProxyFactoryBeanTests {
|
||||
String throwCheckedException(String s) throws TestException;
|
||||
}
|
||||
|
||||
interface InheritSuper {
|
||||
|
||||
String overridden(String in);
|
||||
|
||||
String NotOverridden(String in);
|
||||
|
||||
}
|
||||
|
||||
interface InheritChild extends InheritSuper {
|
||||
|
||||
@Override
|
||||
String overridden(String in);
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
static class TestException extends Exception {
|
||||
|
||||
Reference in New Issue
Block a user