From 8772fd81699ad2415ca402ae7e728edb8ad0bdc6 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Sat, 22 Nov 2008 17:52:38 +0000 Subject: [PATCH] Added support for request and reply Destination names for the JmsOutboundGateway. The 'destinationResolver' property reference may also be provided including namespace support with the 'destination-resolver' attribute. This also applies to the 'inbound-gateway' and 'message-driven-channel-adapter' elements (INT-488). --- .../integration/jms/JmsOutboundGateway.java | 66 +++++++++++++++++-- .../JmsMessageDrivenEndpointParser.java | 3 +- .../jms/config/JmsOutboundGatewayParser.java | 14 +++- .../jms/config/spring-integration-jms-1.0.xsd | 6 +- 4 files changed, 81 insertions(+), 8 deletions(-) diff --git a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java index 4c9819f29f..e658cc9ba6 100644 --- a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java +++ b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsOutboundGateway.java @@ -41,6 +41,8 @@ import org.springframework.jms.connection.ConnectionFactoryUtils; import org.springframework.jms.support.JmsUtils; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.jms.support.converter.SimpleMessageConverter; +import org.springframework.jms.support.destination.DestinationResolver; +import org.springframework.jms.support.destination.DynamicDestinationResolver; import org.springframework.util.Assert; /** @@ -54,8 +56,14 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp private volatile Destination requestDestination; + private volatile String requestDestinationName; + private volatile Destination replyDestination; + private volatile String replyDestinationName; + + private volatile DestinationResolver destinationResolver = new DynamicDestinationResolver(); + private volatile boolean pubSubDomain; private volatile long receiveTimeout = 5000; @@ -91,7 +99,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp /** * Set the JMS Destination to which request Messages should be sent. - * This is a required property. + * Either this or the 'requestDestinationName' property is required. */ public void setRequestDestination(Destination requestDestination) { if (requestDestination instanceof Topic) { @@ -100,6 +108,14 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp this.requestDestination = requestDestination; } + /** + * Set the name of the JMS Destination to which request Messages should be + * sent. Either this or the 'requestDestination' property is required. + */ + public void setRequestDestinationName(String requestDestinationName) { + this.requestDestinationName = requestDestinationName; + } + /** * Set the JMS Destination from which reply Messages should be received. * If none is provided, this gateway will create a {@link TemporaryQueue} per invocation. @@ -108,6 +124,23 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp this.replyDestination = replyDestination; } + /** + * Set the name of the JMS Destination from which reply Messages should be received. + * If none is provided, this gateway will create a {@link TemporaryQueue} per invocation. + */ + public void setReplyDestinationName(String replyDestinationName) { + this.replyDestinationName = replyDestinationName; + } + + /** + * Provide the {@link DestinationResolver} to use when resolving either a + * 'requestDestinationName' or 'replyDestinationName' value. The default + * is an instance of {@link DynamicDestinationResolver}. + */ + public void setDestinationResolver(DestinationResolver destinationResolver) { + this.destinationResolver = destinationResolver; + } + /** * Specify whether the request destination is a Topic. This value is * necessary when providing a destination name for a Topic rather than @@ -192,13 +225,37 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp this.setOutputChannel(replyChannel); } + private Destination getRequestDestination(Session session) throws JMSException { + if (this.requestDestination != null) { + return this.requestDestination; + } + Assert.notNull(this.destinationResolver, + "DestinationResolver is required when relying upon the 'requestDestinationName' property."); + return this.destinationResolver.resolveDestinationName( + session, this.requestDestinationName, this.pubSubDomain); + } + + private Destination getReplyDestination(Session session) throws JMSException { + if (this.replyDestination != null) { + return this.replyDestination; + } + if (this.replyDestinationName != null) { + Assert.notNull(this.destinationResolver, + "DestinationResolver is required when relying upon the 'replyDestinationName' property."); + return this.destinationResolver.resolveDestinationName( + session, this.replyDestinationName, this.pubSubDomain); + } + return session.createTemporaryQueue(); + } + public void afterPropertiesSet() { synchronized (this.initializationMonitor) { if (this.initialized) { return; } Assert.notNull(this.connectionFactory, "connectionFactory must not be null"); - Assert.notNull(this.requestDestination, "requestDestination must not be null"); + Assert.isTrue(this.requestDestination != null || this.requestDestinationName != null, + "Either a 'requestDestination' or 'requestDestinationName' is required."); if (this.messageConverter == null) { HeaderMappingMessageConverter hmmc = new HeaderMappingMessageConverter(null, this.headerMapper); hmmc.setExtractIntegrationMessagePayload(this.extractRequestPayload); @@ -237,12 +294,11 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp try { session = createSession(connection); javax.jms.Message jmsRequest = this.messageConverter.toMessage(requestMessage, session); - messageProducer = session.createProducer(this.requestDestination); + messageProducer = session.createProducer(this.getRequestDestination(session)); messageProducer.setDeliveryMode(this.deliveryMode); messageProducer.setPriority(this.priority); messageProducer.setTimeToLive(this.timeToLive); - replyTo = (this.replyDestination != null) - ? this.replyDestination : session.createTemporaryQueue(); + replyTo = this.getReplyDestination(session); jmsRequest.setJMSReplyTo(replyTo); connection.start(); messageProducer.send(jmsRequest); diff --git a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java index 67a902e4d3..32634faa41 100644 --- a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java +++ b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsMessageDrivenEndpointParser.java @@ -43,7 +43,7 @@ public class JmsMessageDrivenEndpointParser extends AbstractSingleBeanDefinition JmsAdapterParserUtils.CONNECTION_FACTORY_PROPERTY, JmsAdapterParserUtils.DESTINATION_ATTRIBUTE, JmsAdapterParserUtils.DESTINATION_NAME_ATTRIBUTE, - "transaction-manager", "pub-sub-domain", + "destination-resolver", "transaction-manager", "pub-sub-domain", "concurrent-consumers", "max-concurrent-consumers", "max-messages-per-task", "idle-task-execution-limit" }; @@ -113,6 +113,7 @@ public class JmsMessageDrivenEndpointParser extends AbstractSingleBeanDefinition builder.addPropertyValue("sessionAcknowledgeMode", acknowledgeMode); } } + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "destination-resolver"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "transaction-manager"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "pub-sub-domain"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "concurrent-consumers"); diff --git a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java index d53767384e..ea1b50e833 100644 --- a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java +++ b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/JmsOutboundGatewayParser.java @@ -23,6 +23,8 @@ import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractConsumerEndpointParser; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.integration.jms.JmsOutboundGateway; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Parser for the <outbound-gateway> element of the integration 'jms' namespace. @@ -40,8 +42,18 @@ public class JmsOutboundGatewayParser extends AbstractConsumerEndpointParser { protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(JmsOutboundGateway.class); builder.addPropertyReference("connectionFactory", element.getAttribute("connection-factory")); - builder.addPropertyReference("requestDestination", element.getAttribute("request-destination")); + String requestDestination = element.getAttribute("request-destination"); + String requestDestinationName = element.getAttribute("request-destination-name"); + Assert.isTrue(StringUtils.hasText(requestDestination) ^ StringUtils.hasText(requestDestinationName), + "Exactly one of the 'request-destination' or 'request-destination-name' attributes is required."); + if (StringUtils.hasText(requestDestination)) { + builder.addPropertyReference("requestDestination", requestDestination); + } + else if (StringUtils.hasText(requestDestinationName)) { + builder.addPropertyValue("requestDestinationName", requestDestinationName); + } IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-destination"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-destination-name"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-converter"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "header-mapper"); diff --git a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/spring-integration-jms-1.0.xsd b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/spring-integration-jms-1.0.xsd index 66f7c49876..bd8bfc5694 100644 --- a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/spring-integration-jms-1.0.xsd +++ b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/config/spring-integration-jms-1.0.xsd @@ -103,8 +103,11 @@ - + + + + @@ -195,6 +198,7 @@ +