From ce996753404936824ed65e676967143cc0f8f6fe Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Thu, 13 Nov 2008 22:14:49 +0000 Subject: [PATCH] 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. --- .../jms/HeaderMappingMessageConverter.java | 41 +++++++------ .../integration/jms/JmsInboundGateway.java | 4 +- .../integration/jms/JmsOutboundGateway.java | 60 ++++++++++++++++--- .../jms/config/JmsOutboundGatewayParser.java | 3 + .../jms/config/spring-integration-jms-1.0.xsd | 3 + 5 files changed, 82 insertions(+), 29 deletions(-) diff --git a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/HeaderMappingMessageConverter.java b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/HeaderMappingMessageConverter.java index 54ed61810e..72c8b4d5d0 100644 --- a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/HeaderMappingMessageConverter.java +++ b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/HeaderMappingMessageConverter.java @@ -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}. * - *

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 - * true. + *

If 'extractJmsMessageBody' is true (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. + * + *

If 'extractIntegrationMessagePayload' is true (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. + * + *

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

The default value is true. */ - 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 { * *

The default value is true. */ - 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(); } } diff --git a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsInboundGateway.java b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsInboundGateway.java index b36094086c..aa2bf3b399 100644 --- a/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsInboundGateway.java +++ b/org.springframework.integration.jms/src/main/java/org/springframework/integration/jms/JmsInboundGateway.java @@ -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()); 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 64768538fd..437d6a594d 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 @@ -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. + * + *

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); 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 8e8bb24244..5f446892a9 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 @@ -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"); 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 19002066bd..3f5114c8e2 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 @@ -81,6 +81,9 @@ + + +