diff --git a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParser.java b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParser.java
index 7c1c95e919..58bc7315ba 100644
--- a/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParser.java
+++ b/spring-integration-amqp/src/main/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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
@@ -29,6 +29,7 @@ import org.springframework.util.StringUtils;
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Gunnar Hillert
+ * @author Artem Bilan
*
* @since 2.1
*/
@@ -53,6 +54,7 @@ public class AmqpOutboundGatewayParser extends AbstractConsumerEndpointParser {
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "routing-key");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "routing-key-expression");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "return-channel");
diff --git a/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-3.0.xsd b/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-3.0.xsd
index 90089d4475..f07cf095f8 100644
--- a/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-3.0.xsd
+++ b/spring-integration-amqp/src/main/resources/org/springframework/integration/amqp/config/spring-integration-amqp-3.0.xsd
@@ -199,6 +199,15 @@
]]>
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml
index 63ec21901b..f42ad1aefc 100644
--- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests-context.xml
@@ -40,6 +40,7 @@
routing-key="si.test.binding"
amqp-template="amqpTemplate"
order="5"
+ requires-reply="false"
mapped-request-headers="foo*"
mapped-reply-headers="bar*"/>
diff --git a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java
index 15da4042a5..73a33b8c37 100644
--- a/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java
+++ b/spring-integration-amqp/src/test/java/org/springframework/integration/amqp/config/AmqpOutboundGatewayParserTests.java
@@ -16,6 +16,7 @@
package org.springframework.integration.amqp.config;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
@@ -62,7 +63,7 @@ public class AmqpOutboundGatewayParserTests {
Object edc = context.getBean("rabbitGateway");
AmqpOutboundEndpoint gateway = TestUtils.getPropertyValue(edc, "handler", AmqpOutboundEndpoint.class);
assertEquals(5, gateway.getOrder());
- assertTrue(context.containsBean("rabbitGateway"));
+ assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
assertEquals(context.getBean("fromRabbit"), TestUtils.getPropertyValue(gateway, "outputChannel"));
assertEquals("amqp:outbound-gateway", gateway.getComponentType());
MessageChannel returnChannel = context.getBean("returnChannel", MessageChannel.class);
@@ -81,6 +82,8 @@ public class AmqpOutboundGatewayParserTests {
AmqpOutboundEndpoint endpoint = TestUtils.getPropertyValue(eventDrivernConsumer, "handler", AmqpOutboundEndpoint.class);
+ assertFalse(TestUtils.getPropertyValue(endpoint, "requiresReply", Boolean.class));
+
Field amqpTemplateField = ReflectionUtils.findField(AmqpOutboundEndpoint.class, "amqpTemplate");
amqpTemplateField.setAccessible(true);
RabbitTemplate amqpTemplate = TestUtils.getPropertyValue(endpoint, "amqpTemplate", RabbitTemplate.class);
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundGatewayParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundGatewayParser.java
index e5bcacff75..a593e4a735 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundGatewayParser.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -26,6 +26,7 @@ import org.springframework.util.StringUtils;
* Base class for url-based outbound gateway parsers.
*
* @author Mark Fisher
+ * @author Artem Bilan
*/
public abstract class AbstractOutboundGatewayParser extends AbstractConsumerEndpointParser {
@@ -45,6 +46,7 @@ public abstract class AbstractOutboundGatewayParser extends AbstractConsumerEndp
if (StringUtils.hasText(replyChannel)) {
builder.addPropertyReference("replyChannel", replyChannel);
}
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
this.postProcessGateway(builder, element, parserContext);
return builder;
}
diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd
index feb0ffd0ab..071527fdc8 100644
--- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd
+++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-3.0.xsd
@@ -1075,7 +1075,6 @@
-
@@ -1083,10 +1082,8 @@
Specify whether the service method must return a non-null value. This value will be
- FALSE by
- default, but if set to TRUE, a MessageHandlingException will be thrown when
- the underlying service method (or
- expression) returns a NULL value.
+ 'false' by default, but if set to 'true', a ReplyRequiredException will be thrown when
+ the underlying service method (or expression) returns a null value.
@@ -3153,9 +3150,9 @@ is provided, the return value is expected to match a channel name exactly.
- Specify whether the splitter method must return a non-null value. This value will be
- FALSE by default, but if set to TRUE, a MessageHandlingException will be thrown when
- the underlying service method (or expression) returns a NULL value.
+ Specify whether the service method must return a non-null value. This value will be
+ 'false' by default, but if set to 'true', a ReplyRequiredException will be thrown when
+ the underlying service method (or expression) returns a null value.
diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractRemoteFileOutboundGatewayParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractRemoteFileOutboundGatewayParser.java
index c869b02ac3..ca68e7f0b4 100644
--- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractRemoteFileOutboundGatewayParser.java
+++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractRemoteFileOutboundGatewayParser.java
@@ -27,6 +27,7 @@ import org.springframework.util.StringUtils;
* @author Gary Russell
* @author Oleg Zhurakousky
* @author Gunnar Hillert
+ * @author Artem Bilan
*
* @since 2.1
*/
@@ -54,8 +55,7 @@ public abstract class AbstractRemoteFileOutboundGatewayParser extends AbstractCo
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "local-directory");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-create-local-directory");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "order");
- IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "rename-expression");
- return builder;
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "rename-expression"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply"); return builder;
}
protected void configureFilter(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java
index 7209ebb0c6..284b76a4f5 100644
--- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java
+++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -44,6 +44,7 @@ public class FileOutboundGatewayParser extends AbstractConsumerEndpointParser {
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder handlerBuilder = FileWritingMessageHandlerBeanDefinitionBuilder.configure(element, true, parserContext);
IntegrationNamespaceUtils.setValueIfAttributeDefined(handlerBuilder, element, "reply-timeout", "sendTimeout");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(handlerBuilder, element, "requires-reply");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(handlerBuilder, element, "reply-channel", "outputChannel");
return handlerBuilder;
}
diff --git a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-3.0.xsd b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-3.0.xsd
index ab6855010e..c74b77fbc9 100644
--- a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-3.0.xsd
+++ b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-3.0.xsd
@@ -394,6 +394,15 @@ Only files matching this regular expression will be picked up by this adapter.
]]>
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml
index b105a54cb0..ae2ce6fc6a 100644
--- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml
+++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml
@@ -19,7 +19,7 @@
+ auto-startup="false" order="777" filename-generator-expression="'foo.txt'" requires-reply="false">
@@ -28,7 +28,7 @@
+ directory="test" requires-reply="false"/>
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml
index 3a9a7fbb27..152d56cc9a 100644
--- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests-context.xml
@@ -43,6 +43,7 @@
command-options="-P"
expression="payload"
order="2"
+ requires-reply="false"
>
diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java
index 6178f01b7c..43d8229ed9 100644
--- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java
+++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundGatewayParserTests.java
@@ -84,6 +84,7 @@ public class FtpOutboundGatewayParserTests {
Long sendTimeout = TestUtils.getPropertyValue(gateway, "messagingTemplate.sendTimeout", Long.class);
assertEquals(Long.valueOf(777), sendTimeout);
+ assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
}
@Test
@@ -101,6 +102,7 @@ public class FtpOutboundGatewayParserTests {
Set options = TestUtils.getPropertyValue(gateway, "options", Set.class);
assertTrue(options.contains(Option.PRESERVE_TIMESTAMP));
gateway.handleMessage(new GenericMessage("foo"));
+ assertFalse(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
assertEquals(1, adviceCalled);
}
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java
index 864b264959..378b57aed6 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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
@@ -24,6 +24,7 @@ import org.w3c.dom.Element;
/**
* @author Dave Syer
* @author Gunnar Hillert
+ * @author Artem Bilan
*
* @since 2.0
*
@@ -48,8 +49,7 @@ public class JdbcOutboundGatewayParser extends AbstractConsumerEndpointParser {
String updateQuery = IntegrationNamespaceUtils.getTextFromAttributeOrNestedElement(element, "update",
parserContext);
- BeanDefinitionBuilder builder = BeanDefinitionBuilder
- .genericBeanDefinition(JdbcOutboundGateway.class);
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(JdbcOutboundGateway.class);
if (refToDataSourceSet) {
builder.addConstructorArgReference(dataSourceRef);
}
@@ -68,6 +68,7 @@ public class JdbcOutboundGatewayParser extends AbstractConsumerEndpointParser {
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "max-rows-per-poll");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "keys-generated");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
String replyChannel = element.getAttribute("reply-channel");
if (StringUtils.hasText(replyChannel)) {
diff --git a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParser.java b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParser.java
index ae73e34d29..2d72923c5b 100644
--- a/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParser.java
+++ b/spring-integration-jdbc/src/main/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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
@@ -27,6 +27,7 @@ import org.w3c.dom.Element;
/**
* @author Gunnar Hillert
+ * @author Artem Bilan
* @since 2.1
*
*/
@@ -62,6 +63,7 @@ public class StoredProcOutboundGatewayParser extends AbstractConsumerEndpointPar
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expect-single-result");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
String replyChannel = element.getAttribute("reply-channel");
if (StringUtils.hasText(replyChannel)) {
diff --git a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd
index 1282510588..78007adeb0 100644
--- a/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd
+++ b/spring-integration-jdbc/src/main/resources/org/springframework/integration/jdbc/config/spring-integration-jdbc-3.0.xsd
@@ -502,6 +502,15 @@
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
@@ -967,6 +976,15 @@
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'false' by default, if it set to 'true', a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
index e4ee01c087..00cdd7b42a 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/JdbcOutboundGatewayParserTests.java
@@ -14,14 +14,17 @@ package org.springframework.integration.jdbc.config;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ApplicationContext;
@@ -29,6 +32,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.endpoint.PollingConsumer;
@@ -75,6 +79,7 @@ public class JdbcOutboundGatewayParserTests {
assertEquals("bar", payload.get("name"));
JdbcOutboundGateway gateway = context.getBean("jdbcGateway.handler", JdbcOutboundGateway.class);
assertEquals(23, TestUtils.getPropertyValue(gateway, "order"));
+ Assert.assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
Object gw = context.getBean("jdbcGateway");
assertEquals(1, adviceCalled);
}
@@ -204,11 +209,15 @@ public class JdbcOutboundGatewayParserTests {
@Test //INT-1029
public void testOutboundGatewayInsideChain() {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("handlingMapPayloadJdbcOutboundGatewayTest.xml", getClass());
- //INT-2755
- assertNotNull(context.getBean("org.springframework.integration.handler.MessageHandlerChain#0$child.jdbc-outbound-gateway-within-chain.handler",
- JdbcOutboundGateway.class));
+
+ JdbcOutboundGateway jdbcMessageHandler =
+ context.getBean("org.springframework.integration.handler.MessageHandlerChain#0$child.jdbc-outbound-gateway-within-chain.handler",
+ JdbcOutboundGateway.class);
MessageChannel channel = context.getBean("jdbcOutboundGatewayInsideChain", MessageChannel.class);
+
+ assertFalse(TestUtils.getPropertyValue(jdbcMessageHandler, "requiresReply", Boolean.class));
+
channel.send(MessageBuilder.withPayload(Collections.singletonMap("foo", "bar")).build());
PollableChannel outbound = context.getBean("replyChannel", PollableChannel.class);
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
index 83077d8a2b..02951a1da8 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/StoredProcOutboundGatewayParserTests.java
@@ -47,6 +47,7 @@ import org.springframework.jdbc.core.SqlParameter;
/**
* @author Gunnar Hillert
* @author Gary Russell
+ * @author Artem Bilan
* @since 2.1
*
*/
@@ -65,6 +66,7 @@ public class StoredProcOutboundGatewayParserTests {
DirectFieldAccessor accessor = new DirectFieldAccessor(this.outboundGateway);
Object source = accessor.getPropertyValue("handler");
accessor = new DirectFieldAccessor(source);
+ assertEquals(Boolean.TRUE, accessor.getPropertyValue("requiresReply"));
source = accessor.getPropertyValue("executor");
accessor = new DirectFieldAccessor(source);
Expression storedProcedureName = (Expression) accessor.getPropertyValue("storedProcedureNameExpression");
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml
index fa1e44b942..6b2ff1ccc1 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/handlingMapPayloadJdbcOutboundGatewayTest.xml
@@ -26,7 +26,7 @@
+ data-source="dataSource" requires-reply="false"/>
diff --git a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcOutboundGatewayParserTest.xml b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcOutboundGatewayParserTest.xml
index 2592380e0e..dfb4f2b367 100644
--- a/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcOutboundGatewayParserTest.xml
+++ b/spring-integration-jdbc/src/test/java/org/springframework/integration/jdbc/config/storedProcOutboundGatewayParserTest.xml
@@ -18,7 +18,7 @@
data-source="datasource" auto-startup="true" id="storedProcedureOutboundGateway"
ignore-column-meta-data="false" is-function="false"
skip-undeclared-results="false" order="2" reply-channel="replyChannel"
- reply-timeout="555" return-value-required="true">
+ reply-timeout="555" return-value-required="true" requires-reply="true">
diff --git a/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java b/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java
index 96ec1cb690..d587dab3fe 100644
--- a/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java
+++ b/spring-integration-jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java
@@ -33,6 +33,7 @@ import org.w3c.dom.Element;
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Gary Russell
+ * @author Artem Bilan
*/
public class JmsOutboundGatewayParser extends AbstractConsumerEndpointParser {
@@ -65,6 +66,7 @@ public class JmsOutboundGatewayParser extends AbstractConsumerEndpointParser {
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "time-to-live");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "priority");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "explicit-qos-enabled");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
String deliveryPersistent = element.getAttribute("delivery-persistent");
if (StringUtils.hasText(deliveryPersistent)) {
@@ -119,7 +121,7 @@ public class JmsOutboundGatewayParser extends AbstractConsumerEndpointParser {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(JmsOutboundGateway.ReplyContainerProperties.class);
Integer acknowledgeMode = JmsAdapterParserUtils.parseAcknowledgeMode(element, parserContext);
if (acknowledgeMode != null) {
- if (acknowledgeMode.intValue() == JmsAdapterParserUtils.SESSION_TRANSACTED) {
+ if (JmsAdapterParserUtils.SESSION_TRANSACTED == acknowledgeMode) {
builder.addPropertyValue("sessionTransacted", Boolean.TRUE);
}
else {
diff --git a/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-3.0.xsd b/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-3.0.xsd
index 10c1ff8a21..dc4b0470b7 100644
--- a/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-3.0.xsd
+++ b/spring-integration-jms/src/main/resources/org/springframework/integration/jms/config/spring-integration-jms-3.0.xsd
@@ -1065,6 +1065,15 @@
]]>
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
@@ -1469,4 +1478,4 @@
-
\ No newline at end of file
+
diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java
index 31762490c6..deabab1b24 100644
--- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java
+++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsOutboundGatewayParserTests.java
@@ -128,6 +128,7 @@ public class JmsOutboundGatewayParserTests {
new DirectFieldAccessor(endpoint).getPropertyValue("handler"));
Object order = accessor.getPropertyValue("order");
assertEquals(99, order);
+ assertEquals(Boolean.TRUE, accessor.getPropertyValue("requiresReply"));
}
@Test
diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml
index f406f83c19..93630ff89d 100644
--- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml
+++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithDeliveryPersistent.xml
@@ -14,7 +14,7 @@
http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd">
-
+
+ auto-startup="false"
+ requires-reply="false">
diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithOrder.xml b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithOrder.xml
index e7a6095ac1..def46dfc37 100644
--- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithOrder.xml
+++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/jmsOutboundGatewayWithOrder.xml
@@ -15,7 +15,7 @@
+ order="99" requires-reply="true"/>
diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayParser.java b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayParser.java
index 7c78355656..0c2222d862 100644
--- a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayParser.java
+++ b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -18,6 +18,7 @@ package org.springframework.integration.jmx.config;
import org.w3c.dom.Element;
+import org.springframework.integration.jmx.OperationInvokingMessageHandler;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
@@ -25,10 +26,11 @@ import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
/**
* @author Oleg Zhurakousky
+ * @author Artem Bilan
* @since 2.0
*/
public class OperationInvokingOutboundGatewayParser extends AbstractConsumerEndpointParser {
-
+
@Override
protected String getInputChannelAttributeName() {
return "request-channel";
@@ -36,12 +38,12 @@ public class OperationInvokingOutboundGatewayParser extends AbstractConsumerEndp
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
- BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
- "org.springframework.integration.jmx.OperationInvokingMessageHandler");
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(OperationInvokingMessageHandler.class);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "server");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "object-name");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "operation-name");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
return builder;
}
diff --git a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd
index fab13b0289..ceaae8ef8b 100644
--- a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd
+++ b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-3.0.xsd
@@ -47,6 +47,15 @@
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml
index 64482bbe5d..f412ab7bd6 100644
--- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml
@@ -29,18 +29,19 @@
object-name="org.springframework.integration.jmx.config:type=TestBean,name=testBeanGateway"
operation-name="testWithReturn">
-
+
-
-
+
+ operation-name="test"
+ requires-reply="false"/>
diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests.java b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests.java
index b4e985b72c..618b54175c 100644
--- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests.java
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -17,6 +17,7 @@
package org.springframework.integration.jmx.config;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.util.List;
@@ -27,10 +28,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
+import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
+import org.springframework.integration.jmx.OperationInvokingMessageHandler;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
+import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -61,6 +65,12 @@ public class OperationInvokingOutboundGatewayTests {
@Autowired
private TestBean testBean;
+ @Autowired
+ @Qualifier("operationInvokingWithinChain.handler")
+ private MessageHandler operationInvokingWithinChain;
+
+
+
private static volatile int adviceCalled;
@After
@@ -89,8 +99,14 @@ public class OperationInvokingOutboundGatewayTests {
assertEquals(3, testBean.messages.size());
}
- @Test //INT-1029
+ @Test //INT-1029, INT-2822
public void testOutboundGatewayInsideChain() throws Exception {
+ List handlers = TestUtils.getPropertyValue(this.operationInvokingWithinChain, "handlers", List.class);
+ assertEquals(1, handlers.size());
+ Object handler = handlers.get(0);
+ assertTrue(handler instanceof OperationInvokingMessageHandler);
+ assertTrue(TestUtils.getPropertyValue(handler, "requiresReply", Boolean.class));
+
jmxOutboundGatewayInsideChain.send(MessageBuilder.withPayload("1").build());
assertEquals(1, ((List>) withReplyChannelOutput.receive().getPayload()).size());
jmxOutboundGatewayInsideChain.send(MessageBuilder.withPayload("2").build());
@@ -99,7 +115,7 @@ public class OperationInvokingOutboundGatewayTests {
assertEquals(3, ((List>) withReplyChannelOutput.receive().getPayload()).size());
}
- public static class FooADvice extends AbstractRequestHandlerAdvice {
+ public static class FooAdvice extends AbstractRequestHandlerAdvice {
@Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
diff --git a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/AbstractJpaOutboundGatewayParser.java b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/AbstractJpaOutboundGatewayParser.java
index dc23e12eee..a6d662858b 100644
--- a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/AbstractJpaOutboundGatewayParser.java
+++ b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/config/xml/AbstractJpaOutboundGatewayParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -30,6 +30,7 @@ import org.w3c.dom.Element;
* The Abstract Parser for the JPA Outbound Gateways.
*
* @author Gunnar Hillert
+ * @author Artem Bilan
*
* @since 2.2
*
@@ -46,6 +47,7 @@ public abstract class AbstractJpaOutboundGatewayParser extends AbstractConsumerE
.genericBeanDefinition(JpaOutboundGatewayFactoryBean.class);
IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaOutboundGatewayBuilder, gatewayElement, "reply-timeout");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(jpaOutboundGatewayBuilder, gatewayElement, "requires-reply");
final String replyChannel = gatewayElement.getAttribute("reply-channel");
diff --git a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java
index 9700ba77de..f3c39fb9b7 100644
--- a/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java
+++ b/spring-integration-jpa/src/main/java/org/springframework/integration/jpa/outbound/JpaOutboundGatewayFactoryBean.java
@@ -70,6 +70,8 @@ public class JpaOutboundGatewayFactoryBean extends AbstractFactoryBean
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java
index ac331ff70a..06b9ff3141 100644
--- a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java
+++ b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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
@@ -13,18 +13,24 @@
package org.springframework.integration.jpa.config.xml;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import org.aopalliance.intercept.MethodInvocation;
import org.junit.After;
import org.junit.Test;
+import org.mockito.Mockito;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
+import org.springframework.integration.MessagingException;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.endpoint.EventDrivenConsumer;
+import org.springframework.integration.handler.ReplyRequiredException;
import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice;
import org.springframework.integration.jpa.core.JpaExecutor;
import org.springframework.integration.jpa.core.JpaOperations;
@@ -42,14 +48,12 @@ import org.springframework.integration.test.util.TestUtils;
* @since 2.2
*
*/
-public class JpaOutboundGatewayParserTests {
+public class JpaOutboundGatewayParserTests extends AbstractRequestHandlerAdvice {
private ConfigurableApplicationContext context;
private EventDrivenConsumer consumer;
- private static volatile int adviceCalled;
-
@Test
public void testRetrievingJpaOutboundGatewayParser() throws Exception {
setUp("JpaOutboundGatewayParserTests.xml", getClass(), "retrievingJpaOutboundGateway");
@@ -69,6 +73,7 @@ public class JpaOutboundGatewayParserTests {
assertEquals(100, sendTimeout);
+ assertFalse(TestUtils.getPropertyValue(jpaOutboundGateway, "requiresReply", Boolean.class));
final JpaExecutor jpaExecutor = TestUtils.getPropertyValue(this.consumer, "handler.jpaExecutor", JpaExecutor.class);
@@ -87,7 +92,6 @@ public class JpaOutboundGatewayParserTests {
final Integer maxNumberOfResults = TestUtils.getPropertyValue(jpaExecutor, "maxNumberOfResults", Integer.class);
assertEquals(Integer.valueOf(55), maxNumberOfResults);
-
}
@Test
@@ -109,6 +113,8 @@ public class JpaOutboundGatewayParserTests {
assertEquals(100, sendTimeout);
+ assertFalse(TestUtils.getPropertyValue(jpaOutboundGateway, "requiresReply", Boolean.class));
+
final JpaExecutor jpaExecutor = TestUtils.getPropertyValue(this.consumer, "handler.jpaExecutor", JpaExecutor.class);
assertNotNull(jpaExecutor);
@@ -136,14 +142,22 @@ public class JpaOutboundGatewayParserTests {
}
@Test
- public void advised() throws Exception {
+ public void advised() throws Throwable {
setUp("JpaOutboundGatewayParserTests.xml", getClass(), "advised");
MessageHandler jpaOutboundGateway = context.getBean("advised.handler", MessageHandler.class);
+ FooAdvice advice = context.getBean("jpaFooAdvice", FooAdvice.class);
assertTrue(AopUtils.isAopProxy(jpaOutboundGateway));
- jpaOutboundGateway.handleMessage(new GenericMessage("foo"));
- assertEquals(1, adviceCalled);
+ try {
+ jpaOutboundGateway.handleMessage(new GenericMessage("foo"));
+ fail("expected ReplyRequiredException");
+ }
+ catch (MessagingException e) {
+ assertTrue(e instanceof ReplyRequiredException);
+ }
+
+ Mockito.verify(advice).doInvoke(Mockito.any(ExecutionCallback.class), Mockito.any(Object.class), Mockito.any(Message.class));
}
@Test
@@ -168,11 +182,16 @@ public class JpaOutboundGatewayParserTests {
consumer = this.context.getBean(gatewayId, EventDrivenConsumer.class);
}
+ @Override
+ protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
+ // Workaround for access to protected AbstractRequestHandlerAdvice.ExecutionCallback
+ return null;
+ }
+
public static class FooAdvice extends AbstractRequestHandlerAdvice {
@Override
protected Object doInvoke(ExecutionCallback callback, Object target, Message> message) throws Exception {
- adviceCalled++;
return null;
}
diff --git a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml
index 2a468fc56e..3471e9e2f3 100644
--- a/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml
+++ b/spring-integration-jpa/src/test/java/org/springframework/integration/jpa/config/xml/JpaOutboundGatewayParserTests.xml
@@ -23,7 +23,8 @@
max-number-of-results="55"
request-channel="in"
reply-channel="out"
- reply-timeout="100"/>
+ reply-timeout="100"
+ requires-reply="false"/>
+ reply-timeout="100"
+ requires-reply="false"/>
-
+
+
+
+
+
+
+
diff --git a/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-3.0.xsd b/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-3.0.xsd
index 63524faa44..fe601f2fca 100644
--- a/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-3.0.xsd
+++ b/spring-integration-rmi/src/main/resources/org/springframework/integration/rmi/config/spring-integration-rmi-3.0.xsd
@@ -101,6 +101,15 @@
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java
index d6043ce61b..a7727dbc67 100644
--- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiOutboundGatewayParserTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 the original author or authors.
+ * Copyright 2002-2013 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.
@@ -17,7 +17,9 @@
package org.springframework.integration.rmi.config;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
@@ -60,6 +62,7 @@ public class RmiOutboundGatewayParserTests {
"rmiOutboundGatewayParserTests.xml", this.getClass());
RmiOutboundGateway gateway = context.getBean("gateway.handler", RmiOutboundGateway.class);
assertEquals(23, TestUtils.getPropertyValue(gateway, "order"));
+ assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
}
@Test
@@ -67,6 +70,9 @@ public class RmiOutboundGatewayParserTests {
ApplicationContext context = new ClassPathXmlApplicationContext(
"rmiOutboundGatewayParserTests.xml", this.getClass());
MessageChannel localChannel = (MessageChannel) context.getBean("advisedChannel");
+ RmiOutboundGateway gateway = context.getBean("advised.handler", RmiOutboundGateway.class);
+ assertFalse(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
+
localChannel.send(new GenericMessage("test"));
Message> result = testChannel.receive(1000);
assertNotNull(result);
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml
index 8254ef1ccb..5d966d2cd6 100644
--- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiOutboundGatewayParserTests.xml
@@ -23,6 +23,7 @@
@@ -30,7 +31,7 @@
-
+
diff --git a/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-3.0.xsd b/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-3.0.xsd
index 0387e63e7c..b8baa78a12 100644
--- a/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-3.0.xsd
+++ b/spring-integration-sftp/src/main/resources/org/springframework/integration/sftp/config/spring-integration-sftp-3.0.xsd
@@ -432,6 +432,15 @@
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'true' by default, and a ReplyRequiredException will be thrown when
+ the underlying service returns a null value.
+
+
+
diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml
index bbb8f8b56a..03434774fe 100644
--- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml
+++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests-context.xml
@@ -43,6 +43,7 @@
command-options="-P"
expression="payload"
order="2"
+ requires-reply="false"
/>
diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java
index 165d8f4d69..de91c54377 100644
--- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java
+++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/SftpOutboundGatewayParserTests.java
@@ -73,6 +73,7 @@ public class SftpOutboundGatewayParserTests {
assertNotNull(TestUtils.getPropertyValue(gateway, "outputChannel"));
assertEquals(new File("local-test-dir"), TestUtils.getPropertyValue(gateway, "localDirectory"));
assertFalse((Boolean) TestUtils.getPropertyValue(gateway, "autoCreateLocalDirectory"));
+ assertTrue(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
assertNotNull(TestUtils.getPropertyValue(gateway, "filter"));
assertEquals(Command.LS, TestUtils.getPropertyValue(gateway, "command"));
@SuppressWarnings("unchecked")
@@ -95,6 +96,7 @@ public class SftpOutboundGatewayParserTests {
assertEquals(new File("local-test-dir"), TestUtils.getPropertyValue(gateway, "localDirectory"));
assertFalse((Boolean) TestUtils.getPropertyValue(gateway, "autoCreateLocalDirectory"));
assertEquals(Command.GET, TestUtils.getPropertyValue(gateway, "command"));
+ assertFalse(TestUtils.getPropertyValue(gateway, "requiresReply", Boolean.class));
@SuppressWarnings("unchecked")
Set options = TestUtils.getPropertyValue(gateway, "options", Set.class);
assertTrue(options.contains(Option.PRESERVE_TIMESTAMP));
diff --git a/spring-integration-ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java b/spring-integration-ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java
index 431dbd2c56..ccb8d77e7d 100644
--- a/spring-integration-ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java
+++ b/spring-integration-ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java
@@ -83,6 +83,7 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout", "sendTimeout");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-empty-responses");
this.postProcessGateway(builder, element, parserContext);
diff --git a/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-3.0.xsd b/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-3.0.xsd
index 156d307e3a..2c87344730 100644
--- a/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-3.0.xsd
+++ b/spring-integration-ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-3.0.xsd
@@ -87,6 +87,16 @@
]]>
+
+
+
+ Specify whether this outbound gateway must return a non-null value. This value is
+ 'false' by default, otherwise a ReplyRequiredException will be thrown when
+ the underlying service returns a null value, or an empty String (if
+ 'ignore-empty-responses' is 'true').
+
+
+
@@ -456,4 +468,4 @@ this list can also be simple patterns to be matched against the header names (e.
-
\ No newline at end of file
+
diff --git a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java
index 6f32183bcd..aaed1d3cba 100644
--- a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java
+++ b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java
@@ -17,13 +17,15 @@
package org.springframework.integration.ws.config;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import java.net.URI;
import java.util.List;
+import org.junit.Assert;
import org.junit.Test;
+
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.ApplicationContext;
@@ -72,6 +74,7 @@ public class WebServiceOutboundGatewayParserTests {
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
Object expected = context.getBean("outputChannel");
assertEquals(expected, accessor.getPropertyValue("outputChannel"));
+ Assert.assertEquals(Boolean.FALSE, accessor.getPropertyValue("requiresReply"));
@SuppressWarnings("unchecked")
List requestHeaders = TestUtils.getPropertyValue(endpoint, "handler.headerMapper.requestHeaderNames", List.class);
@@ -96,18 +99,20 @@ public class WebServiceOutboundGatewayParserTests {
assertEquals(SimpleWebServiceOutboundGateway.class, gateway.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
assertEquals(Boolean.TRUE, accessor.getPropertyValue("ignoreEmptyResponses"));
+ Assert.assertEquals(Boolean.FALSE, accessor.getPropertyValue("requiresReply"));
}
@Test
public void simpleGatewayWithIgnoreEmptyResponses() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"simpleWebServiceOutboundGatewayParserTests.xml", this.getClass());
- AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithIgnoreEmptyResponsesFalse");
+ AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithIgnoreEmptyResponsesFalseAndRequiresReplyTrue");
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
assertEquals(SimpleWebServiceOutboundGateway.class, gateway.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
assertEquals(Boolean.FALSE, accessor.getPropertyValue("ignoreEmptyResponses"));
+ Assert.assertEquals(Boolean.TRUE, accessor.getPropertyValue("requiresReply"));
}
@Test
diff --git a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml
index 80a615ded9..49485a95ce 100644
--- a/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml
+++ b/spring-integration-ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml
@@ -31,10 +31,11 @@
mapped-request-headers="testRequest"
mapped-reply-headers="testReply"/>
-
+ ignore-empty-responses="false"
+ requires-reply="true"/>
.
+
+ 'requires-reply' Attribute for Outbound Gateways
+
+ All Outbound Gateways (e.g. <jdbc:outbound-gateway/> or <jms:outbound-gateway/>)
+ are designed for 'request-reply' scenarios. A response is expected from the external service and
+ will be published to the reply-channel, or the replyChannel message header.
+ However, there are some cases where the external system might not always return a
+ result, e.g. a <jdbc:outbound-gateway/>, when a SELECT ends with an empty ResultSet
+ or, say, a Web Service is One-Way. An option is therefore needed to configure whether or not a
+ reply is required.
+ For this purpose, the requires-reply attribute has been introduced for Outbound Gateway components.
+ In most cases, the default value for requires-reply is true and, if there is not any result,
+ a ReplyRequiredException will be thrown. Changing the value to false
+ means that, if an external service doesn't return anything, the message-flow will end at that point,
+ similar to an Outbound Channel Adapter.
+
+
+ The WebService outbound gateway has an additional attribute ignore-empty-responses; this is used to
+ treat an empty String response as if no response was received. It is true by default but can be set to false to
+ allow the application to receive an empty String in the reply message payload. When the attribute is true an empty
+ string is treated as no response for the purposes of the requires-reply attribute.
+ requires-reply is false by default for the WebService outbound gateway.
+
+
+ Note, the requiresReply property was previously present in the AbstractReplyProducingMessageHandler
+ but set to false, and there wasn't any way to configure it on Outbound Gateways using the XML namespace.
+
+
+ Previously, a gateway receiving no reply would silently end the flow (with a DEBUG log message); with this change an
+ exception will now be thrown by default by most gateways. To revert to the previous behavior,
+ set requires-reply to false.
+
+