Added the headerMapper, extractRequestPayload, and extractReplyPayload properties to JmsOutboundGateway. Also added the corresponding namespace support with 'header-mapper', 'extract-request-payload', and 'extract-reply-payload' attributes for the 'jms:outbound-gateway' element. This work is related to INT-368, INT-460, and INT-467.

This commit is contained in:
Mark Fisher
2008-11-13 22:14:49 +00:00
parent f8aff7d281
commit ce99675340
5 changed files with 82 additions and 29 deletions

View File

@@ -34,16 +34,21 @@ import org.springframework.jms.support.converter.SimpleMessageConverter;
/**
* A {@link MessageConverter} implementation that is capable of delegating to
* an existing converter instance and an existing {@link JmsHeaderMapper}. The
* default header mapper implementation is {@link DefaultJmsHeaderMapper}.
* No MessageConverter will be created by default. Unless a converter is
* provided, each inbound JMS Message will become the payload of an integration
* Message, and each outbound integration Message will become the body of a JMS
* Message.
* default MessageConverter implementation is {@link SimpleMessageConverter},
* and the default header mapper implementation is {@link DefaultJmsHeaderMapper}.
*
* <p>Even without specifying a converter, it is possible to have the
* integration Message payload Object passed instead. Simply set the
* {@link #setExtractPayload(boolean) extractPayload} property to
* <code>true</code>.
* <p>If 'extractJmsMessageBody' is <code>true</code> (the default), the body
* of each received JMS Message will become the payload of a Spring Integration
* Message. Otherwise, the JMS Message itself will be the payload of the Spring
* Integration Message.
*
* <p>If 'extractIntegrationMessagePayload' is <code>true</code> (the default),
* the payload of each outbound Spring Integration Message will be passed to
* the MessageConverter to produce the body of the JMS Message. Otherwise, the
* Spring Integration Message itself will become the body of the JMS Message.
*
* <p>The {@link JmsHeaderMapper} will be applied regardless of the values
* specified for Message extraction.
*
* @author Mark Fisher
*/
@@ -55,9 +60,9 @@ public class HeaderMappingMessageConverter implements MessageConverter {
private final JmsHeaderMapper headerMapper;
private volatile boolean extractRequestPayload = true;
private volatile boolean extractJmsMessageBody = true;
private volatile boolean extractReplyPayload = true;
private volatile boolean extractIntegrationMessagePayload = true;
/**
@@ -96,15 +101,15 @@ public class HeaderMappingMessageConverter implements MessageConverter {
}
/**
* Specify whether the inbound JMS Message's payload should be extracted
* Specify whether the inbound JMS Message's body should be extracted
* during the conversion process. Otherwise, the raw JMS Message itself
* will be the payload of the created Spring Integration Message. The
* HeaderMapper will be applied to the Message regardless of this value.
*
* <p>The default value is <code>true</code>.
*/
public void setExtractRequestPayload(boolean extractRequestPayload) {
this.extractRequestPayload = extractRequestPayload;
public void setExtractJmsMessageBody(boolean extractJmsMessageBody) {
this.extractJmsMessageBody = extractJmsMessageBody;
}
/**
@@ -123,8 +128,8 @@ public class HeaderMappingMessageConverter implements MessageConverter {
*
* <p>The default value is <code>true</code>.
*/
public void setExtractReplyPayload(boolean extractReplyPayload) {
this.extractReplyPayload = extractReplyPayload;
public void setExtractIntegrationMessagePayload(boolean extractIntegrationMessagePayload) {
this.extractIntegrationMessagePayload = extractIntegrationMessagePayload;
}
/**
@@ -132,7 +137,7 @@ public class HeaderMappingMessageConverter implements MessageConverter {
*/
public Object fromMessage(javax.jms.Message jmsMessage) throws JMSException, MessageConversionException {
MessageBuilder<?> builder = null;
if (this.extractRequestPayload) {
if (this.extractJmsMessageBody) {
Object conversionResult = this.converter.fromMessage(jmsMessage);
if (conversionResult == null) {
return null;
@@ -163,7 +168,7 @@ public class HeaderMappingMessageConverter implements MessageConverter {
javax.jms.Message jmsMessage = null;
if (object instanceof Message) {
headers = ((Message<?>) object).getHeaders();
if (this.extractReplyPayload) {
if (this.extractIntegrationMessagePayload) {
object = ((Message<?>) object).getPayload();
}
}

View File

@@ -162,8 +162,8 @@ public class JmsInboundGateway extends SimpleMessagingGateway implements Disposa
}
if (this.messageConverter == null) {
HeaderMappingMessageConverter hmmc = new HeaderMappingMessageConverter(null, this.headerMapper);
hmmc.setExtractRequestPayload(this.extractRequestPayload);
hmmc.setExtractReplyPayload(this.extractReplyPayload);
hmmc.setExtractJmsMessageBody(this.extractRequestPayload);
hmmc.setExtractIntegrationMessagePayload(this.extractReplyPayload);
this.messageConverter = hmmc;
}
this.container.setMessageListener(new GatewayInvokingMessageListener());

View File

@@ -16,8 +16,6 @@
package org.springframework.integration.jms;
import java.io.Serializable;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
@@ -66,7 +64,17 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp
private ConnectionFactory connectionFactory;
private volatile MessageConverter messageConverter = new HeaderMappingMessageConverter(new SimpleMessageConverter());
private volatile MessageConverter messageConverter;
private volatile JmsHeaderMapper headerMapper;
private volatile boolean extractRequestPayload = true;
private volatile boolean extractReplyPayload = true;
private volatile boolean initialized;
private final Object initializationMonitor = new Object();
/**
@@ -137,6 +145,27 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp
this.messageConverter = messageConverter;
}
/**
* Provide a {@link JmsHeaderMapper} implementation for mapping the
* Spring Integration Message Headers to/from JMS Message properties.
*
* <p>This property will be ignored if a {@link MessageConverter} is
* provided to the {@link #setMessageConverter(MessageConverter)} method.
* However, you may provide your own implementation of the delegating
* {@link HeaderMappingMessageConverter} implementation.
*/
public void setHeaderMapper(JmsHeaderMapper headerMapper) {
this.headerMapper = headerMapper;
}
public void setExtractRequestPayload(boolean extractRequestPayload) {
this.extractRequestPayload = extractRequestPayload;
}
public void setExtractReplyPayload(boolean extractReplyPayload) {
this.extractReplyPayload = extractReplyPayload;
}
/**
* Specify the Spring Integration reply channel. If this property is not
* set the gateway will check for a 'replyChannel' header on the request.
@@ -146,16 +175,31 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp
}
public void afterPropertiesSet() {
Assert.notNull(this.connectionFactory, "connectionFactory must not be null");
Assert.notNull(this.requestDestination, "requestDestination must not be null");
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");
if (this.messageConverter == null) {
HeaderMappingMessageConverter hmmc = new HeaderMappingMessageConverter(null, this.headerMapper);
hmmc.setExtractIntegrationMessagePayload(this.extractRequestPayload);
hmmc.setExtractJmsMessageBody(this.extractReplyPayload);
this.messageConverter = hmmc;
}
this.initialized = true;
}
}
@Override
protected void handleRequestMessage(final Message<?> message, final ReplyMessageHolder replyMessageHolder) {
if (!this.initialized) {
this.afterPropertiesSet();
}
final Message<?> requestMessage = MessageBuilder.fromMessage(message).build();
try {
javax.jms.Message jmsReply = JmsOutboundGateway.this.sendAndReceive(requestMessage);
Object result = (messageConverter != null) ? messageConverter.fromMessage(jmsReply) : jmsReply;
Object result = this.messageConverter.fromMessage(jmsReply);
replyMessageHolder.set(result);
}
catch (JMSException e) {
@@ -171,9 +215,7 @@ public class JmsOutboundGateway extends AbstractReplyProducingMessageHandler imp
Destination replyTo = null;
try {
session = createSession(connection);
javax.jms.Message jmsRequest = (messageConverter != null)
? messageConverter.toMessage(requestMessage, session)
: session.createObjectMessage((Serializable) requestMessage);
javax.jms.Message jmsRequest = this.messageConverter.toMessage(requestMessage, session);
messageProducer = session.createProducer(this.requestDestination);
messageProducer.setDeliveryMode(this.deliveryMode);
messageProducer.setPriority(this.priority);

View File

@@ -44,6 +44,9 @@ public class JmsOutboundGatewayParser extends AbstractConsumerEndpointParser {
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-destination");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-converter");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "header-mapper");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-request-payload");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-reply-payload");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "receive-timeout");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "delivery-mode");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "time-to-live");

View File

@@ -81,6 +81,9 @@
<xsd:attribute name="reply-destination" type="xsd:string"/>
<xsd:attribute name="connection-factory" type="xsd:string" default="connectionFactory"/>
<xsd:attribute name="message-converter" type="xsd:string"/>
<xsd:attribute name="header-mapper" type="xsd:string"/>
<xsd:attribute name="extract-request-payload" type="xsd:string" default="true"/>
<xsd:attribute name="extract-reply-payload" type="xsd:string" default="true"/>
<xsd:attribute name="receive-timeout" type="xsd:string"/>
<xsd:attribute name="delivery-mode" type="xsd:string"/>
<xsd:attribute name="time-to-live" type="xsd:string"/>