Bernardo Silva created CAMEL-5618:
-------------------------------------

             Summary: The tag "contextScan" should inject @Converter methods 
from @Converter components.
                 Key: CAMEL-5618
                 URL: https://issues.apache.org/jira/browse/CAMEL-5618
             Project: Camel
          Issue Type: Improvement
          Components: camel-core
    Affects Versions: 2.10.1
            Reporter: Bernardo Silva


The ability to detect converters using "META-INF/services/org/apache/camel" SPI 
is cool, but obligates me to make my converters as static methods.

This brings me 3 issues:
1) It is hard to "mock" the converters in the "CamelTestSupport" because he 
auto-detect the "real" ones;
2) If I want to "inject" beans in my converter class and use it in my converter 
method, I can't.

So, to solve my problem I did a very simple class. I will copy the code at the 
end of this. With this class, I don't use Camel SPI anymore and Spring injects 
the converters for me using "TypeConverterSupport". 

Then, my suggestion is: why the annotation "contextScan" doesn't have a similar 
behavior? It would be very nice and simple.

Thanks,
Bernardo Silva

CLASS:


import java.lang.reflect.Method;
import java.util.Map;

import org.apache.camel.CamelContext;
import org.apache.camel.Converter;
import org.apache.camel.Exchange;
import org.apache.camel.TypeConversionException;
import org.apache.camel.support.TypeConverterSupport;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@SuppressWarnings("unchecked")
@Component
public class CamelConverterInjector implements InitializingBean {

        @Autowired
        private CamelContext camelContext;

        @Autowired
        private ApplicationContext springContext;

        private static abstract class TypeConverterWrapper extends 
TypeConverterSupport {
                protected final Method method;
                protected final Object bean;

                protected TypeConverterWrapper(Method method, Object bean) {
                        this.method = method;
                        this.bean = method;
                }
        }

        private static final class TypeConverterSimpleWrapper extends 
TypeConverterWrapper {
                protected TypeConverterSimpleWrapper(Method method, Object 
bean) {
                        super(method, bean);
                }

                public <T> T convertTo(Class<T> type, Exchange exchange, Object 
value) throws TypeConversionException {
                        try {
                                return (T) method.invoke(bean, value);
                        } catch (Throwable t) {
                                throw new TypeConversionException(value, type, 
t);
                        }
                }
        }

        private static final class TypeConverterExchangeWrapper extends 
TypeConverterWrapper {
                protected TypeConverterExchangeWrapper(Method method, Object 
bean) {
                        super(method, bean);
                }

                public <T> T convertTo(Class<T> type, Exchange exchange, Object 
value) throws TypeConversionException {
                        try {
                                return (T) method.invoke(bean, value, exchange);
                        } catch (Throwable t) {
                                throw new TypeConversionException(value, type, 
t);
                        }
                }
        }

        public void afterPropertiesSet() throws Exception {
                final Map<String, Object> beans = 
springContext.getBeansWithAnnotation(Converter.class);
                for (String beanName : beans.keySet()) {
                        final Object bean = beans.get(beanName);
                        for (Method method : bean.getClass().getMethods()) {
                                if (method.getAnnotation(Converter.class) != 
null) {
                                        final Class<?>[] parameterTypes = 
method.getParameterTypes();
                                        final TypeConverterWrapper converter;
                                        if (parameterTypes.length == 1) {
                                                converter = new 
TypeConverterSimpleWrapper(method, bean);
                                        } else {
                                                converter = new 
TypeConverterExchangeWrapper(method, bean);
                                        }
                                        
camelContext.getTypeConverterRegistry().addTypeConverter(method.getReturnType(),
 parameterTypes[0], converter);
                                }
                        }
                }
        }

}


--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to