Questo contenuto non è disponibile nella lingua selezionata.
Chapter 36. Type Converters
Abstract
Apache Camel has a built-in type conversion mechanism, which is used to convert message bodies and message headers to different types. This chapter explains how to extend the type conversion mechanism by adding your own custom converter methods.
36.1. Type Converter Architecture Copia collegamentoCollegamento copiato negli appunti!
Overview Copia collegamentoCollegamento copiato negli appunti!
This section describes the overall architecture of the type converter mechanism, which you must understand, if you want to write custom type converters. If you only need to use the built-in type converters, see Chapter 34, Understanding Message Formats.
Type converter interface Copia collegamentoCollegamento copiato negli appunti!
Example 36.1, “TypeConverter Interface” shows the definition of the org.apache.camel.TypeConverter interface, which all type converters must implement.
Example 36.1. TypeConverter Interface
package org.apache.camel; public interface TypeConverter { <T> T convertTo(Class<T> type, Object value); }
package org.apache.camel;
public interface TypeConverter {
<T> T convertTo(Class<T> type, Object value);
}
Controller type converter Copia collegamentoCollegamento copiato negli appunti!
The Apache Camel type converter mechanism follows a controller/worker pattern. There are many worker type converters, which are each capable of performing a limited number of type conversions, and a single controller type converter, which aggregates the type conversions performed by the workers. The controller type converter acts as a front-end for the worker type converters. When you request the controller to perform a type conversion, it selects the appropriate worker and delegates the conversion task to that worker.
For users of the type conversion mechanism, the controller type converter is the most important because it provides the entry point for accessing the conversion mechanism. During start up, Apache Camel automatically associates a controller type converter instance with the CamelContext
object. To obtain a reference to the controller type converter, you call the CamelContext.getTypeConverter()
method. For example, if you have an exchange object, exchange
, you can obtain a reference to the controller type converter as shown in Example 36.2, “Getting a Controller Type Converter”.
Example 36.2. Getting a Controller Type Converter
org.apache.camel.TypeConverter tc = exchange.getContext().getTypeConverter();
org.apache.camel.TypeConverter tc = exchange.getContext().getTypeConverter();
Type converter loader Copia collegamentoCollegamento copiato negli appunti!
The controller type converter uses a type converter loader to populate the registry of worker type converters. A type converter loader is any class that implements the TypeConverterLoader interface. Apache Camel currently uses only one kind of type converter loader — the annotation type converter loader (of AnnotationTypeConverterLoader
type).
Type conversion process Copia collegamentoCollegamento copiato negli appunti!
Figure 36.1, “Type Conversion Process” gives an overview of the type conversion process, showing the steps involved in converting a given data value, value
, to a specified type, toType
.
Figure 36.1. Type Conversion Process
The type conversion mechanism proceeds as follows:
-
The
CamelContext
object holds a reference to the controller TypeConverter instance. The first step in the conversion process is to retrieve the controller type converter by callingCamelContext.getTypeConverter()
. -
Type conversion is initiated by calling the
convertTo()
method on the controller type converter. This method instructs the type converter to convert the data object,value
, from its original type to the type specified by thetoType
argument. -
Because the controller type converter is a front end for many different worker type converters, it looks up the appropriate worker type converter by checking a registry of type mappings The registry of type converters is keyed by a type mapping pair
(toType, fromType)
. If a suitable type converter is found in the registry, the controller type converter calls the worker’sconvertTo()
method and returns the result. - If a suitable type converter cannot be found in the registry, the controller type converter loads a new type converter, using the type converter loader.
-
The type converter loader searches the available JAR libraries on the classpath to find a suitable type converter. Currently, the loader strategy that is used is implemented by the annotation type converter loader, which attempts to load a class annotated by the
org.apache.camel.Converter
annotation. See the section called “Create a TypeConverter file”. -
If the type converter loader is successful, a new worker type converter is loaded and entered into the type converter registry. This type converter is then used to convert the
value
argument to thetoType
type. -
If the data is successfully converted, the converted data value is returned. If the conversion does not succeed,
null
is returned.
36.2. Handling Duplicate Type Converters Copia collegamentoCollegamento copiato negli appunti!
You can configure what must happen if a duplicate type converter is added.
In the TypeConverterRegistry
(See Section 36.3, “Implementing Type Converter Using Annotations”) you can set the action to Override, Ignore or Fail using the following code:
typeconverterregistry = camelContext.getTypeConverter() // Define the behaviour if the TypeConverter already exists typeconverterregistry.setTypeConverterExists(TypeConverterExists.Override);
typeconverterregistry = camelContext.getTypeConverter()
// Define the behaviour if the TypeConverter already exists
typeconverterregistry.setTypeConverterExists(TypeConverterExists.Override);
Override in this code can be replaced by Ignore or Fail, depending on your requirements.
TypeConverterExists Class Copia collegamentoCollegamento copiato negli appunti!
The TypeConverterExists class consists of the following commands:
36.3. Implementing Type Converter Using Annotations Copia collegamentoCollegamento copiato negli appunti!
Overview Copia collegamentoCollegamento copiato negli appunti!
The type conversion mechanism can easily be customized by adding a new worker type converter. This section describes how to implement a worker type converter and how to integrate it with Apache Camel, so that it is automatically loaded by the annotation type converter loader.
How to implement a type converter Copia collegamentoCollegamento copiato negli appunti!
To implement a custom type converter, perform the following steps:
Implement an annotated converter class Copia collegamentoCollegamento copiato negli appunti!
You can implement a custom type converter class using the @Converter
annotation. You must annotate the class itself and each of the static
methods intended to perform type conversion. Each converter method takes an argument that defines the from type, optionally takes a second Exchange
argument, and has a non-void return value that defines the to type. The type converter loader uses Java reflection to find the annotated methods and integrate them into the type converter mechanism. Example 36.3, “Example of an Annotated Converter Class” shows an example of an annotated converter class that defines a converter method for converting from java.io.File
to java.io.InputStream
and another converter method (with an Exchange
argument) for converting from byte[]
to String
.
Example 36.3. Example of an Annotated Converter Class
The toInputStream()
method is responsible for performing the conversion from the File
type to the InputStream
type and the toString()
method is responsible for performing the conversion from the byte[]
type to the String
type.
The method name is unimportant, and can be anything you choose. What is important are the argument type, the return type, and the presence of the @Converter
annotation.
Create a TypeConverter file Copia collegamentoCollegamento copiato negli appunti!
To enable the discovery mechanism (which is implemented by the annotation type converter loader) for your custom converter, create a TypeConverter
file at the following location:
META-INF/services/org/apache/camel/TypeConverter
META-INF/services/org/apache/camel/TypeConverter
The TypeConverter
file must contain a comma-separated list of Fully Qualified Names (FQN) of type converter classes. For example, if you want the type converter loader to search the YourPackageName.
YourClassName package for annotated converter classes, the TypeConverter
file would have the following contents:
com.PackageName.FooClass
com.PackageName.FooClass
An alternative method of enabling the discovery mechanism is to add just package names to the TypeConverter
file. For example, the TypeConverter
file would have the following contents:
com.PackageName
com.PackageName
This would cause the package scanner to scan through the packages for the @Converter
tag. Using the FQN method is faster and is the preferred method.
Package the type converter Copia collegamentoCollegamento copiato negli appunti!
The type converter is packaged as a JAR file containing the compiled classes of your custom type converters and the META-INF
directory. Put this JAR file on your classpath to make it available to your Apache Camel application.
Fallback converter method Copia collegamentoCollegamento copiato negli appunti!
In addition to defining regular converter methods using the @Converter
annotation, you can optionally define a fallback converter method using the @FallbackConverter
annotation. The fallback converter method will only be tried, if the controller type converter fails to find a regular converter method in the type registry.
The essential difference between a regular converter method and a fallback converter method is that whereas a regular converter is defined to perform conversion between a specific pair of types (for example, from byte[]
to String
), a fallback converter can potentially perform conversion between any pair of types. It is up to the code in the body of the fallback converter method to figure out which conversions it is able to perform. At run time, if a conversion cannot be performed by a regular converter, the controller type converter iterates through every available fallback converter until it finds one that can perform the conversion.
The method signature of a fallback converter can have either of the following forms:
Where MethodName is an arbitrary method name for the fallback converter.
For example, the following code extract (taken from the implementation of the File component) shows a fallback converter that can convert the body of a GenericFile
object, exploiting the type converters already available in the type converter registry:
36.4. Implementing a Type Converter Directly Copia collegamentoCollegamento copiato negli appunti!
Overview Copia collegamentoCollegamento copiato negli appunti!
Generally, the recommended way to implement a type converter is to use an annotated class, as described in the previous section, Section 36.3, “Implementing Type Converter Using Annotations”. But if you want to have complete control over the registration of your type converter, you can implement a custom worker type converter and add it directly to the type converter registry, as described here.
Implement the TypeConverter interface Copia collegamentoCollegamento copiato negli appunti!
To implement your own type converter class, define a class that implements the TypeConverter
interface. For example, the following MyOrderTypeConverter
class converts an integer value to a MyOrder
object, where the integer value is used to initialize the order ID in the MyOrder
object.
Add the type converter to the registry Copia collegamentoCollegamento copiato negli appunti!
You can add the custom type converter directly to the type converter registry using code like the following:
// Add the custom type converter to the type converter registry context.getTypeConverterRegistry().addTypeConverter(MyOrder.class, String.class, new MyOrderTypeConverter());
// Add the custom type converter to the type converter registry
context.getTypeConverterRegistry().addTypeConverter(MyOrder.class, String.class, new MyOrderTypeConverter());
Where context
is the current org.apache.camel.CamelContext
instance. The addTypeConverter()
method registers the MyOrderTypeConverter
class against the specific type conversion, from String.class
to MyOrder.class
.
You can add custom type converters to your Camel applications without having to use the META-INF
file. If you are using Spring or Blueprint, then you can just declare a <bean>. CamelContext discovers the bean automatically and adds the converters.
<bean id="myOrderTypeConverters" class="..."/> <camelContext> ... </camelContext>
<bean id="myOrderTypeConverters" class="..."/>
<camelContext>
...
</camelContext>
You can declare multiple <bean>s if you have more classes.