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 42c0449cdc..feb0ffd0ab 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
@@ -644,7 +644,7 @@
+
+
+
+
+
+
+
+
+ If a downstream exception is thrown and an error-channel is specified,
+ the MessagingException will be sent to this channel. Otherwise, any such exception
+ will be propagated to the calling system.
+
+
+
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/BackToBackTests-context.xml b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/BackToBackTests-context.xml
new file mode 100644
index 0000000000..43ff846688
--- /dev/null
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/BackToBackTests-context.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/BackToBackTests.java b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/BackToBackTests.java
new file mode 100644
index 0000000000..c2c92e5ebc
--- /dev/null
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/BackToBackTests.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.integration.rmi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.integration.Message;
+import org.springframework.integration.core.PollableChannel;
+import org.springframework.integration.core.SubscribableChannel;
+import org.springframework.integration.message.GenericMessage;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Gary Russell
+ * @since 3.0
+ *
+ */
+@ContextConfiguration
+@RunWith(SpringJUnit4ClassRunner.class)
+public class BackToBackTests {
+
+ @Autowired
+ private SubscribableChannel good;
+
+ @Autowired
+ private SubscribableChannel bad;
+
+ @Autowired
+ private SubscribableChannel ugly;
+
+ @Autowired
+ private PollableChannel reply;
+
+ @Autowired
+ private AbstractApplicationContext context;
+
+ @Test
+ public void testGood() {
+ good.send(new GenericMessage("foo"));
+ Message> reply = this.reply.receive(0);
+ assertNotNull(reply);
+ assertEquals("reply:foo", reply.getPayload());
+ }
+
+ @Test
+ public void testBad() {
+ bad.send(new GenericMessage("foo"));
+ Message> reply = this.reply.receive(0);
+ assertNotNull(reply);
+ assertEquals("error:foo", reply.getPayload());
+ }
+
+ @Test
+ public void testUgly() {
+ context.setId("context");
+ try {
+ ugly.send(new GenericMessage("foo"));
+ fail("Expected exception");
+ }
+ catch (Exception e) {
+ assertEquals("Dispatcher has no subscribers for channel 'context.baz'.", e.getCause().getMessage());
+ }
+ }
+
+}
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/RmiOutboundGatewayTests.java b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/RmiOutboundGatewayTests.java
index af3aaa0275..e62acc6de5 100644
--- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/RmiOutboundGatewayTests.java
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/RmiOutboundGatewayTests.java
@@ -35,6 +35,7 @@ import org.springframework.integration.gateway.RequestReplyExchanger;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.support.MessageBuilder;
+import org.springframework.integration.test.util.SocketUtils;
import org.springframework.remoting.RemoteLookupFailureException;
import org.springframework.remoting.rmi.RmiServiceExporter;
@@ -44,7 +45,9 @@ import org.springframework.remoting.rmi.RmiServiceExporter;
*/
public class RmiOutboundGatewayTests {
- private final RmiOutboundGateway gateway = new RmiOutboundGateway("rmi://localhost:1099/testRemoteHandler");
+ private final static int port = SocketUtils.findAvailableServerSocket(11099);
+
+ private final RmiOutboundGateway gateway = new RmiOutboundGateway("rmi://localhost:" + port + "/testRemoteHandler");
private final QueueChannel output = new QueueChannel(1);
@@ -59,6 +62,7 @@ public class RmiOutboundGatewayTests {
exporter.setService(new TestExchanger());
exporter.setServiceInterface(RequestReplyExchanger.class);
exporter.setServiceName("testRemoteHandler");
+ exporter.setRegistryPort(port);
exporter.afterPropertiesSet();
}
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiInboundGatewayParserTests.java b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiInboundGatewayParserTests.java
index 3fdc705991..565833433c 100644
--- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiInboundGatewayParserTests.java
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/RmiInboundGatewayParserTests.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.rmi.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
import org.junit.Test;
@@ -27,9 +28,11 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.rmi.RmiInboundGateway;
+import org.springframework.integration.test.util.TestUtils;
/**
* @author Mark Fisher
+ * @author Gary Russell
*/
public class RmiInboundGatewayParserTests {
@@ -71,9 +74,11 @@ public class RmiInboundGatewayParserTests {
public void gatewayWithHost() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"rmiInboundGatewayParserTests.xml", this.getClass());
- RmiInboundGateway gateway = (RmiInboundGateway) context.getBean("gatewayWithHost");
+ RmiInboundGateway gateway = (RmiInboundGateway) context.getBean("gatewayWithHostAndErrorChannel");
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
assertEquals("localhost", accessor.getPropertyValue("registryHost"));
+ assertSame(context.getBean("testErrorChannel"),
+ TestUtils.getPropertyValue(gateway, "errorChannel"));
}
@Test
diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiInboundGatewayParserTests.xml b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiInboundGatewayParserTests.xml
index b57c48fde8..1360f0568f 100644
--- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiInboundGatewayParserTests.xml
+++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/rmiInboundGatewayParserTests.xml
@@ -14,12 +14,15 @@
+
+
-
+
diff --git a/src/reference/docbook/rmi.xml b/src/reference/docbook/rmi.xml
index f29924550b..a1dca910e8 100644
--- a/src/reference/docbook/rmi.xml
+++ b/src/reference/docbook/rmi.xml
@@ -32,6 +32,13 @@
]]>
+
+ If you use an errorChannel on an inbound gateway, it would be normal for the error flow to return a result
+ (or throw an exception). This is because it is likely that there is a corresponding outbound gateway waiting for a
+ response of some kind. Consuming a message on the error flow, and not replying, will result in no reply at the inbound
+ gateway. Exceptions (on the main flow when there is no errorChannel, or on the error flow) will be propagated to the
+ corresponding inbound gateway.
+
@@ -47,7 +54,7 @@
registry-host="localhost"/>
+ registry-port="1234" error-channel="rmiErrorChannel"/>
]]>
diff --git a/src/reference/docbook/whats-new.xml b/src/reference/docbook/whats-new.xml
index fd05f895ae..3d0a09ac24 100644
--- a/src/reference/docbook/whats-new.xml
+++ b/src/reference/docbook/whats-new.xml
@@ -201,6 +201,13 @@
in addition to several other container attributes that were already available.
+
+ RMI Inbound Gateway
+
+ The RMI Inbound Gateway now supports an error-channel attribute. See
+ .
+
+
SqlReturnType support for Stored Procedure components