2.6. Transforming Message Content

Abstract

Apache Camel supports a variety of approaches to transforming message content. In addition to a simple native API for modifying message content, Apache Camel supports integration with several different third-party libraries and transformation standards.

6.1. Simple Message Transformations

Overview

The Java DSL has a built-in API that enables you to perform simple transformations on incoming and outgoing messages. For example, the rule shown in Example 2.1, “Simple Transformation of Incoming Messages” appends the text, World!, to the end of the incoming message body.

Example 2.1. Simple Transformation of Incoming Messages

from("SourceURL").setBody(body().append(" World!")).to("TargetURL");

Where the setBody() command replaces the content of the incoming message’s body.

API for simple transformations

You can use the following API classes to perform simple transformations of the message content in a router rule:

    org.apache.camel.model.ProcessorDefinition
    org.apache.camel.builder.Builder
    org.apache.camel.builder.ValueBuilder 

ProcessorDefinition class

The org.apache.camel.model.ProcessorDefinition class defines the DSL commands you can insert directly into a router rule—for example, the setBody() command in Example 2.1, “Simple Transformation of Incoming Messages”. Table 2.5, “Transformation Methods from the ProcessorDefinition Class” shows the ProcessorDefinition methods that are relevant to transforming message content:

Table 2.5. Transformation Methods from the ProcessorDefinition Class 
这里写图片描述 
这里写图片描述

Builder class

The org.apache.camel.builder.Builder class provides access to message content in contexts where expressions or predicates are expected. In other words, Builder methods are typically invoked in the arguments of DSL commands—for example, the body() command in Example 2.1, “Simple Transformation of Incoming Messages”. Table 2.6, “Methods from the Builder Class” summarizes the static methods available in the Builder class.

Table 2.6. Methods from the Builder Class 
这里写图片描述 
这里写图片描述

ValueBuilder class

The org.apache.camel.builder.ValueBuilder class enables you to modify values returned by the Builder methods. In other words, the methods in ValueBuilder provide a simple way of modifying message content. Table 2.7, “Modifier Methods from the ValueBuilder Class” summarizes the methods available in the ValueBuilder class. That is, the table shows only the methods that are used to modify the value they are invoked on (for full details, see the API Reference documentation).

Table 2.7. Modifier Methods from the ValueBuilder Class 
这里写图片描述 
这里写图片描述 
这里写图片描述

6.2. Marshalling and Unmarshalling

Java DSL commands 
You can convert between low-level and high-level message formats using the following commands:

 marshal()— Converts a high-level data format to a low-level data format.
    unmarshal() — Converts a low-level data format to a high-level data format. 

Data formats

Apache Camel supports marshalling and unmarshalling of the following data formats:

Java serialization
JAXB
XMLBeans
XStream 

Java serialization

Enables you to convert a Java object to a blob of binary data. For this data format, unmarshalling converts a binary blob to a Java object, and marshalling converts a Java object to a binary blob. For example, to read a serialized Java object from an endpoint, SourceURL, and convert it to a Java object, you use a rule like the following:

from("SourceURL").unmarshal().serialization()
.<FurtherProcessing>.to("TargetURL");

Or alternatively, in Spring XML:

<camelContext id="serialization" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <serialization/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

JAXB

