Mapping JMS attributes to MessageHeader in source adapters (INT-150). Also provided new strategy interface (MessageHeaderMapper) and a HeaderMappingMessageConverter that wraps an existing MessageConverter implementation. Factored out common configuration code from JmsPollingSourceAdapter and JmsTargetAdapter into AbstractJmsTemplateBasedAdapter. The JMS attribute keys are now defined in JmsAttributeKeys, and a similar class (MailAttributeKeys) is used for MailMessages.

This commit is contained in:
Mark Fisher
2008-03-19 23:53:49 +00:00
parent 183159139b
commit 5e7141959d
21 changed files with 683 additions and 384 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,21 +14,20 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import javax.jms.JMSException;
import javax.jms.Message;
package org.springframework.integration.adapter;
import org.springframework.integration.message.MessageHeader;
/**
* Strategy interface for post-processing a JMS Message before it is sent to its
* destination.
* Strategy interface for mapping between a source or target object and an
* integration {@link MessageHeader}.
*
* @author Mark Fisher
*/
public interface JmsMessagePostProcessor {
public interface MessageHeaderMapper<T> {
void postProcessJmsMessage(Message jmsMessage, MessageHeader header) throws JMSException;
void mapFromMessageHeader(MessageHeader header, T target);
void mapToMessageHeader(T source, MessageHeader header);
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageHandlingException;
/**
* Exception that indicates an error during message mapping.
*
* @author Mark Fisher
*/
@SuppressWarnings("serial")
public class MessageMappingException extends MessageHandlingException {
public MessageMappingException(Message<?> failedMessage, String description) {
super(failedMessage, description);
}
public MessageMappingException(String description, Throwable cause) {
super(description, cause);
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.MessagingConfigurationException;
import org.springframework.integration.adapter.MessageHeaderMapper;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MessageConverter;
/**
* Base class for adapters that delegate to a {@link JmsTemplate}.
*
* @author Mark Fisher
*/
public abstract class AbstractJmsTemplateBasedAdapter implements InitializingBean {
private volatile ConnectionFactory connectionFactory;
private volatile Destination destination;
private volatile String destinationName;
private volatile JmsTemplate jmsTemplate;
private volatile MessageHeaderMapper<javax.jms.Message> headerMapper;
private volatile boolean initialized;
private final Object initializationMonitor = new Object();
public AbstractJmsTemplateBasedAdapter(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public AbstractJmsTemplateBasedAdapter(ConnectionFactory connectionFactory, Destination destination) {
this.connectionFactory = connectionFactory;
this.destination = destination;
this.jmsTemplate = createDefaultJmsTemplate();
}
public AbstractJmsTemplateBasedAdapter(ConnectionFactory connectionFactory, String destinationName) {
this.connectionFactory = connectionFactory;
this.destinationName = destinationName;
this.jmsTemplate = createDefaultJmsTemplate();
}
/**
* No-arg constructor provided for convenience when configuring with
* setters. Note that the initialization callback will validate.
*/
public AbstractJmsTemplateBasedAdapter() {
}
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public void setDestination(Destination destination) {
this.destination = destination;
}
public void setDestinationName(String destinationName) {
this.destinationName = destinationName;
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void setHeaderMapper(MessageHeaderMapper<javax.jms.Message> headerMapper) {
this.headerMapper = headerMapper;
}
protected JmsTemplate getJmsTemplate() {
if (this.jmsTemplate == null) {
this.afterPropertiesSet();
}
return this.jmsTemplate;
}
public void afterPropertiesSet() {
synchronized (this.initializationMonitor) {
if (this.initialized) {
return;
}
if (this.jmsTemplate == null) {
if (this.connectionFactory == null || (this.destination == null && this.destinationName == null)) {
throw new MessagingConfigurationException("Either a 'jmsTemplate' or " +
"*both* 'connectionFactory' and 'destination' (or 'destination-name') are required.");
}
this.jmsTemplate = this.createDefaultJmsTemplate();
}
MessageConverter converter = this.jmsTemplate.getMessageConverter();
this.jmsTemplate.setMessageConverter(new HeaderMappingMessageConverter(converter, this.headerMapper));
this.initialized = true;
}
}
private JmsTemplate createDefaultJmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(this.connectionFactory);
if (this.destination != null) {
jmsTemplate.setDefaultDestination(this.destination);
}
else {
jmsTemplate.setDefaultDestinationName(this.destinationName);
}
return jmsTemplate;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,17 +16,13 @@
package org.springframework.integration.adapter.jms;
import javax.jms.JMSException;
import javax.jms.MessageListener;
import org.springframework.integration.MessagingConfigurationException;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageDeliveryException;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.SimplePayloadMessageMapper;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.SimpleMessageConverter;
import org.springframework.util.Assert;
/**
@@ -37,50 +33,31 @@ import org.springframework.util.Assert;
*/
public class ChannelPublishingJmsListener implements MessageListener {
private MessageChannel channel;
private final MessageChannel channel;
private long timeout = -1;
private final MessageConverter converter;
private MessageConverter converter = new SimpleMessageConverter();
private MessageMapper mapper = new SimplePayloadMessageMapper();
private volatile long timeout = -1;
public ChannelPublishingJmsListener() {
}
public ChannelPublishingJmsListener(MessageChannel channel) {
public ChannelPublishingJmsListener(MessageChannel channel, MessageConverter converter) {
Assert.notNull(channel, "'channel' must not be null");
this.channel = channel;
this.converter = (converter != null && converter instanceof HeaderMappingMessageConverter) ?
converter : new HeaderMappingMessageConverter(converter);
}
public void setChannel(MessageChannel channel) {
Assert.notNull(channel, "'channel' must not be null");
this.channel = channel;
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public void setMessageConverter(MessageConverter messageConverter) {
Assert.notNull(messageConverter, "'messageConverter' must not be null");
this.converter = messageConverter;
}
public void setMessageMapper(MessageMapper messageMapper) {
Assert.notNull(messageMapper, "'messageMapper' must not be null");
this.mapper = messageMapper;
}
public void onMessage(javax.jms.Message jmsMessage) {
if (this.channel == null) {
throw new MessagingConfigurationException("'channel' must not be null");
}
try {
Object payload = converter.fromMessage(jmsMessage);
Message messageToSend = mapper.toMessage(payload);
Message<?> messageToSend = (Message<?>) this.converter.fromMessage(jmsMessage);
if (this.timeout < 0) {
this.channel.send(messageToSend);
}
@@ -88,7 +65,7 @@ public class ChannelPublishingJmsListener implements MessageListener {
this.channel.send(messageToSend, timeout);
}
}
catch (JMSException e) {
catch (Exception e) {
throw new MessageDeliveryException("failed to convert JMS Message", e);
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import javax.jms.Destination;
import javax.jms.JMSException;
import org.springframework.integration.adapter.MessageHeaderMapper;
import org.springframework.integration.adapter.MessageMappingException;
import org.springframework.integration.message.MessageHeader;
import org.springframework.util.StringUtils;
/**
* A {@link HeaderMapper} implementation for JMS {@link javax.jms.Message Messages}.
*
* @author Mark Fisher
*/
public class DefaultJmsHeaderMapper implements MessageHeaderMapper<javax.jms.Message> {
private static List<Class<?>> SUPPORTED_PROPERTY_TYPES = Arrays.asList(new Class<?>[] {
Boolean.class, Byte.class, Double.class, Float.class, Integer.class, Long.class, Short.class, String.class });
public void mapFromMessageHeader(MessageHeader header, javax.jms.Message jmsMessage) {
try {
Object jmsCorrelationId = header.getAttribute(JmsAttributeKeys.CORRELATION_ID);
if (jmsCorrelationId != null && (jmsCorrelationId instanceof String)) {
jmsMessage.setJMSCorrelationID((String) jmsCorrelationId);
}
Object jmsReplyTo = header.getAttribute(JmsAttributeKeys.REPLY_TO);
if (jmsReplyTo != null && (jmsReplyTo instanceof Destination)) {
jmsMessage.setJMSReplyTo((Destination) jmsReplyTo);
}
Object jmsType = header.getAttribute(JmsAttributeKeys.TYPE);
if (jmsType != null && (jmsType instanceof String)) {
jmsMessage.setJMSType((String) jmsType);
}
String prefix = JmsAttributeKeys.USER_DEFINED_ATTRIBUTE_PREFIX;
Set<String> attributeNames = header.getAttributeNames();
for (String attributeName : attributeNames) {
if (attributeName.startsWith(prefix)) {
String jmsAttributeName = attributeName.substring(prefix.length());
if (StringUtils.hasText(attributeName)) {
Object value = header.getAttribute(attributeName);
if (value != null && SUPPORTED_PROPERTY_TYPES.contains(value.getClass())) {
jmsMessage.setObjectProperty(jmsAttributeName, value);
}
}
}
}
}
catch (JMSException e) {
throw new MessageMappingException("failed to map from MessageHeader", e);
}
}
public void mapToMessageHeader(javax.jms.Message jmsMessage, MessageHeader header) {
try {
String correlationId = jmsMessage.getJMSCorrelationID();
if (correlationId != null) {
header.setAttribute(JmsAttributeKeys.CORRELATION_ID, correlationId);
}
Destination replyTo = jmsMessage.getJMSReplyTo();
if (replyTo != null) {
header.setAttribute(JmsAttributeKeys.REPLY_TO, replyTo);
}
String type = jmsMessage.getJMSType();
if (type != null) {
header.setAttribute(JmsAttributeKeys.TYPE, type);
}
Enumeration<?> jmsPropertyNames = jmsMessage.getPropertyNames();
if (jmsPropertyNames != null) {
while (jmsPropertyNames.hasMoreElements()) {
String propertyName = jmsPropertyNames.nextElement().toString();
header.setAttribute(JmsAttributeKeys.USER_DEFINED_ATTRIBUTE_PREFIX + propertyName,
jmsMessage.getObjectProperty(propertyName));
}
}
}
catch (JMSException e) {
throw new MessageMappingException("failed to map to MessageHeader", e);
}
}
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import org.springframework.integration.message.MessageHeader;
/**
* A {@link JmsMessagePostProcessor} that passes attributes from a
* {@link MessageHeader} to a JMS message before it is sent to its destination.
*
* @author Mark Fisher
*/
public class DefaultJmsMessagePostProcessor implements JmsMessagePostProcessor {
public void postProcessJmsMessage(Message jmsMessage, MessageHeader header) throws JMSException {
Object jmsCorrelationId = header.getAttribute(JmsTargetAdapter.JMS_CORRELATION_ID);
if (jmsCorrelationId != null && (jmsCorrelationId instanceof String)) {
jmsMessage.setJMSCorrelationID((String) jmsCorrelationId);
}
Object jmsReplyTo = header.getAttribute(JmsTargetAdapter.JMS_REPLY_TO);
if (jmsReplyTo != null && (jmsReplyTo instanceof Destination)) {
jmsMessage.setJMSReplyTo((Destination) jmsReplyTo);
}
Object jmsType = header.getAttribute(JmsTargetAdapter.JMS_TYPE);
if (jmsType != null && (jmsType instanceof String)) {
jmsMessage.setJMSType((String) jmsType);
}
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import javax.jms.JMSException;
import javax.jms.Session;
import org.springframework.integration.adapter.MessageHeaderMapper;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageHandlingException;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.SimpleMessageConverter;
/**
* A {@link MessageConverter} implementation that delegates to an existing
* converter as well as an implementation of {@link MessageHeaderMapper}.
*
* @author Mark Fisher
*/
public class HeaderMappingMessageConverter implements MessageConverter {
private final MessageConverter converter;
private final MessageHeaderMapper<javax.jms.Message> headerMapper;
public HeaderMappingMessageConverter(MessageConverter converter) {
this(converter, null);
}
public HeaderMappingMessageConverter(MessageConverter converter, MessageHeaderMapper<javax.jms.Message> headerMapper) {
this.converter = (converter != null ? converter : new SimpleMessageConverter());
this.headerMapper = (headerMapper != null ? headerMapper : new DefaultJmsHeaderMapper());
}
public Object fromMessage(javax.jms.Message jmsMessage) throws JMSException, MessageConversionException {
Object payload = this.converter.fromMessage(jmsMessage);
Message<?> message = new GenericMessage<Object>(payload);
this.headerMapper.mapToMessageHeader(jmsMessage, message.getHeader());
return message;
}
public javax.jms.Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
if (!(object instanceof Message<?>)) {
throw new MessageHandlingException("expected a '" + Message.class.getName() +
"', but received '" + object.getClass() + "'");
}
Message<?> message = (Message<?>) object;
javax.jms.Message jmsMessage = this.converter.toMessage(message.getPayload(), session);
this.headerMapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
return jmsMessage;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
/**
* Keys to be used for setting and/or retrieving JMS attributes stored in the
* integration message header.
*
* @author Mark Fisher
*/
public abstract class JmsAttributeKeys {
public static final String USER_DEFINED_ATTRIBUTE_PREFIX = "jms.";
public static final String CORRELATION_ID = "_jms.JMSCorrelationID";
public static final String REPLY_TO = "_jms.JMSReplyTo";
public static final String TYPE = "_jms.JMSType";
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -132,9 +132,8 @@ public class JmsMessageDrivenSourceAdapter extends AbstractSourceAdapter<Object>
dmlc.setSessionTransacted(this.sessionTransacted);
dmlc.setSessionAcknowledgeMode(this.sessionAcknowledgeMode);
dmlc.setAutoStartup(false);
ChannelPublishingJmsListener listener = new ChannelPublishingJmsListener(this.getChannel());
listener.setMessageConverter(this.messageConverter);
listener.setMessageMapper(this.getMessageMapper());
ChannelPublishingJmsListener listener = new ChannelPublishingJmsListener(
this.getChannel(), this.messageConverter);
listener.setTimeout(this.sendTimeout);
dmlc.setMessageListener(listener);
if (this.taskExecutor != null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,8 +22,6 @@ import java.util.Collection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.MessagingConfigurationException;
import org.springframework.integration.adapter.PollableSource;
import org.springframework.jms.core.JmsTemplate;
@@ -35,82 +33,27 @@ import org.springframework.jms.core.JmsTemplate;
*
* @author Mark Fisher
*/
public class JmsPollableSource implements PollableSource<Object>, InitializingBean {
private ConnectionFactory connectionFactory;
private Destination destination;
private String destinationName;
private JmsTemplate jmsTemplate;
public class JmsPollableSource extends AbstractJmsTemplateBasedAdapter implements PollableSource<Object> {
public JmsPollableSource(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
super(jmsTemplate);
}
public JmsPollableSource(ConnectionFactory connectionFactory, Destination destination) {
this.connectionFactory = connectionFactory;
this.destination = destination;
this.initJmsTemplate();
super(connectionFactory, destination);
}
public JmsPollableSource(ConnectionFactory connectionFactory, String destinationName) {
this.connectionFactory = connectionFactory;
this.destinationName = destinationName;
this.initJmsTemplate();
super(connectionFactory, destinationName);
}
/**
* No-arg constructor provided for convenience when configuring with
* setters. Note that the initialization callback will validate.
*/
public JmsPollableSource() {
super();
}
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public void setDestination(Destination destination) {
this.destination = destination;
}
public void setDestinationName(String destinationName) {
this.destinationName = destinationName;
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void afterPropertiesSet() {
if (this.jmsTemplate == null) {
if (this.connectionFactory == null || (this.destination == null && this.destinationName == null)) {
throw new MessagingConfigurationException("Either a 'jmsTemplate' or "
+ "both 'connectionFactory' and 'destination' (or 'destinationName') are required.");
}
this.initJmsTemplate();
}
}
private void initJmsTemplate() {
this.jmsTemplate = new JmsTemplate();
this.jmsTemplate.setConnectionFactory(this.connectionFactory);
if (this.destination != null) {
this.jmsTemplate.setDefaultDestination(this.destination);
}
else if (this.destinationName != null) {
this.jmsTemplate.setDefaultDestinationName(this.destinationName);
}
else {
throw new MessagingConfigurationException("either 'destination' or 'destinationName' is required");
}
}
public Collection<Object> poll(int limit) {
return Arrays.asList(this.jmsTemplate.receiveAndConvert());
return Arrays.asList(this.getJmsTemplate().receiveAndConvert());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,121 +18,39 @@ package org.springframework.integration.adapter.jms;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.MessagingConfigurationException;
import org.springframework.integration.handler.MessageHandler;
import org.springframework.integration.message.Message;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessagePostProcessor;
import org.springframework.jms.support.converter.SimpleMessageConverter;
/**
* A target adapter for sending JMS Messages.
*
* @author Mark Fisher
*/
public class JmsTargetAdapter implements MessageHandler, InitializingBean {
public static final String JMS_CORRELATION_ID = "JMSCorrelationID";
public static final String JMS_REPLY_TO = "JMSReplyTo";
public static final String JMS_TYPE = "JMSType";
private ConnectionFactory connectionFactory;
private Destination destination;
private String destinationName;
private JmsTemplate jmsTemplate;
private JmsMessagePostProcessor jmsMessagePostProcessor = new DefaultJmsMessagePostProcessor();
public class JmsTargetAdapter extends AbstractJmsTemplateBasedAdapter implements MessageHandler {
public JmsTargetAdapter(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
super(jmsTemplate);
}
public JmsTargetAdapter(ConnectionFactory connectionFactory, Destination destination) {
this.connectionFactory = connectionFactory;
this.destination = destination;
this.initJmsTemplate();
super(connectionFactory, destination);
}
public JmsTargetAdapter(ConnectionFactory connectionFactory, String destinationName) {
this.connectionFactory = connectionFactory;
this.destinationName = destinationName;
this.initJmsTemplate();
super(connectionFactory, destinationName);
}
/**
* No-arg constructor provided for convenience when configuring with
* setters. Note that the initialization callback will validate.
*/
public JmsTargetAdapter() {
super();
}
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public void setDestination(Destination destination) {
this.destination = destination;
}
public void setDestinationName(String destinationName) {
this.destinationName = destinationName;
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void setJmsMessagePostProcessor(JmsMessagePostProcessor jmsMessagePostProcessor) {
this.jmsMessagePostProcessor = jmsMessagePostProcessor;
}
public void afterPropertiesSet() {
if (this.jmsTemplate == null) {
if (this.connectionFactory == null || (this.destination == null && this.destinationName == null)) {
throw new MessagingConfigurationException("Either a 'jmsTemplate' or " +
"*both* 'connectionFactory' and 'destination' (or 'destination-name') are required.");
}
this.initJmsTemplate();
}
if (this.jmsTemplate.getMessageConverter() == null) {
this.jmsTemplate.setMessageConverter(new SimpleMessageConverter());
}
}
private void initJmsTemplate() {
this.jmsTemplate = new JmsTemplate();
this.jmsTemplate.setConnectionFactory(this.connectionFactory);
if (this.destination != null) {
this.jmsTemplate.setDefaultDestination(this.destination);
}
else {
this.jmsTemplate.setDefaultDestinationName(this.destinationName);
}
}
public final Message<?> handle(final Message<?> message) {
if (message == null) {
return null;
if (message != null) {
this.getJmsTemplate().convertAndSend(message);
}
this.jmsTemplate.convertAndSend(message.getPayload(), new MessagePostProcessor() {
public javax.jms.Message postProcessMessage(javax.jms.Message jmsMessage) throws JMSException {
if (jmsMessagePostProcessor != null) {
jmsMessagePostProcessor.postProcessJmsMessage(jmsMessage, message.getHeader());
}
return jmsMessage;
}
});
return null;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,32 +29,32 @@ public class DefaultMailHeaderGenerator extends AbstractMailHeaderGenerator {
@Override
protected String getSubject(Message<?> message) {
return this.retrieveAsString(message, MailTargetAdapter.SUBJECT);
return this.retrieveAsString(message, MailAttributeKeys.SUBJECT);
}
@Override
protected String[] getTo(Message<?> message) {
return this.retrieveAsStringArray(message, MailTargetAdapter.TO);
return this.retrieveAsStringArray(message, MailAttributeKeys.TO);
}
@Override
protected String[] getCc(Message<?> message) {
return this.retrieveAsStringArray(message, MailTargetAdapter.CC);
return this.retrieveAsStringArray(message, MailAttributeKeys.CC);
}
@Override
protected String[] getBcc(Message<?> message) {
return this.retrieveAsStringArray(message, MailTargetAdapter.BCC);
return this.retrieveAsStringArray(message, MailAttributeKeys.BCC);
}
@Override
protected String getFrom(Message<?> message) {
return this.retrieveAsString(message, MailTargetAdapter.FROM);
return this.retrieveAsString(message, MailAttributeKeys.FROM);
}
@Override
protected String getReplyTo(Message<?> message) {
return this.retrieveAsString(message, MailTargetAdapter.REPLY_TO);
return this.retrieveAsString(message, MailAttributeKeys.REPLY_TO);
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.mail;
/**
* Keys to be used for setting and/or retrieving mail attributes stored in the
* integration message header.
*
* @author Mark Fisher
*/
public class MailAttributeKeys {
public static final String SUBJECT = "_mail.SUBJECT";
public static final String TO = "_mail.TO";
public static final String CC = "_mail.CC";
public static final String BCC = "_mail.BCC";
public static final String FROM = "_mail.FROM";
public static final String REPLY_TO = "_mail.REPLY_TO";
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,19 +35,6 @@ import org.springframework.util.Assert;
*/
public class MailTargetAdapter implements MessageHandler, InitializingBean {
public static final String SUBJECT = "_mail.SUBJECT";
public static final String TO = "_mail.TO";
public static final String CC = "_mail.CC";
public static final String BCC = "_mail.BCC";
public static final String FROM = "_mail.FROM";
public static final String REPLY_TO = "_mail.REPLY_TO";
private final JavaMailSender mailSender;
private volatile MailHeaderGenerator mailHeaderGenerator = new DefaultMailHeaderGenerator();
@@ -104,7 +91,8 @@ public class MailTargetAdapter implements MessageHandler, InitializingBean {
return null;
}
public MailMessage convertMessageToMailMessage(Message<?> message) {
@SuppressWarnings("unchecked")
private MailMessage convertMessageToMailMessage(Message<?> message) {
if (message.getPayload() instanceof String) {
return this.textMessageMapper.fromMessage((Message<String>) message);
}

View File

@@ -0,0 +1,179 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import javax.jms.Destination;
import javax.jms.JMSException;
import org.junit.Test;
import org.springframework.integration.message.StringMessage;
/**
* @author Mark Fisher
*/
public class DefaultJmsHeaderMapperTests {
@Test
public void testJmsReplyToMappedFromHeader() throws JMSException {
StringMessage message = new StringMessage("test");
Destination replyTo = new Destination() {};
message.getHeader().setAttribute(JmsAttributeKeys.REPLY_TO, replyTo);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
assertNotNull(jmsMessage.getJMSReplyTo());
assertSame(replyTo, jmsMessage.getJMSReplyTo());
}
@Test
public void testJmsReplyToIgnoredIfIncorrectType() throws JMSException {
StringMessage message = new StringMessage("test");
message.getHeader().setAttribute(JmsAttributeKeys.REPLY_TO, "not-a-destination");
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
assertNull(jmsMessage.getJMSReplyTo());
}
@Test
public void testJmsCorrelationIdMappedFromHeader() throws JMSException {
StringMessage message = new StringMessage("test");
String jmsCorrelationId = "ABC-123";
message.getHeader().setAttribute(JmsAttributeKeys.CORRELATION_ID, jmsCorrelationId);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
assertNotNull(jmsMessage.getJMSCorrelationID());
assertEquals(jmsCorrelationId, jmsMessage.getJMSCorrelationID());
}
@Test
public void testJmsCorrelationIdIgnoredIfIncorrectType() throws JMSException {
StringMessage message = new StringMessage("test");
message.getHeader().setAttribute(JmsAttributeKeys.CORRELATION_ID, new Integer(123));
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
assertNull(jmsMessage.getJMSCorrelationID());
}
@Test
public void testJmsTypeMappedFromHeader() throws JMSException {
StringMessage message = new StringMessage("test");
String jmsType = "testing";
message.getHeader().setAttribute(JmsAttributeKeys.TYPE, jmsType);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
assertNotNull(jmsMessage.getJMSType());
assertEquals(jmsType, jmsMessage.getJMSType());
}
@Test
public void testJmsTypeIgnoredIfIncorrectType() throws JMSException {
StringMessage message = new StringMessage("test");
message.getHeader().setAttribute(JmsAttributeKeys.TYPE, new Integer(123));
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
assertNull(jmsMessage.getJMSType());
}
@Test
public void testUserDefinedPropertyMappedFromHeader() throws JMSException {
StringMessage message = new StringMessage("test");
message.getHeader().setAttribute(JmsAttributeKeys.USER_DEFINED_ATTRIBUTE_PREFIX + "foo", new Integer(123));
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
Object value = jmsMessage.getObjectProperty("foo");
assertNotNull(value);
assertEquals(Integer.class, value.getClass());
assertEquals(123, ((Integer) value).intValue());
}
@Test
public void testUserDefinedPropertyWithUnsupportedType() throws JMSException {
StringMessage message = new StringMessage("test");
Destination destination = new Destination() {};
message.getHeader().setAttribute(JmsAttributeKeys.USER_DEFINED_ATTRIBUTE_PREFIX + "destination", destination);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
javax.jms.Message jmsMessage = new StubTextMessage();
mapper.mapFromMessageHeader(message.getHeader(), jmsMessage);
Object value = jmsMessage.getObjectProperty("foo");
assertNull(value);
}
@Test
public void testJmsReplyToMappedToHeader() throws JMSException {
StringMessage message = new StringMessage("test");
Destination replyTo = new Destination() {};
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSReplyTo(replyTo);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
mapper.mapToMessageHeader(jmsMessage, message.getHeader());
Object attrib = message.getHeader().getAttribute(JmsAttributeKeys.REPLY_TO);
assertNotNull(attrib);
assertSame(replyTo, attrib);
}
@Test
public void testJmsCorrelationIdMappedToHeader() throws JMSException {
StringMessage message = new StringMessage("test");
String correlationId = "ABC-123";
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSCorrelationID(correlationId);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
mapper.mapToMessageHeader(jmsMessage, message.getHeader());
Object attrib = message.getHeader().getAttribute(JmsAttributeKeys.CORRELATION_ID);
assertNotNull(attrib);
assertSame(correlationId, attrib);
}
@Test
public void testJmsTypeMappedToHeader() throws JMSException {
StringMessage message = new StringMessage("test");
String type = "testing";
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setJMSType(type);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
mapper.mapToMessageHeader(jmsMessage, message.getHeader());
Object attrib = message.getHeader().getAttribute(JmsAttributeKeys.TYPE);
assertNotNull(attrib);
assertSame(type, attrib);
}
@Test
public void testUserDefinedPropertyMappedToHeader() throws JMSException {
StringMessage message = new StringMessage("test");
javax.jms.Message jmsMessage = new StubTextMessage();
jmsMessage.setIntProperty("foo", 123);
DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper();
mapper.mapToMessageHeader(jmsMessage, message.getHeader());
Object attrib = message.getHeader().getAttribute(JmsAttributeKeys.USER_DEFINED_ATTRIBUTE_PREFIX + "foo");
assertNotNull(attrib);
assertEquals(Integer.class, attrib.getClass());
assertEquals(123, ((Integer) attrib).intValue());
}
}

View File

@@ -1,102 +0,0 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import javax.jms.Destination;
import javax.jms.JMSException;
import org.junit.Test;
import org.springframework.integration.message.StringMessage;
/**
* @author Mark Fisher
*/
public class DefaultJmsMessagePostProcessorTests {
@Test
public void testJmsReplyTo() throws JMSException {
StringMessage message = new StringMessage("test1");
Destination replyTo = new Destination() {};
message.getHeader().setAttribute(JmsTargetAdapter.JMS_REPLY_TO, replyTo);
DefaultJmsMessagePostProcessor postProcessor = new DefaultJmsMessagePostProcessor();
javax.jms.Message jmsMessage = new StubTextMessage();
postProcessor.postProcessJmsMessage(jmsMessage, message.getHeader());
assertNotNull(jmsMessage.getJMSReplyTo());
assertSame(replyTo, jmsMessage.getJMSReplyTo());
}
@Test
public void testJmsReplyToIgnoredIfIncorrectType() throws JMSException {
StringMessage message = new StringMessage("test1");
message.getHeader().setAttribute(JmsTargetAdapter.JMS_REPLY_TO, "not-a-destination");
DefaultJmsMessagePostProcessor postProcessor = new DefaultJmsMessagePostProcessor();
javax.jms.Message jmsMessage = new StubTextMessage();
postProcessor.postProcessJmsMessage(jmsMessage, message.getHeader());
assertNull(jmsMessage.getJMSReplyTo());
}
@Test
public void testJmsCorrelationId() throws JMSException {
StringMessage message = new StringMessage("test1");
String jmsCorrelationId = "ABC-123";
message.getHeader().setAttribute(JmsTargetAdapter.JMS_CORRELATION_ID, jmsCorrelationId);
DefaultJmsMessagePostProcessor postProcessor = new DefaultJmsMessagePostProcessor();
javax.jms.Message jmsMessage = new StubTextMessage();
postProcessor.postProcessJmsMessage(jmsMessage, message.getHeader());
assertNotNull(jmsMessage.getJMSCorrelationID());
assertEquals(jmsCorrelationId, jmsMessage.getJMSCorrelationID());
}
@Test
public void testJmsCorrelationIdIgnoredIfIncorrectType() throws JMSException {
StringMessage message = new StringMessage("test1");
message.getHeader().setAttribute(JmsTargetAdapter.JMS_CORRELATION_ID, new Integer(123));
DefaultJmsMessagePostProcessor postProcessor = new DefaultJmsMessagePostProcessor();
javax.jms.Message jmsMessage = new StubTextMessage();
postProcessor.postProcessJmsMessage(jmsMessage, message.getHeader());
assertNull(jmsMessage.getJMSCorrelationID());
}
@Test
public void testJmsType() throws JMSException {
StringMessage message = new StringMessage("test1");
String jmsType = "testing";
message.getHeader().setAttribute(JmsTargetAdapter.JMS_TYPE, jmsType);
DefaultJmsMessagePostProcessor postProcessor = new DefaultJmsMessagePostProcessor();
javax.jms.Message jmsMessage = new StubTextMessage();
postProcessor.postProcessJmsMessage(jmsMessage, message.getHeader());
assertNotNull(jmsMessage.getJMSType());
assertEquals(jmsType, jmsMessage.getJMSType());
}
@Test
public void testJmsTypeIgnoredIfIncorrectType() throws JMSException {
StringMessage message = new StringMessage("test1");
message.getHeader().setAttribute(JmsTargetAdapter.JMS_TYPE, new Integer(123));
DefaultJmsMessagePostProcessor postProcessor = new DefaultJmsMessagePostProcessor();
javax.jms.Message jmsMessage = new StubTextMessage();
postProcessor.postProcessJmsMessage(jmsMessage, message.getHeader());
assertNull(jmsMessage.getJMSType());
}
}

View File

@@ -1,6 +1,23 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.jms;
import java.util.Enumeration;
import java.util.concurrent.ConcurrentHashMap;
import javax.jms.Destination;
import javax.jms.JMSException;
@@ -16,6 +33,8 @@ public class StubTextMessage implements TextMessage {
private String type;
private ConcurrentHashMap<String, Object> properties = new ConcurrentHashMap<String, Object>();
public String getText() throws JMSException {
return this.text;
@@ -103,11 +122,11 @@ public class StubTextMessage implements TextMessage {
}
public Object getObjectProperty(String name) throws JMSException {
return null;
return this.properties.get(name);
}
public Enumeration getPropertyNames() throws JMSException {
return null;
return this.properties.keys();
}
public short getShortProperty(String name) throws JMSException {
@@ -119,22 +138,27 @@ public class StubTextMessage implements TextMessage {
}
public boolean propertyExists(String name) throws JMSException {
return false;
return this.properties.containsKey(name);
}
public void setBooleanProperty(String name, boolean value) throws JMSException {
this.properties.put(name, value);
}
public void setByteProperty(String name, byte value) throws JMSException {
this.properties.put(name, value);
}
public void setDoubleProperty(String name, double value) throws JMSException {
this.properties.put(name, value);
}
public void setFloatProperty(String name, float value) throws JMSException {
this.properties.put(name, value);
}
public void setIntProperty(String name, int value) throws JMSException {
this.properties.put(name, value);
}
public void setJMSCorrelationID(String correlationID) throws JMSException {
@@ -174,15 +198,19 @@ public class StubTextMessage implements TextMessage {
}
public void setLongProperty(String name, long value) throws JMSException {
this.properties.put(name, value);
}
public void setObjectProperty(String name, Object value) throws JMSException {
this.properties.put(name, value);
}
public void setShortProperty(String name, short value) throws JMSException {
this.properties.put(name, value);
}
public void setStringProperty(String name, String value) throws JMSException {
this.properties.put(name, value);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -93,12 +93,12 @@ public class MailTargetAdapterTests {
@Test
public void testDefaultMailHeaderGenerator() {
StringMessage message = new StringMessage(MailTestsHelper.MESSAGE_TEXT);
message.getHeader().setAttribute(MailTargetAdapter.SUBJECT, MailTestsHelper.SUBJECT);
message.getHeader().setAttribute(MailTargetAdapter.TO, MailTestsHelper.TO);
message.getHeader().setAttribute(MailTargetAdapter.CC, MailTestsHelper.CC);
message.getHeader().setAttribute(MailTargetAdapter.BCC, MailTestsHelper.BCC);
message.getHeader().setAttribute(MailTargetAdapter.FROM, MailTestsHelper.FROM);
message.getHeader().setAttribute(MailTargetAdapter.REPLY_TO, MailTestsHelper.REPLY_TO);
message.getHeader().setAttribute(MailAttributeKeys.SUBJECT, MailTestsHelper.SUBJECT);
message.getHeader().setAttribute(MailAttributeKeys.TO, MailTestsHelper.TO);
message.getHeader().setAttribute(MailAttributeKeys.CC, MailTestsHelper.CC);
message.getHeader().setAttribute(MailAttributeKeys.BCC, MailTestsHelper.BCC);
message.getHeader().setAttribute(MailAttributeKeys.FROM, MailTestsHelper.FROM);
message.getHeader().setAttribute(MailAttributeKeys.REPLY_TO, MailTestsHelper.REPLY_TO);
this.mailTargetAdapter.handle(message);
SimpleMailMessage mailMessage = MailTestsHelper.createSimpleMailMessage();
assertEquals("no mime message should have been sent",