...
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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
<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);
}
|