INT-4033: Support SpEL in Gateway Timeouts

JIRA: https://jira.spring.io/browse/INT-4033

Provide a mechanism to support dynamic timeouts when invoking gateway methods.

Polishing - PR Comments

* Polishing `what's new`
* Add `STOMP` to the `endpoint-summary.adoc`
* Polishing code style a bit for the changes in this fix
This commit is contained in:
Gary Russell
2017-05-23 21:28:52 -04:00
committed by Artem Bilan
parent 914094e51d
commit f58106ec3c
20 changed files with 421 additions and 99 deletions

View File

@@ -46,6 +46,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.Expression;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.MessageRejectedException;
import org.springframework.integration.channel.QueueChannel;
@@ -391,8 +392,10 @@ public class ChainParserTests {
GatewayProxyFactoryBean.class);
assertEquals("strings", TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultRequestChannelName"));
assertEquals("numbers", TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyChannelName"));
assertEquals(new Long(1000), TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultRequestTimeout", Long.class));
assertEquals(new Long(100), TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyTimeout", Long.class));
assertEquals(new Long(1000), TestUtils
.getPropertyValue(gatewayProxyFactoryBean, "defaultRequestTimeout", Expression.class).getValue());
assertEquals(new Long(100), TestUtils
.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyTimeout", Expression.class).getValue());
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.objectToStringTransformerWithinChain.handler"));
assertTrue(this.beanFactory.containsBean("subComponentsIdSupport1$child.objectToMapTransformerWithinChain.handler"));

View File

@@ -79,6 +79,8 @@
service-interface="org.springframework.integration.gateway.TestService"
default-request-channel="requestChannel"
default-reply-channel="replyChannel"
default-request-timeout="1000"
default-reply-timeout="2000"
async-executor="testExecutor">
<default-header name="baz" value="qux"/>
<method name="oneWay" request-channel="otherRequestChannel"
@@ -88,6 +90,10 @@
reply-channel="foo">
<header name="foo" value="bar"/>
</method>
<method name="oneWayWithTimeouts" request-channel="otherRequestChannel"
request-timeout="#args[1]"
reply-timeout="#args[2]">
</method>
</gateway>
<!-- no assertions for this. The fact that this config does not result in error is sufficient -->

View File

@@ -45,6 +45,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.expression.Expression;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.IntegrationConfigUtils;
import org.springframework.integration.gateway.GatewayMethodMetadata;
@@ -95,16 +96,26 @@ public class GatewayParserTests {
service.oneWay("foo");
PollableChannel channel = (PollableChannel) context.getBean("otherRequestChannel");
Message<?> result = channel.receive(10000);
assertNotNull(result);
assertEquals("fiz", result.getPayload());
assertEquals("bar", result.getHeaders().get("foo"));
assertEquals("qux", result.getHeaders().get("baz"));
GatewayProxyFactoryBean fb = context.getBean("&methodOverride", GatewayProxyFactoryBean.class);
assertEquals(1000L, TestUtils.getPropertyValue(fb, "defaultRequestTimeout", Expression.class).getValue());
assertEquals(2000L, TestUtils.getPropertyValue(fb, "defaultReplyTimeout", Expression.class).getValue());
Map<?, ?> methods = TestUtils.getPropertyValue(fb, "methodMetadataMap", Map.class);
GatewayMethodMetadata meta = (GatewayMethodMetadata) methods.get("oneWay");
assertNotNull(meta);
assertEquals("456", meta.getRequestTimeout());
assertEquals("123", meta.getReplyTimeout());
assertEquals("foo", meta.getReplyChannelName());
meta = (GatewayMethodMetadata) methods.get("oneWayWithTimeouts");
assertNotNull(meta);
assertEquals("#args[1]", meta.getRequestTimeout());
assertEquals("#args[2]", meta.getReplyTimeout());
service.oneWayWithTimeouts("foo", 100L, 200L);
result = channel.receive(10000);
assertNotNull(result);
}
@Test

View File

@@ -19,7 +19,6 @@
<int:method name="baz">
<int:header name="name" value="overrideGlobal"/>
</int:method>
<int:method name="lateReply" request-channel="lateReplyChannel" reply-timeout="0"/>
</int:gateway>
<int:chain input-channel="lateReplyChannel" >

View File

@@ -46,7 +46,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -63,6 +62,7 @@ import org.springframework.context.annotation.FilterType;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.expression.Expression;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.annotation.AnnotationConstants;
import org.springframework.integration.annotation.BridgeTo;
@@ -357,15 +357,17 @@ public class GatewayInterfaceTests {
@Test
public void testLateReply() throws Exception {
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml", this.getClass());
ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("GatewayInterfaceTests-context.xml",
this.getClass());
Bar baz = ac.getBean(Bar.class);
String reply = baz.lateReply("hello");
String reply = baz.lateReply("hello", 1000, 0);
assertNull(reply);
PollableChannel errorChannel = ac.getBean("errorChannel", PollableChannel.class);
Message<?> receive = errorChannel.receive(5000);
assertNotNull(receive);
MessagingException messagingException = (MessagingException) receive.getPayload();
assertThat(messagingException.getMessage(), Matchers.startsWith("Reply message received but the receiving thread has exited due to a timeout"));
assertThat(messagingException.getMessage(),
startsWith("Reply message received but the receiving thread has exited due to a timeout"));
ac.close();
}
@@ -436,10 +438,12 @@ public class GatewayInterfaceTests {
assertNotNull(this.gatewayByAnnotationGPFB);
assertSame(this.exec, this.annotationGatewayProxyFactoryBean.getAsyncExecutor());
assertEquals(1111L,
TestUtils.getPropertyValue(this.annotationGatewayProxyFactoryBean, "defaultRequestTimeout"));
assertEquals(222L,
TestUtils.getPropertyValue(this.annotationGatewayProxyFactoryBean, "defaultReplyTimeout"));
assertEquals(1111L, TestUtils
.getPropertyValue(this.annotationGatewayProxyFactoryBean, "defaultRequestTimeout", Expression.class)
.getValue());
assertEquals(222L, TestUtils
.getPropertyValue(this.annotationGatewayProxyFactoryBean, "defaultReplyTimeout", Expression.class)
.getValue());
Collection<MessagingGatewaySupport> messagingGateways =
this.annotationGatewayProxyFactoryBean.getGateways().values();
@@ -490,7 +494,9 @@ public class GatewayInterfaceTests {
void baz(String payload);
String lateReply(String payload);
@Gateway(payloadExpression = "#args[0]", requestChannel = "lateReplyChannel",
requestTimeoutExpression = "#args[1]", replyTimeoutExpression = "#args[2]")
String lateReply(String payload, long requestTimeout, long replyTimeout);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -24,7 +24,9 @@ import java.util.Map.Entry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Expression;
import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
@@ -44,7 +46,8 @@ public class GatewayXmlAndAnnotationTests {
@Test
public void test() {
assertEquals(123L, TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyTimeout"));
assertEquals(123L, TestUtils.getPropertyValue(gatewayProxyFactoryBean, "defaultReplyTimeout", Expression.class)
.getValue());
@SuppressWarnings("unchecked")
Map<Method, MessagingGatewaySupport> gatewayMap = TestUtils.getPropertyValue(gatewayProxyFactoryBean,
"gatewayMap", Map.class);

View File

@@ -37,6 +37,9 @@ public interface TestService {
void oneWay(String input);
@Payload("#args[0]")
void oneWayWithTimeouts(String input, Long sendTimeout, Long receiveTimeout);
String solicitResponse();
Message<String> getMessage();