diff --git a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/JmxNamespaceHandler.java b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/JmxNamespaceHandler.java
index 6acc15dc54..323dc41046 100644
--- a/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/JmxNamespaceHandler.java
+++ b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/JmxNamespaceHandler.java
@@ -22,12 +22,14 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa
* Namespace handler for Spring Integration's jmx namespace.
*
* @author Mark Fisher
+ * @author Oleg Zhurakousky
* @since 2.0
*/
public class JmxNamespaceHandler extends AbstractIntegrationNamespaceHandler {
public void init() {
this.registerBeanDefinitionParser("operation-invoking-channel-adapter", new OperationInvokingChannelAdapterParser());
+ this.registerBeanDefinitionParser("operation-invoking-outbound-gateway", new OperationInvokingOutboundGatewayParser());
this.registerBeanDefinitionParser("attribute-polling-channel-adapter", new AttributePollingChannelAdapterParser());
this.registerBeanDefinitionParser("notification-listening-channel-adapter", new NotificationListeningChannelAdapterParser());
this.registerBeanDefinitionParser("notification-publishing-channel-adapter", new NotificationPublishingChannelAdapterParser());
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
new file mode 100644
index 0000000000..0799210fac
--- /dev/null
+++ b/spring-integration-jmx/src/main/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayParser.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2002-2010 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.jmx.config;
+
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.integration.config.xml.AbstractConsumerEndpointParser;
+import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
+import org.w3c.dom.Element;
+
+/**
+ * @author Oleg Zhurakousky
+ * @since 2.0
+ */
+public class OperationInvokingOutboundGatewayParser extends AbstractConsumerEndpointParser{
+
+ @Override
+ protected String getInputChannelAttributeName() {
+ return "request-channel";
+ }
+
+ @Override
+ protected BeanDefinitionBuilder parseHandler(Element element,
+ ParserContext parserContext) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(
+ "org.springframework.integration.jmx.OperationInvokingMessageHandler");
+ IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "mbean-server", "server");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-object-name");
+ IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-operation-name");
+ IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
+ return builder;
+ }
+
+}
diff --git a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.0.xsd b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.0.xsd
index 4b4cfcb9ab..dcab9bde80 100644
--- a/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.0.xsd
+++ b/spring-integration-jmx/src/main/resources/org/springframework/integration/jmx/config/spring-integration-jmx-2.0.xsd
@@ -37,6 +37,21 @@
+
+
+
+ Defines an outbound Gateway which allows for Message-driven invocation of managed operations that return values
+
+
+
+
+
+
+
+
+
+
+
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
new file mode 100644
index 0000000000..dbc4728ce2
--- /dev/null
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests-context.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
new file mode 100644
index 0000000000..a1347938e9
--- /dev/null
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/OperationInvokingOutboundGatewayTests.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2002-2010 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.jmx.config;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.integration.channel.PollableChannel;
+import org.springframework.integration.core.Message;
+import org.springframework.integration.core.MessageChannel;
+import org.springframework.integration.jmx.JmxHeaders;
+import org.springframework.integration.message.MessageBuilder;
+import org.springframework.integration.message.StringMessage;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * @author Oleg Zhurakousky
+ *
+ */
+@ContextConfiguration
+@RunWith(SpringJUnit4ClassRunner.class)
+public class OperationInvokingOutboundGatewayTests {
+ @Autowired
+ @Qualifier("noDefaultInput")
+ private MessageChannel noDefaultInput;
+
+ @Autowired
+ @Qualifier("noDefaultOutput")
+ private PollableChannel noDefaultOutput;
+ @Autowired
+ @Qualifier("noDefaultInputA")
+ private MessageChannel noDefaultInputA;
+
+ @Autowired
+ @Qualifier("noDefaultOutputA")
+ private PollableChannel noDefaultOutputA;
+
+ @Autowired
+ @Qualifier("defaultInput")
+ private MessageChannel defaultInput;
+
+ @Autowired
+ @Qualifier("defaultOutput")
+ private PollableChannel defaultOutput;
+
+ @Autowired
+ private TestBean testBeanForDefaultsGateway;
+
+ @Autowired
+ private TestBean testBeanForNoDefaultsGateway;
+ @After
+ public void resetLists() {
+ testBeanForDefaultsGateway.messages.clear();
+ testBeanForNoDefaultsGateway.messages.clear();
+ }
+
+ @Test
+ public void adapterWithoutNoDefaultsAndReturn() throws Exception {
+ noDefaultInput.send(createMessageWithHeadersForReturnCase("1"));
+ assertEquals(1, ((List>)noDefaultOutput.receive().getPayload()).size());
+ noDefaultInput.send(createMessageWithHeadersForReturnCase("2"));
+ assertEquals(2, ((List>)noDefaultOutput.receive().getPayload()).size());
+ noDefaultInput.send(createMessageWithHeadersForReturnCase("3"));
+ assertEquals(3, ((List>)noDefaultOutput.receive().getPayload()).size());
+ }
+
+ @Test
+ public void adapterWithoutNoDefaultsAndReturnAndReplyChannel() throws Exception {
+ noDefaultInputA.send(createMessageWithHeadersForReturnCaseAndReplyChannel("1", noDefaultOutputA));
+ assertEquals(1, ((List>)noDefaultOutputA.receive().getPayload()).size());
+ noDefaultInputA.send(createMessageWithHeadersForReturnCaseAndReplyChannel("2", noDefaultOutputA));
+ assertEquals(2, ((List>)noDefaultOutputA.receive().getPayload()).size());
+ noDefaultInputA.send(createMessageWithHeadersForReturnCaseAndReplyChannel("3", noDefaultOutputA));
+ assertEquals(3, ((List>)noDefaultOutputA.receive().getPayload()).size());
+ }
+
+ @Test
+ public void adapterWithoutDefaultsAndReturn() throws Exception {
+ defaultInput.send(new StringMessage("1"));
+ assertEquals(1, ((List>)defaultOutput.receive().getPayload()).size());
+ defaultInput.send(new StringMessage("2"));
+ assertEquals(2, ((List>)defaultOutput.receive().getPayload()).size());
+ defaultInput.send(new StringMessage("3"));
+ assertEquals(3, ((List>)defaultOutput.receive().getPayload()).size());
+ }
+
+ private static Message createMessageWithHeadersForReturnCase(String payload) {
+ String objectName = "org.springframework.integration.jmx.config:name=testBeanForNoDefaultsGateway,type=TestBean";
+ return MessageBuilder.withPayload(payload)
+ .setHeader(JmxHeaders.OBJECT_NAME, objectName)
+ .setHeader(JmxHeaders.OPERATION_NAME, "testWithReturn")
+ .build();
+ }
+
+ private static Message createMessageWithHeadersForReturnCaseAndReplyChannel(String payload, MessageChannel replyChannel) {
+ String objectName = "org.springframework.integration.jmx.config:name=testBeanForNoDefaultsGateway,type=TestBean";
+ return MessageBuilder.withPayload(payload)
+ .setHeader(JmxHeaders.OBJECT_NAME, objectName)
+ .setHeader(JmxHeaders.OPERATION_NAME, "testWithReturn")
+ .setReplyChannel(replyChannel)
+ .build();
+ }
+}
diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/TestBean.java b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/TestBean.java
index 538f84c71d..fa34a4a236 100644
--- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/TestBean.java
+++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/config/TestBean.java
@@ -25,6 +25,7 @@ import org.springframework.jmx.export.annotation.ManagedResource;
/**
* @author Mark Fisher
+ * @author Oleg Zhurakousky
* @since 2.0
*/
@ManagedResource
@@ -41,5 +42,11 @@ public class TestBean {
public void test(String text) {
this.messages.add(text);
}
+
+ @ManagedOperation
+ public List testWithReturn(String text) {
+ this.messages.add(text);
+ return messages;
+ }
}