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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
Reference in New Issue
Block a user