diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/GlobalChannelInterceptor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/GlobalChannelInterceptor.java
index fa2a8ce81c..323a8c0cf4 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/GlobalChannelInterceptor.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/GlobalChannelInterceptor.java
@@ -27,8 +27,10 @@ import java.lang.annotation.Target;
* annotation will be applied as global channel interceptors
* using the provided {@code patterns} to match channel names.
*
- * The annotation can be used at the {@code class} level for {@link org.springframework.stereotype.Component} beans
+ * This annotation can be used at the {@code class} level for {@link org.springframework.stereotype.Component} beans
* and on methods with {@link org.springframework.context.annotation.Bean}.
+ *
+ * This annotation is an analogue of {@code }.
*
* @author Artem Bilan
* @since 4.0
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConverter.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConverter.java
new file mode 100644
index 0000000000..5e68156bfc
--- /dev/null
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConverter.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 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.config;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A marker annotation (an analogue of {@code }) to register
+ * {@link org.springframework.core.convert.converter.Converter},
+ * {@link org.springframework.core.convert.converter.GenericConverter} or
+ * {@link org.springframework.core.convert.converter.ConverterFactory} beans for the {@code integrationConversionService}.
+ *
+ * This annotation can be used at the {@code class} level for {@link org.springframework.stereotype.Component} beans
+ * and on methods with {@link org.springframework.context.annotation.Bean}.
+ *
+ * @author Artem Bilan
+ * @since 4.0
+ */
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface IntegrationConverter {
+
+}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConverterInitializer.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConverterInitializer.java
new file mode 100644
index 0000000000..874dfa14fd
--- /dev/null
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationConverterInitializer.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014 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.config;
+
+import java.util.Set;
+
+import org.springframework.beans.BeanMetadataElement;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.ManagedSet;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.core.type.MethodMetadata;
+import org.springframework.integration.context.IntegrationContextUtils;
+
+/**
+ * @author Artem Bilan
+ * @since 4.0
+ */
+public class IntegrationConverterInitializer implements IntegrationConfigurationInitializer {
+
+ private static final String CONTEXT_PACKAGE = "org.springframework.integration.context.";
+
+ @Override
+ public void initialize(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
+
+ for (String beanName : registry.getBeanDefinitionNames()) {
+ BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
+ if (beanDefinition instanceof AnnotatedBeanDefinition) {
+ AnnotationMetadata metadata = ((AnnotatedBeanDefinition) beanDefinition).getMetadata();
+ boolean hasIntegrationConverter = metadata.hasAnnotation(IntegrationConverter.class.getName());
+
+ if (!hasIntegrationConverter && beanDefinition.getSource() instanceof MethodMetadata) {
+ MethodMetadata beanMethod = (MethodMetadata) beanDefinition.getSource();
+ hasIntegrationConverter = beanMethod.isAnnotated(IntegrationConverter.class.getName());
+ }
+
+ if (hasIntegrationConverter) {
+ this.registerConverter(registry, new RuntimeBeanReference(beanName));
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void registerConverter(BeanDefinitionRegistry registry, BeanMetadataElement converterBeanDefinition) {
+ Set converters = new ManagedSet();
+ if (!registry.containsBeanDefinition(IntegrationContextUtils.CONVERTER_REGISTRAR_BEAN_NAME)) {
+ BeanDefinitionBuilder converterRegistrarBuilder = BeanDefinitionBuilder.genericBeanDefinition(
+ CONTEXT_PACKAGE + "ConverterRegistrar").addConstructorArgValue(converters);
+ registry.registerBeanDefinition(IntegrationContextUtils.CONVERTER_REGISTRAR_BEAN_NAME,
+ converterRegistrarBuilder.getBeanDefinition());
+
+ if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_CONVERSION_SERVICE_BEAN_NAME)) {
+ registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_CONVERSION_SERVICE_BEAN_NAME,
+ new RootBeanDefinition(CONTEXT_PACKAGE + "CustomConversionServiceFactoryBean"));
+ }
+ }
+ else {
+ BeanDefinition converterRegistrarBeanDefinition = registry
+ .getBeanDefinition(IntegrationContextUtils.CONVERTER_REGISTRAR_BEAN_NAME);
+ converters = (Set) converterRegistrarBeanDefinition
+ .getConstructorArgumentValues()
+ .getIndexedArgumentValues()
+ .values()
+ .iterator()
+ .next()
+ .getValue();
+ }
+
+ converters.add(converterBeanDefinition);
+ }
+}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java
index cfa6abced6..e438fa1468 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ConverterParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2014 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.
@@ -21,56 +21,37 @@ import org.w3c.dom.Element;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
-import org.springframework.beans.factory.support.ManagedSet;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.integration.config.IntegrationConverterInitializer;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author Oleg Zhurakousky
* @author Mark Fisher
+ * @author Artem Bilan
* @since 2.0
*/
public class ConverterParser extends AbstractBeanDefinitionParser {
- private final ManagedSet