Writing a custom data type converter

If you find that you have written one or more processors that are just casting or converting from one data type to another, then writing a custom Camel Type Converter will help you reduce that boilerplate code. Camel attempts to automatically convert from one data type to another within a route, and allows you to extend its type converter registry with converters between known types.

The Type Converters are like cast operations in Java. If you want to do a more complex data format change, say from XML to JSON, then you should look at Chapter 4, Transformation, Camel's built in Data Format Marshallers (http://camel.apache.org/data-format.html), and the Writing a Custom Data Marshaller recipe.

This recipe will show you how to create and register a custom Type Converter that Camel will use to automatically convert those specified data types.

Getting ready

The Java code for this recipe is located in the org.camelcookbook.extend.typeconverter package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with typeconverter.

This recipe assumes a custom Java class, MyPerson, and a custom bean processor, MyPersonGreeter. The sayHello() method on MyPersonGreeter assumes that the message body is of the type MyPerson. For the purpose of our example integration, we will assume that we need to deal with String message bodies.

This String to MyPerson conversation is quite common in our fictitious integration scenario, so we are going to write a custom Type Converter, and that way Camel can do the conversation automatically for us; without the need to have an explicit step defined within our routes.

MyPerson is a simple data class with a couple of fields:

public class MyPerson {
  private String firstName;
  private String lastName;
  // getters, setters, and equals excluded for brevity
}

MyPersonGreeter is a Java class that takes a MyPerson object as a parameter and performs some processing on it:

public class MyPersonGreeter {
  public String sayHello(MyPerson person) {
    return "Hello " + person.getFirstName()
        + " " + person.getLastName();
  }
}

How to do it...

There are two main steps to creating and using a custom Type Converter. First, you need to create it, and second, you need to register it with Camel.

  1. Create a Java class with a method whose first parameter is of the type you want to convert from, and the return type is of the type you want to convert to. The name of the method is not important. Mark both the class and the conversion method(s) with the @Converter annotation. The second conversion method parameter can optionally be Camel's Exchange if you require additional information to correctly perform the conversion, such as through a header or property.

    Your converter can be static or an instance method. Static methods require less instance caching on Camel's part, so are preferred. Instances, being objects that are configured through Spring, allow you to later inject field settings on a case-by-case basis to influence how the converter works.

    import org.apache.camel.Converter;
    
    @Converter
    public final class MyPersonTypeConverter {
      // Utility classes should not have a public constructor
      private MyPersonTypeConverter() {}
    
      /**
       * Converts a String in the format of
       * "firstName|lastName" to a {@link MyPerson}.
       */
      @Converter
      public static MyPerson convertStringToMyPerson(
          String str) {
        final int index = str.indexOf("|");
        if (index > 0) {
          final MyPerson person = new MyPerson();
          person.setFirstName(str.substring(0, index));
          person.setLastName(str.substring(index + 1));
          return person;
        }
    
        throw new IllegalArgumentException("String must be in" 
            + " format of '<firstName>|<lastName>'");
      }
    }
  2. Register your new Type Converter with Camel. To do this, include the file META-INF/services/org/apache/camel/TypeConverter within your Jar. This TypeConverter file contains a common separated list of either:
    • The fully qualified class names of your type converters (for example, org.cookbook.extend.typeconverter.MyPersonTypeConverter)
    • Java packages to be scanned for classes marked with the @Converter annotation (for example, org.cookbook.extend.typeconverter)
      org.camelcookbook.extend.typeconverter.MyPersonTypeConverter

    In this example, the TypeConverter file only contains a single entry:

Using fully qualified names is the recommended approach as it eliminates the need for Camel to scan all the Jars in the classpath for matches, and as some containers do not work as you would expect with package scanning.

Also note that the file is literally named TypeConverter with no file extension.

How it works...

Camel has a TypeConverterRegistry associated with each Camel context that maintains a list of all TypeConverters. Whenever Camel needs to convert data from one type to another, it uses this registry to find methods that take the source data type as a parameter, and returns the target data type.

There is no need to explicitly tell Camel to convert data; it does it automatically. There is a DSL operation called convertBodyTo, which allows you to explicitly convert data from one type to another. Generally, you do not need to do this unless, for example, your conversion is slow, and you would like to control when that conversion happens during your integration flow, or if the converter selection is potentially ambiguous.

You can also register your custom type converter at runtime using the following code, for example, to convert from a String to an instance of MyOrder:

context.getTypeConverterRegistry()
    .addTypeConverter(MyOrder.class, String.class,
                      new MyOrderTypeConverter());

There's more...

You can use Camel's type conversation capabilities within your own code as long as you have a reference to a Camel context (or an exchange, which knows its Camel context). The following code will convert a String type into MyPerson:

MyPerson person = context.getTypeConverter()
    .convertTo(MyPerson.class, "Scott|Cranton");

There is also an org.apache.camel.util.ExchangeHelper utility class that provides a number of static helper methods such as convertTo, convertToMandatoryType, and getMandatoryInBody. This helper class makes it easier, given an exchange, to perform operations with some internal null checking:

String str = ExchangeHelper.convertToMandatoryType(exchange,
    String.class, value);

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.139.15