Refinement for gateway Mono processing (#3075)

* Refinement for gateway Mono processing

* Introduce a `MessagingGatewaySupport.MonoReplyChannel` instead of
`FutureReplyChannel` for better on demand handling and reusing a
`Mono` returned from the target handler
* Refactor `GatewayProxyFactoryBean` to identify a target return type
(including generics for `Function`) during initialization
* Handle a `Mono` return type via
`MessagingGatewaySupport.sendAndReceiveMessageReactive()`
* Some `@Nullable` in the `GatewayProxyFactoryBean` and `ExpressionUtils`
* Add `MonoFunction` test-case into the `FunctionsTests.kt`

* * Deprecate `GatewayProxyFactoryBean.setServiceInterface()` in favor of
ctor initialization
* Fix `GatewayProxyFactoryBean.setServiceInterface()` usage in tests
This commit is contained in:
Artem Bilan
2019-10-14 15:31:04 -04:00
committed by Gary Russell
parent 7733da651f
commit 911cdc86b5
11 changed files with 224 additions and 259 deletions

View File

@@ -25,7 +25,6 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
@@ -50,6 +49,7 @@ import reactor.core.publisher.Mono;
* @author Oleg Zhurakousky
* @author Gary Russell
* @author Artem Bilan
*
* @since 2.0
*/
public class AsyncGatewayTests {
@@ -58,9 +58,8 @@ public class AsyncGatewayTests {
public void futureWithMessageReturned() throws Exception {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
@@ -82,9 +81,8 @@ public class AsyncGatewayTests {
}
};
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(channel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
@@ -104,16 +102,15 @@ public class AsyncGatewayTests {
QueueChannel requestChannel = new QueueChannel();
addThreadEnricher(requestChannel);
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
TestEchoService service = (TestEchoService) proxyFactory.getObject();
ListenableFuture<Message<?>> f = service.returnMessageListenable("foo");
long start = System.currentTimeMillis();
final AtomicReference<Message<?>> result = new AtomicReference<Message<?>>();
final AtomicReference<Message<?>> result = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
f.addCallback(new ListenableFutureCallback<Message<?>>() {
@@ -141,9 +138,8 @@ public class AsyncGatewayTests {
QueueChannel requestChannel = new QueueChannel();
addThreadEnricher(requestChannel);
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
@@ -159,9 +155,8 @@ public class AsyncGatewayTests {
QueueChannel requestChannel = new QueueChannel();
addThreadEnricher(requestChannel);
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
@@ -192,9 +187,8 @@ public class AsyncGatewayTests {
public void futureWithPayloadReturned() throws Exception {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
@@ -209,9 +203,8 @@ public class AsyncGatewayTests {
public void futureWithWildcardReturned() throws Exception {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
@@ -224,12 +217,11 @@ public class AsyncGatewayTests {
@Test
public void monoWithMessageReturned() throws Exception {
public void monoWithMessageReturned() {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.setBeanName("testGateway");
proxyFactory.afterPropertiesSet();
@@ -240,12 +232,11 @@ public class AsyncGatewayTests {
}
@Test
public void monoWithPayloadReturned() throws Exception {
public void monoWithPayloadReturned() {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.setBeanName("testGateway");
proxyFactory.afterPropertiesSet();
@@ -256,12 +247,11 @@ public class AsyncGatewayTests {
}
@Test
public void monoWithWildcardReturned() throws Exception {
public void monoWithWildcardReturned() {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.setBeanName("testGateway");
proxyFactory.afterPropertiesSet();
@@ -276,16 +266,15 @@ public class AsyncGatewayTests {
public void monoWithConsumer() throws Exception {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestEchoService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestEchoService.class);
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.setBeanName("testGateway");
proxyFactory.afterPropertiesSet();
TestEchoService service = (TestEchoService) proxyFactory.getObject();
Mono<String> mono = service.returnStringPromise("foo");
final AtomicReference<String> result = new AtomicReference<String>();
final AtomicReference<String> result = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
mono.subscribe(s -> {
@@ -374,14 +363,13 @@ public class AsyncGatewayTests {
}
@Override
public String get() throws InterruptedException, ExecutionException {
return result;
public String get() {
return this.result;
}
@Override
public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
TimeoutException {
return result;
public String get(long timeout, TimeUnit unit) {
return this.result;
}
}

View File

@@ -17,7 +17,8 @@
package org.springframework.integration.gateway;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -67,12 +68,11 @@ import org.springframework.util.ReflectionUtils;
public class GatewayProxyFactoryBeanTests {
@Test
public void testRequestReplyWithAnonymousChannel() throws Exception {
public void testRequestReplyWithAnonymousChannel() {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestService.class);
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.setBeanName("testGateway");
proxyFactory.afterPropertiesSet();
@@ -82,7 +82,7 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testRequestReplyWithAnonymousChannelConvertedTypeViaConversionService() throws Exception {
public void testRequestReplyWithAnonymousChannelConvertedTypeViaConversionService() {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GenericConversionService cs = new DefaultConversionService();
@@ -98,13 +98,12 @@ public class GatewayProxyFactoryBeanTests {
};
stringToByteConverter = spy(stringToByteConverter);
cs.addConverter(stringToByteConverter);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerSingleton(IntegrationUtils.INTEGRATION_CONVERSION_SERVICE_BEAN_NAME, cs);
proxyFactory.setBeanFactory(bf);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setServiceInterface(TestService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.afterPropertiesSet();
TestService service = (TestService) proxyFactory.getObject();
@@ -114,10 +113,9 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testOneWay() throws Exception {
public void testOneWay() {
final QueueChannel requestChannel = new QueueChannel();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
@@ -130,11 +128,10 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testSolicitResponse() throws Exception {
public void testSolicitResponse() {
QueueChannel replyChannel = new QueueChannel();
replyChannel.send(new GenericMessage<>("foo"));
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(new DirectChannel());
proxyFactory.setDefaultReplyChannel(replyChannel);
proxyFactory.setBeanName("testGateway");
@@ -147,11 +144,10 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testReceiveMessage() throws Exception {
public void testReceiveMessage() {
QueueChannel replyChannel = new QueueChannel();
replyChannel.send(new GenericMessage<>("foo"));
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultReplyChannel(replyChannel);
proxyFactory.setBeanFactory(mock(BeanFactory.class));
@@ -163,15 +159,14 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testRequestReplyWithTypeConversion() throws Exception {
public void testRequestReplyWithTypeConversion() {
final QueueChannel requestChannel = new QueueChannel();
new Thread(() -> {
Message<?> input = requestChannel.receive();
GenericMessage<String> reply = new GenericMessage<>(input.getPayload() + "456");
((MessageChannel) input.getHeaders().getReplyChannel()).send(reply);
}).start();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
@@ -239,11 +234,10 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testMessageAsMethodArgument() throws Exception {
public void testMessageAsMethodArgument() {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
@@ -254,11 +248,10 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testNoArgMethodWithPayloadAnnotation() throws Exception {
public void testNoArgMethodWithPayloadAnnotation() {
QueueChannel requestChannel = new QueueChannel();
startResponder(requestChannel);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
@@ -269,15 +262,14 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testMessageAsReturnValue() throws Exception {
public void testMessageAsReturnValue() {
final QueueChannel requestChannel = new QueueChannel();
new Thread(() -> {
Message<?> input = requestChannel.receive();
GenericMessage<String> reply = new GenericMessage<>(input.getPayload() + "bar");
((MessageChannel) input.getHeaders().getReplyChannel()).send(reply);
}).start();
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
proxyFactory.setServiceInterface(TestService.class);
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(requestChannel);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
@@ -289,25 +281,14 @@ public class GatewayProxyFactoryBeanTests {
@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
}
assertThat(count).isEqualTo(1);
assertThatIllegalArgumentException()
.isThrownBy(() -> new GatewayProxyFactoryBean(String.class));
}
@Test
public void testProxiedToStringMethod() throws Exception {
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
public void testProxiedToStringMethod() {
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestService.class);
proxyFactory.setDefaultRequestChannel(new DirectChannel());
proxyFactory.setServiceInterface(TestService.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
@@ -316,9 +297,9 @@ public class GatewayProxyFactoryBeanTests {
assertThat(proxy.toString().substring(0, expected.length())).isEqualTo(expected);
}
@Test(expected = TestException.class)
public void testCheckedExceptionRethrownAsIs() throws Exception {
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean();
@Test
public void testCheckedExceptionRethrownAsIs() {
GatewayProxyFactoryBean proxyFactory = new GatewayProxyFactoryBean(TestExceptionThrowingInterface.class);
DirectChannel channel = new DirectChannel();
EventDrivenConsumer consumer = new EventDrivenConsumer(channel, new MessageHandler() {
@@ -331,12 +312,12 @@ public class GatewayProxyFactoryBeanTests {
});
consumer.start();
proxyFactory.setDefaultRequestChannel(channel);
proxyFactory.setServiceInterface(TestExceptionThrowingInterface.class);
proxyFactory.setBeanName("testGateway");
proxyFactory.setBeanFactory(mock(BeanFactory.class));
proxyFactory.afterPropertiesSet();
TestExceptionThrowingInterface proxy = (TestExceptionThrowingInterface) proxyFactory.getObject();
proxy.throwCheckedException("test");
assertThatExceptionOfType(TestException.class)
.isThrownBy(() -> proxy.throwCheckedException("test"));
}
@@ -349,10 +330,9 @@ public class GatewayProxyFactoryBeanTests {
}
@Test
public void testProgrammaticWiring() throws Exception {
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean();
public void testProgrammaticWiring() {
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean(TestEchoService.class);
gpfb.setBeanFactory(mock(BeanFactory.class));
gpfb.setServiceInterface(TestEchoService.class);
QueueChannel drc = new QueueChannel();
gpfb.setDefaultRequestChannel(drc);
gpfb.setDefaultReplyTimeout(0L);
@@ -377,49 +357,29 @@ public class GatewayProxyFactoryBeanTests {
meta.setHeaderExpressions(Collections.singletonMap(MessageHeaders.ID, new LiteralExpression("bar")));
gpfb.setGlobalMethodMetadata(meta);
try {
gpfb.afterPropertiesSet();
fail("BeanInitializationException expected");
}
catch (Exception e) {
assertThat(e).isInstanceOf(BeanInitializationException.class);
assertThat(e.getMessage())
.contains("Messaging Gateway cannot override 'id' and 'timestamp' read-only headers");
}
assertThatExceptionOfType(BeanInitializationException.class)
.isThrownBy(gpfb::afterPropertiesSet)
.withMessageContaining("Messaging Gateway cannot override 'id' and 'timestamp' read-only headers");
}
@Test
public void testIdHeaderOverrideGatewayHeaderAnnotation() {
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean(HeadersOverwriteService.class);
gpfb.setBeanFactory(mock(BeanFactory.class));
gpfb.setServiceInterface(HeadersOverwriteService.class);
try {
gpfb.afterPropertiesSet();
fail("BeanInitializationException expected");
}
catch (Exception e) {
assertThat(e).isInstanceOf(BeanInitializationException.class);
assertThat(e.getMessage())
.contains("Messaging Gateway cannot override 'id' and 'timestamp' read-only headers");
}
assertThatExceptionOfType(BeanInitializationException.class)
.isThrownBy(gpfb::afterPropertiesSet)
.withMessageContaining("Messaging Gateway cannot override 'id' and 'timestamp' read-only headers");
}
@Test
public void testTimeStampHeaderOverrideParamHeaderAnnotation() {
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean();
GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean(HeadersParamService.class);
gpfb.setBeanFactory(mock(BeanFactory.class));
gpfb.setServiceInterface(HeadersParamService.class);
try {
gpfb.afterPropertiesSet();
fail("BeanInitializationException expected");
}
catch (Exception e) {
assertThat(e).isInstanceOf(BeanInitializationException.class);
assertThat(e.getMessage())
.contains("Messaging Gateway cannot override 'id' and 'timestamp' read-only headers");
}
assertThatExceptionOfType(BeanInitializationException.class)
.isThrownBy(gpfb::afterPropertiesSet)
.withMessageContaining("Messaging Gateway cannot override 'id' and 'timestamp' read-only headers");
}
// @Test

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.gateway;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import java.util.HashMap;
import java.util.Map;
@@ -39,6 +40,7 @@ import org.springframework.messaging.handler.annotation.Payload;
* @author Mark Fisher
* @author Gary Russell
* @author Artem Bilan
*
* @since 2.0
*/
public class GatewayProxyMessageMappingTests {
@@ -49,9 +51,8 @@ public class GatewayProxyMessageMappingTests {
@Before
public void initializeGateway() throws Exception {
GatewayProxyFactoryBean factoryBean = new GatewayProxyFactoryBean();
factoryBean.setServiceInterface(TestGateway.class);
public void initializeGateway() {
GatewayProxyFactoryBean factoryBean = new GatewayProxyFactoryBean(TestGateway.class);
factoryBean.setDefaultRequestChannel(channel);
factoryBean.setBeanName("testGateway");
GenericApplicationContext context = new GenericApplicationContext();
@@ -65,8 +66,8 @@ public class GatewayProxyMessageMappingTests {
@Test
public void payloadAndHeaderMapWithoutAnnotations() throws Exception {
Map<String, Object> m = new HashMap<String, Object>();
public void payloadAndHeaderMapWithoutAnnotations() {
Map<String, Object> m = new HashMap<>();
m.put("k1", "v1");
m.put("k2", "v2");
gateway.payloadAndHeaderMapWithoutAnnotations("foo", m);
@@ -78,8 +79,8 @@ public class GatewayProxyMessageMappingTests {
}
@Test
public void payloadAndHeaderMapWithAnnotations() throws Exception {
Map<String, Object> m = new HashMap<String, Object>();
public void payloadAndHeaderMapWithAnnotations() {
Map<String, Object> m = new HashMap<>();
m.put("k1", "v1");
m.put("k2", "v2");
gateway.payloadAndHeaderMapWithAnnotations("foo", m);
@@ -91,7 +92,7 @@ public class GatewayProxyMessageMappingTests {
}
@Test
public void headerValuesAndPayloadWithAnnotations() throws Exception {
public void headerValuesAndPayloadWithAnnotations() {
gateway.headerValuesAndPayloadWithAnnotations("headerValue1", "payloadValue", "headerValue2");
Message<?> result = channel.receive(0);
assertThat(result).isNotNull();
@@ -101,8 +102,8 @@ public class GatewayProxyMessageMappingTests {
}
@Test
public void mapOnly() throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
public void mapOnly() {
Map<String, Object> map = new HashMap<>();
map.put("k1", "v1");
map.put("k2", "v2");
gateway.mapOnly(map);
@@ -115,8 +116,8 @@ public class GatewayProxyMessageMappingTests {
@Test
public void twoMapsAndOneAnnotatedWithPayload() {
Map<String, Object> map1 = new HashMap<String, Object>();
Map<String, Object> map2 = new HashMap<String, Object>();
Map<String, Object> map1 = new HashMap<>();
Map<String, Object> map2 = new HashMap<>();
map1.put("k1", "v1");
map2.put("k2", "v2");
gateway.twoMapsAndOneAnnotatedWithPayload(map1, map2);
@@ -128,7 +129,7 @@ public class GatewayProxyMessageMappingTests {
}
@Test
public void payloadAnnotationAtMethodLevel() throws Exception {
public void payloadAnnotationAtMethodLevel() {
gateway.payloadAnnotationAtMethodLevel("foo", "bar");
Message<?> result = channel.receive(0);
assertThat(result).isNotNull();
@@ -136,7 +137,7 @@ public class GatewayProxyMessageMappingTests {
}
@Test
public void payloadAnnotationAtMethodLevelUsingBeanResolver() throws Exception {
public void payloadAnnotationAtMethodLevelUsingBeanResolver() {
GenericApplicationContext context = new GenericApplicationContext();
RootBeanDefinition gatewayDefinition = new RootBeanDefinition(GatewayProxyFactoryBean.class);
gatewayDefinition.getPropertyValues().add("defaultRequestChannel", channel);
@@ -155,7 +156,7 @@ public class GatewayProxyMessageMappingTests {
}
@Test
public void payloadAnnotationWithExpression() throws Exception {
public void payloadAnnotationWithExpression() {
gateway.payloadAnnotationWithExpression("foo");
Message<?> result = channel.receive(0);
assertThat(result).isNotNull();
@@ -163,7 +164,7 @@ public class GatewayProxyMessageMappingTests {
}
@Test
public void payloadAnnotationWithExpressionUsingBeanResolver() throws Exception {
public void payloadAnnotationWithExpressionUsingBeanResolver() {
GenericApplicationContext context = new GenericApplicationContext();
RootBeanDefinition gatewayDefinition = new RootBeanDefinition(GatewayProxyFactoryBean.class);
gatewayDefinition.getPropertyValues().add("defaultRequestChannel", channel);
@@ -186,28 +187,32 @@ public class GatewayProxyMessageMappingTests {
context.close();
}
@Test(expected = MessagingException.class)
@Test
public void twoMapsWithoutAnnotations() {
Map<String, Object> map1 = new HashMap<String, Object>();
Map<String, Object> map2 = new HashMap<String, Object>();
Map<String, Object> map1 = new HashMap<>();
Map<String, Object> map2 = new HashMap<>();
map1.put("k1", "v1");
map2.put("k2", "v2");
gateway.twoMapsWithoutAnnotations(map1, map2);
assertThatExceptionOfType(MessagingException.class)
.isThrownBy(() -> this.gateway.twoMapsWithoutAnnotations(map1, map2));
}
@Test(expected = MessagingException.class)
public void twoPayloads() throws Exception {
gateway.twoPayloads("won't", "work");
@Test
public void twoPayloads() {
assertThatExceptionOfType(MessagingException.class)
.isThrownBy(() -> this.gateway.twoPayloads("won't", "work"));
}
@Test(expected = MessagingException.class)
public void payloadAndHeaderAnnotationsOnSameParameter() throws Exception {
gateway.payloadAndHeaderAnnotationsOnSameParameter("oops");
@Test
public void payloadAndHeaderAnnotationsOnSameParameter() {
assertThatExceptionOfType(MessagingException.class)
.isThrownBy(() -> this.gateway.payloadAndHeaderAnnotationsOnSameParameter("oops"));
}
@Test(expected = MessagingException.class)
public void payloadAndHeadersAnnotationsOnSameParameter() throws Exception {
gateway.payloadAndHeadersAnnotationsOnSameParameter(new HashMap<String, Object>());
@Test
public void payloadAndHeadersAnnotationsOnSameParameter() {
assertThatExceptionOfType(MessagingException.class)
.isThrownBy(() -> this.gateway.payloadAndHeadersAnnotationsOnSameParameter(new HashMap<>()));
}
@@ -261,6 +266,7 @@ public class GatewayProxyMessageMappingTests {
}
return sum;
}
}
}

View File

@@ -14,7 +14,7 @@
<channel id="requestChannel"/>
<beans:bean id="proxy" class="org.springframework.integration.gateway.GatewayProxyFactoryBean">
<beans:property name="serviceInterface" value="org.springframework.integration.gateway.TestService"/>
<beans:constructor-arg value="org.springframework.integration.gateway.TestService"/>
<beans:property name="defaultRequestChannel" ref="requestChannel"/>
</beans:bean>

View File

@@ -12,7 +12,7 @@
<service-activator ref="testHandler" input-channel="requestChannel"/>
<beans:bean id="proxy" class="org.springframework.integration.gateway.GatewayProxyFactoryBean">
<beans:property name="serviceInterface" value="org.springframework.integration.gateway.TestService"/>
<beans:constructor-arg value="org.springframework.integration.gateway.TestService"/>
<beans:property name="defaultRequestChannel" ref="requestChannel"/>
</beans:bean>

View File

@@ -19,7 +19,7 @@
<service-activator ref="handler" input-channel="requestChannel" output-channel="replyChannel"/>
<beans:bean id="proxy" class="org.springframework.integration.gateway.GatewayProxyFactoryBean">
<beans:property name="serviceInterface" value="org.springframework.integration.gateway.TestService"/>
<beans:constructor-arg value="org.springframework.integration.gateway.TestService"/>
<beans:property name="defaultRequestChannel" ref="requestChannel"/>
<beans:property name="defaultReplyChannel" ref="replyChannel"/>
<beans:property name="defaultRequestTimeout" value="10000"/>

View File

@@ -44,9 +44,12 @@ import org.springframework.messaging.support.GenericMessage
import org.springframework.messaging.support.MessageBuilder
import org.springframework.test.annotation.DirtiesContext
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig
import reactor.core.publisher.Mono
import reactor.test.StepVerifier
import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.function.Function
/**
* @author Artem Bilan
@@ -120,6 +123,18 @@ class FunctionsTests {
assertThat(this.fromSupplierQueue.receive(10_000)).isNotNull()
}
@Autowired
private lateinit var monoFunction: Function<String, Mono<Message<*>>>
@Test
fun `verify Mono gateway`() {
val mono = this.monoFunction.apply("test")
StepVerifier.create(mono.map(Message<*>::getPayload).cast(String::class.java))
.expectNext("TEST")
.verifyComplete()
}
@Configuration
@EnableIntegration
class Config {
@@ -155,6 +170,14 @@ class FunctionsTests {
IntegrationFlows.from<String>({ "bar" }) { e -> e.poller { p -> p.fixedDelay(10).maxMessagesPerPoll(1) } }
.channel { c -> c.queue("fromSupplierQueue") }
.get()
@Bean
fun monoFunctionGateway() =
IntegrationFlows.from(MonoFunction::class.java)
.handle<String>({ p, _ -> Mono.just(p).map(String::toUpperCase) }) { e -> e.async(true) }
.get()
}
interface MonoFunction : Function<String, Mono<Message<*>>>
}