diff --git a/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java b/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java
index fe69a7ae91..e528ae0677 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/channel/AbstractMessageChannel.java
@@ -20,19 +20,19 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import org.springframework.core.OrderComparator;
import org.springframework.core.convert.ConversionService;
+import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.history.MessageHistory;
import org.springframework.integration.history.TrackableComponent;
import org.springframework.integration.support.MessageBuilder;
+import org.springframework.integration.support.converter.DefaultDatatypeChannelMessageConverter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageDeliveryException;
import org.springframework.messaging.MessagingException;
+import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -51,8 +51,6 @@ import org.springframework.util.StringUtils;
public abstract class AbstractMessageChannel extends IntegrationObjectSupport
implements MessageChannel, TrackableComponent, ChannelInterceptorAware {
- protected final Log logger = LogFactory.getLog(this.getClass());
-
private volatile boolean shouldTrack = false;
private volatile Class>[] datatypes = new Class>[] { Object.class };
@@ -61,6 +59,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
private volatile String fullChannelName;
+ private volatile MessageConverter messageConverter;
@Override
public String getComponentType() {
@@ -83,7 +82,7 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
*
* @param datatypes The supported data types.
*
- * @see #setConversionService(ConversionService)
+ * @see #setMessageConverter(MessageConverter)
*/
public void setDatatypes(Class>... datatypes) {
this.datatypes = (datatypes != null && datatypes.length > 0)
@@ -129,14 +128,36 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
* does not already match. If this property is not set explicitly but
* the channel is managed within a context, it will attempt to locate a
* bean named "integrationConversionService" defined within that context.
- * Finally, if that bean is not available, it will fallback to the
- * "conversionService" bean, if available.
*
* @param conversionService The conversion service.
+ * @deprecated No longer used; see {@link DefaultDatatypeChannelMessageConverter}.
*/
+ @Deprecated
@Override
public void setConversionService(ConversionService conversionService) {
- super.setConversionService(conversionService);
+ if (logger.isWarnEnabled()) {
+ logger.warn("The conversion service is no longer used; see setMessageConverter()");
+ }
+ }
+
+ /**
+ * Specify the {@link MessageConverter} to use when trying to convert to
+ * one of this channel's supported datatypes (in order) for a Message whose payload
+ * does not already match.
+ *
+ * Note: only the {@link MessageConverter#fromMessage(Message, Class)}
+ * method is used. If the returned object is not a {@link Message}, the inbound
+ * headers will be copied; if the returned object is a {@code Message}, it is
+ * expected that the converter will have fully populated the headers; no
+ * further action is performed by the channel. If {@code null} is returned,
+ * conversion to the next datatype (if any) will be attempted.
+ *
+ * Defaults to a {@link DefaultDatatypeChannelMessageConverter}.
+ *
+ * @param messageConverter The message converter.
+ */
+ public void setMessageConverter(MessageConverter messageConverter) {
+ this.messageConverter = messageConverter;
}
/**
@@ -156,6 +177,21 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
return this.interceptors;
}
+ @Override
+ protected void onInit() throws Exception {
+ super.onInit();
+ if (this.messageConverter == null) {
+ if (this.getBeanFactory() != null) {
+ if (this.getBeanFactory().containsBean(
+ IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME)) {
+ this.messageConverter = this.getBeanFactory().getBean(
+ IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME,
+ MessageConverter.class);
+ }
+ }
+ }
+ }
+
/**
* Returns the fully qualified channel name including the application context
* id, if available.
@@ -235,13 +271,17 @@ public abstract class AbstractMessageChannel extends IntegrationObjectSupport
return message;
}
}
- // second pass applies conversion if possible, attempting datatypes in order
- ConversionService conversionService = this.getConversionService();
- if (conversionService != null) {
+ if (this.messageConverter != null) {
+ // second pass applies conversion if possible, attempting datatypes in order
for (Class> datatype : this.datatypes) {
- if (conversionService.canConvert(message.getPayload().getClass(), datatype)) {
- Object convertedPayload = conversionService.convert(message.getPayload(), datatype);
- return MessageBuilder.withPayload(convertedPayload).copyHeaders(message.getHeaders()).build();
+ Object converted = this.messageConverter.fromMessage(message, datatype);
+ if (converted != null) {
+ if (converted instanceof Message) {
+ return (Message>) converted;
+ }
+ else {
+ return MessageBuilder.withPayload(converted).copyHeaders(message.getHeaders()).build();
+ }
}
}
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java
index 4a7af30840..473bab1aae 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationRegistrar.java
@@ -48,6 +48,7 @@ import org.springframework.integration.config.annotation.MessagingAnnotationPost
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.context.IntegrationProperties;
import org.springframework.integration.expression.IntegrationEvaluationContextAwareBeanPostProcessor;
+import org.springframework.integration.support.converter.DefaultDatatypeChannelMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -55,6 +56,7 @@ import org.springframework.util.StringUtils;
* {@link ImportBeanDefinitionRegistrar} implementation that configures integration infrastructure.
*
* @author Artem Bilan
+ * @author Gary Russell
* @since 4.0
*/
public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, BeanClassLoaderAware {
@@ -84,6 +86,7 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
this.registerHeaderChannelRegistry(registry);
this.registerBuiltInBeans(registry);
this.registerDefaultConfiguringBeanFactoryPostProcessor(registry);
+ this.registerDefaultDatatypeChannelMessageConverter(registry);
if (importingClassMetadata != null) {
this.registerMessagingAnnotationPostProcessors(importingClassMetadata, registry);
}
@@ -325,4 +328,29 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
}
}
+ /**
+ * Register the default datatype channel MessageConverter.
+ *
+ * @param registry the registry.
+ */
+ private void registerDefaultDatatypeChannelMessageConverter(BeanDefinitionRegistry registry) {
+ boolean alreadyRegistered = false;
+ if (registry instanceof ListableBeanFactory) {
+ alreadyRegistered = ((ListableBeanFactory) registry)
+ .containsBean(IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME);
+ }
+ else {
+ alreadyRegistered = registry
+ .isBeanNameInUse(IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME);
+ }
+ if (!alreadyRegistered) {
+ BeanDefinitionBuilder converterBuilder = BeanDefinitionBuilder
+ .genericBeanDefinition(DefaultDatatypeChannelMessageConverter.class);
+ registry.registerBeanDefinition(
+ IntegrationContextUtils.INTEGRATION_DATATYPE_CHANNEL_MESSAGE_CONVERTER_BEAN_NAME,
+ converterBuilder.getBeanDefinition());
+ }
+
+ }
+
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/MessageHistoryRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/config/MessageHistoryRegistrar.java
index 5c47be3ed4..063f32ff03 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/MessageHistoryRegistrar.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/MessageHistoryRegistrar.java
@@ -54,7 +54,7 @@ public class MessageHistoryRegistrar implements ImportBeanDefinitionRegistrar {
componentNamePatterns = componentNamePatternsString.substring(0, componentNamePatternsString.length() - 1);
}
- if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_MESSAGE_HISTORY_CONFIGURER)) {
+ if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_MESSAGE_HISTORY_CONFIGURER_BEAN_NAME)) {
Set