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).

This commit is contained in:
Mark Fisher
2008-11-22 17:52:38 +00:00
parent a71127fb4d
commit 8772fd8169
4 changed files with 81 additions and 8 deletions

View File

@@ -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 <em>required</em> 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);

View File

@@ -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");

View File

@@ -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 &lt;outbound-gateway&gt; 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");

View File

@@ -103,8 +103,11 @@
<xsd:attribute name="reply-channel" type="xsd:string"/>
<xsd:attribute name="request-timeout" type="xsd:string"/>
<xsd:attribute name="reply-timeout" type="xsd:string"/>
<xsd:attribute name="request-destination" type="xsd:string" use="required"/>
<xsd:attribute name="request-destination" type="xsd:string"/>
<xsd:attribute name="request-destination-name" type="xsd:string"/>
<xsd:attribute name="reply-destination" type="xsd:string"/>
<xsd:attribute name="reply-destination-name" type="xsd:string"/>
<xsd:attribute name="destination-resolver" type="xsd:string"/>
<xsd:attribute name="pub-sub-domain" type="xsd:string"/>
<xsd:attribute name="connection-factory" type="xsd:string" default="connectionFactory"/>
<xsd:attribute name="message-converter" type="xsd:string"/>
@@ -195,6 +198,7 @@
<xsd:attribute name="connection-factory" type="xsd:string"/>
<xsd:attribute name="destination" type="xsd:string"/>
<xsd:attribute name="destination-name" type="xsd:string"/>
<xsd:attribute name="destination-resolver" type="xsd:string"/>
<xsd:attribute name="pub-sub-domain" type="xsd:string"/>
</xsd:complexType>