Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

So in an endpoint you can convert a body to another type via

Code Block

Message message = exchange.getIn();
Document document = message.getBody(Document.class);

...

To access the registry, you get it from the CamelContext

Code Block
java
java

   CamelContext context = ...
   context.getTypeConverterRegistry()

...

From Camel 2.11.0/2.10.5 onwards these statistics are turned off by default as there is some performance overhead under very high concurrent load. To enable the statistics in Java, do the following:

Code Block

   CamelContext context = ...
   context.setTypeConverterStatisticsEnabled(true);

Or in the XML DSL with:

Code Block
xml
xml

<camelContext xmlns="http://camel.apache.org/schema/spring" typeConverterStatisticsEnabled="true">
...
</camelContext>

...

Wiki Markup
{snippet:id=e3|lang=java|url=camel/trunk/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryTest.java}

Add type converter classes at runtime

Available as of Camel 2.16

From Camel 2.16 onwards you type converter classes can implement org.apache.camel.TypeConverters which is an marker interface. Then for each type converter you want use the @Converter annotation. Then you can add these converters to the registry using

Code Block
MyClassWithConverters myClass = ...
context.getTypeConverterRegistry().addTypeConverters(myClass);

If you are using Spring or Blueprint, then you can just declare a <bean> then CamelContext will automatic discover and add the converters.

Code Block
<bean id="myConverters" class="..."/>
 
<camelContext ...>
   ...
</camelContext>

You can declare multiple <bean>s if you have more classes.

Using this technique do not require to scan the classpath and using the file META-INF/services/org/apache/camel/TypeConverter as discussed in the Discovering Type Converters section. However the latter is highly recommended when developing Camel components or data formats as then the type converters is automatic included out of the box. The functionality from this section requires the end users to explicit add the converters to their Camel applications.

Discovering Type Converters

...

e.g. the following shows how to register a converter from File -> InputStream

Code Block

@Converter
public class IOConverter {

    @Converter
    public static InputStream toInputStream(File file) throws FileNotFoundException {
        return new BufferedInputStream(new FileInputStream(file));
    }
}

...

By default when using a method in a POJO annotation with @Converter returning null is not a valid response. If null is returned, then Camel will regard that type converter as a miss, and prevent from using it in the future. If null should be allowed as a valid response, then from Camel 2.11.2/2.12 onwards you can specify this in the annotation as shown:

Code Block

    @Converter(allowNull = true)
    public static InputStream toInputStream(File file) throws IOException {
        if (file.exist()) {
            return new BufferedInputStream(new FileInputStream(file));
        } else {
            return null;
        }
    }

...

Fallback type converters are used as a last resort for converting a given value to another type. Its used when the regular type converters give up.
The fallback converters is also meant for a broader scope, so its method signature is a bit different:

Code Block

    @FallbackConverter
    public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry)

Or you can use the non generic signature.

Code Block

    @FallbackConverter
    public static Object convertTo(Class type, Exchange exchange, Object value, TypeConverterRegistry registry)

...

For instance in the method below we will handle all type conversions that is based on the wrapper class GenericFile and we let Camel do the type conversions on its body instead.

Code Block

    @FallbackConverter
    public static <T> T convertTo(Class<T> type, Exchange exchange, Object value, TypeConverterRegistry registry) {
        // use a fallback type converter so we can convert the embedded body if the value is GenericFile
        if (GenericFile.class.isAssignableFrom(value.getClass())) {
            GenericFile file = (GenericFile) value;
            Class from = file.getBody().getClass();
            TypeConverter tc = registry.lookup(type, from);
            if (tc != null) {
                Object body = file.getBody();
                return tc.convertTo(type, exchange, body);
            }
        }
        
        return null;
    }

...

The file in the JAR: META-INF/services/org/apache/camel/TypeConverter contains the following line(s)

Code Block

com.foo
com.bar

Each line in the file is a package name. This tells Camel to go scan those packages for any classes that has been annotated with the @Converter.

...

The file in the JAR: META-INF/services/org/apache/camel/TypeConverter contains the following line(s) for FQN class names

Code Block

com.foo.MyConverter
com.bar.MyOtherConverter
com.bar.YetOtherConverter

...

The type converter accepts the Exchange as an optional 2nd parameter. This is usable if the type converter for instance needs information from the current exchange. For instance combined with the encoding support its possible for type converters to convert with the configured encoding. An example from camel-core for the byte[] -> String converter:

Code Block

    @Converter
    public static String toString(byte[] data, Exchange exchange) {
        if (exchange != null) {
            String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
            if (charsetName != null) {
                try {
                    return new String(data, charsetName);
                } catch (UnsupportedEncodingException e) {
                    LOG.warn("Can't convert the byte to String with the charset " + charsetName, e);
                }
            }
        }
        return new String(data);
    }