Provides a mapping between XML schema types and Java types (see https://jaxb.dev.java.net/). For JAXB, unmarshalling converts an XML data type to a Java object, and marshalling converts a Java object to an XML data type. Before you can use JAXB data formats, you must compile your XML schema using a JAXB compiler to generate the Java classes that represent the XML data types in the schema. This is called binding the schema. After the schema is bound, you define a rule to unmarshal XML data to a Java object, using code like the following:

org.apache.camel.spi.DataFormat jaxb = new org.apache.camel.model.dataformat.JaxbDataFormat("GeneratedPackageName");

from("SourceURL").unmarshal(jaxb)
.<FurtherProcessing>.to("TargetURL");

where GeneratedPackagename is the name of the Java package generated by the JAXB compiler, which contains the Java classes representing your XML schema. 
Or alternatively, in Spring XML:

<camelContext id="jaxb" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <jaxb prettyPrint="true" contextPath="GeneratedPackageName"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

XMLBeans

Provides an alternative mapping between XML schema types and Java types (see http://xmlbeans.apache.org/). For XMLBeans, unmarshalling converts an XML data type to a Java object and marshalling converts a Java object to an XML data type. For example, to unmarshal XML data to a Java object using XMLBeans, you use code like the following:

from("SourceURL").unmarshal().xmlBeans()
.<FurtherProcessing>.to("TargetURL");

Or alternatively, in Spring XML:

<camelContext id="xmlBeans" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="SourceURL"/>
    <unmarshal>
      <xmlBeans prettyPrint="true"/>
    </unmarshal>
    <to uri="TargetURL"/>
  </route>
</camelContext>

XStream

Provides another mapping between XML types and Java types (see http://xstream.codehaus.org/). XStream is a serialization library (like Java serialization), enabling you to convert any Java object to XML. For XStream, unmarshalling converts an XML data type to a Java object, and marshalling converts a Java object to an XML data type.

from("SourceURL").unmarshal().xstream()
.<FurtherProcessing>.to("TargetURL");

Note The XStream data format is currently not supported in Spring XML.

6.3. Endpoint Bindings

What is a binding?

In Apache Camel, a binding is a way of wrapping an endpoint in a contract—for example, by applying a Data Format, a Content Enricher or a validation step. A condition or transformation is applied to the messages coming in, and a complementary condition or transformation is applied to the messages going out.

DataFormatBinding

The DataFormatBinding class is useful for the specific case where you want to define a binding that marshals and unmarshals a particular data format (see Section 6.2, “Marshalling and Unmarshalling”). In this case, all that you need to do to create a binding is to create a DataFormatBinding instance, passing a reference to the relevant data format in the constructor.

For example, the XML DSL snippet in Example 2.2, “JAXB Binding” shows a binding (with ID, jaxb) that is capable of marshalling and unmarshalling the JAXB data format when it is associated with an Apache Camel endpoint:

Example 2.2. JAXB Binding

<beans ... >
    ...
    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

Associating a binding with an endpoint

The following alternatives are available for associating a binding with an endpoint:

the section called “Binding URI”
the section called “BindingComponent” 

Binding URI

To associate a binding with an endpoint, you can prefix the endpoint URI with binding:NameOfBinding, where NameOfBinding is the bean ID of the binding (for example, the ID of a binding bean created in Spring XML).

For example, the following example shows how to associate ActiveMQ endpoints with the JAXB binding defined in Example 2.2, “JAXB Binding”.

<beans ...>
    ...    
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:orderQueue"/>
            <to uri="binding:jaxb:activemq:otherQueue"/>
        </route>
    </camelContext>
    ...    
</beans>

BindingComponent

Instead of using a prefix to associate a binding with an endpoint, you can make the association implicit, so that the binding does not need to appear in the URI. For existing endpoints that do not have an implicit binding, the easiest way to achieve this is to wrap the endpoint using the BindingComponent class.

For example, to associate the jaxb binding with activemq endpoints, you could define a new BindingComponent instance as follows:

<beans ... >
    ...
    <bean id="jaxbmq" class="org.apache.camel.component.binding.BindingComponent">
        <constructor-arg ref="jaxb"/>
        <constructor-arg value="activemq:foo."/>
    </bean>

    <bean id="jaxb" class="org.apache.camel.processor.binding.DataFormatBinding">
        <constructor-arg ref="jaxbformat"/>
    </bean>

    <bean id="jaxbformat" class="org.apache.camel.model.dataformat.JaxbDataFormat">
        <property name="prettyPrint" value="true"/>
        <property name="contextPath" value="org.apache.camel.example"/>
    </bean>

</beans>

Where the (optional) second constructor argument to jaxbmq defines a URI prefix. You can now use the jaxbmq ID as the scheme for an endpoint URI. For example, you can define the following route using this binding component:

<beans ...>
    ...    
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="jaxbmq:firstQueue"/>
            <to uri="jaxbmq:otherQueue"/>
        </route>
    </camelContext>
    ...    
</beans>

The preceding route is equivalent to the following route, which uses the binding URI approach:

<beans ...>
    ...    
    <camelContext xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="binding:jaxb:activemq:foo.firstQueue"/>
            <to uri="binding:jaxb:activemq:foo.otherQueue"/>
        </route>
    </camelContext>
    ...    
</beans>

Note 
For developers that implement a custom Apache Camel component, it 
is possible to achieve this by implementing an endpoint class that 
inherits from the org.apache.camel.spi.HasBinding interface.

BindingComponent constructors

The BindingComponent class supports the following constructors:

public BindingComponent() 
No arguments form. Use property injection to configure the binding component instance.

public BindingComponent(Binding binding) 
Associate this binding component with the specified Binding object, binding.

public BindingComponent(Binding binding, String uriPrefix) 
Associate this binding component with the specified Binding object, binding, and URI prefix, uriPrefix. This is the most commonly used constructor.

public BindingComponent(Binding binding, String uriPrefix, String uriPostfix) 
This constructor supports the additional URI post-fix, uriPostfix, argument, which is automatically appended to any URIs defined using this binding component.

Implementing a custom binding

In addition to the DataFormatBinding, which is used for marshalling and unmarshalling data formats, you can implement your own custom bindings. Define a custom binding as follows:

Implement an org.apache.camel.Processor class to perform a transformation on messages incoming to a consumer endpoint (appearing in a from element).


Implement the org.apache.camel.spi.Binding interface, which acts as a factory for the processor instances. 

Binding interface

Example 2.3, “The org.apache.camel.spi.Binding Interface” shows the definition of the org.apache.camel.spi.Binding interface, which you must implement to define a custom binding.

Example 2.3. The org.apache.camel.spi.Binding Interface

// Java
package org.apache.camel.spi;

import org.apache.camel.Processor;

/**
 * Represents a <a href="http://camel.apache.org/binding.html">Binding</a> or contract
 * which can be applied to an Endpoint; such as ensuring that a particular
 * <a href="http://camel.apache.org/data-format.html">Data Format</a> is used on messages in and out of an endpoint.
 */
public interface Binding {

    /**
     * Returns a new {@link Processor} which is used by a producer on an endpoint to implement
     * the producer side binding before the message is sent to the underlying endpoint.
     */
    Processor createProduceProcessor();

    /**
     * Returns a new {@link Processor} which is used by a consumer on an endpoint to process the
     * message with the binding before its passed to the endpoint consumer producer.
     */
    Processor createConsumeProcessor();
}

When to use bindings

Bindings are useful when you need to apply the same kind of transformation to many different kinds of endpoint.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值