Bean integration provides a general purpose mechanism for processing messages using arbitrary Java objects. By inserting a bean reference into a route, you can call an arbitrary method on a Java object, which can then access and modify the incoming exchange. The mechanism that maps an exchange's contents to the parameters and return values of a bean method is known as parameter binding. Parameter binding can use any combination of the following approaches in order to initialize a method's parameters:
Conventional method signatures — If the method signature conforms to certain conventions, the parameter binding can use Java reflection to determine what parameters to pass.
Annotations and dependency injection — For a more flexible binding mechanism, employ Java annotations to specify what to inject into the method's arguments. This dependency injection mechanism relies on Spring 2.5 component scanning. Normally, if you are deploying your Apache Camel application into a Spring container, the dependency injection mechanism will work automatically.
Explicitly specified parameters — You can specify parameters explicitly (either as constants or using the Simple language), at the point where the bean is invoked.
Beans are made accessible through a bean registry, which is a service that enables you to look up beans using either the class name or the bean ID as a key. The way that you create an entry in the bean registry depends on the underlying framework—for example, plain Java, Spring, Guice, or Blueprint. Registry entries are usually created implicitly (for example, when you instantiate a Spring bean in a Spring XML file).
Apache Camel implements a plug-in strategy for the bean registry, defining an integration layer for accessing beans which makes the underlying registry implementation transparent. Hence, it is possible to integrate Apache Camel applications with a variety of different bean registries, as shown in Table 3.
Table 3. Registry Plug-Ins
| Registry Implementation | Camel Component with Registry Plug-In |
|---|---|
| Spring bean registry | camel-spring |
| Guice bean registry | camel-guice |
| Blueprint bean registry | camel-blueprint |
| OSGi service registry | deployed in OSGi container |
Normally, you do not have to worry about configuring bean registries, because the
relevant bean registry is automatically installed for you. For example, if you are
using the Spring framework to define your routes, the Spring
ApplicationContextRegistry plug-in is automatically installed in
the current CamelContext instance.
Deployment in an OSGi container is a special case. When an Apache Camel route is
deployed into the OSGi container, the CamelContext automatically sets
up a registry chain for resolving bean instances: the registry chain consists of the
OSGi registry, followed by the Blueprint (or Spring) registry.
To process exchange objects using a Java bean (which is a
plain old Java object or POJO), use the bean()
processor, which binds the inbound exchange to a method on the
Java object. For example, to process inbound exchanges using the
class, MyBeanProcessor, define a route like the
following:
from("file:data/inbound")
.bean(MyBeanProcessor.class, "processBody")
.to("file:data/outbound");Where the bean() processor creates an instance of
MyBeanProcessor type and invokes the
processBody() method to process inbound
exchanges. This approach is adequate if you only want to access
the MyBeanProcessor instance from a single route.
However, if you want to access the same
MyBeanProcessor instance from multiple routes,
use the variant of bean() that takes the
Object type as its first argument. For
example:
MyBeanProcessor myBean = new MyBeanProcessor();
from("file:data/inbound")
.bean(myBean, "processBody")
.to("file:data/outbound");
from("activemq:inboundData")
.bean(myBean, "processBody")
.to("activemq:outboundData");If a bean defines overloaded methods, you can choose which of
the overloaded methods to invoke by specifying the method name
along with its parameter types. For example, if the
MyBeanBrocessor class has two overloaded
methods, processBody(String) and
processBody(String,String), you can invoke the
latter overloaded method as follows:
from("file:data/inbound")
.bean(MyBeanProcessor.class, "processBody(String,String)")
.to("file:data/outbound");Alternatively, if you want to identify a method by the number
of parameters it takes, rather than specifying the type of each
parameter explicitly, you can use the wildcard character,
*. For example, to invoke a method named
processBody that takes two parameters,
irrespective of the exact type of the parameters, invoke the
bean() processor as follows:
from("file:data/inbound")
.bean(MyBeanProcessor.class, "processBody(*,*)")
.to("file:data/outbound");When specifying the method, you can use either a simple
unqualified type name—for example,
processBody(Exchange)—or a fully qualified type
name—for example,
processBody(org.apache.camel.Exchange).
![]() | Note |
|---|---|
In the current implementation, the specified type name must be an exact match of the parameter type. Type inheritance is not taken into account. |
You can specify parameter values explicitly, when you call the bean method. The following simple type values can be passed:
Boolean:
trueorfalse.Numeric:
123,7, and so on.String:
'In single quotes'or"In double quotes".Null object:
null.
The following example shows how you can mix explicit parameter values with type specifiers in the same method invocation:
from("file:data/inbound")
.bean(MyBeanProcessor.class, "processBody(String, 'Sample string value', true, 7)")
.to("file:data/outbound");In the preceding example, the value of the first parameter would presumably be determined by a parameter binding annotation (see Basic annotations).
In addition to the simple type values, you can also specify
parameter values using the Simple language (The Simple Language in Routing Expression and Predicate Languages). This means
that the full power of the Simple language is
available when specifying parameter values. For
example, to pass the message body and the value of the
title header to a bean method:
from("file:data/inbound")
.bean(MyBeanProcessor.class, "processBodyAndHeader(${body},${header.title})")
.to("file:data/outbound");You can also pass the entire header hash map as a parameter.
For example, in the following example, the second method
parameter must be declared to be of type
java.util.Map:
from("file:data/inbound")
.bean(MyBeanProcessor.class, "processBodyAndAllHeaders(${body},${header})")
.to("file:data/outbound");To bind exchanges to a bean method, you can define a method signature that conforms to certain conventions. In particular, there are two basic conventions for method signatures:
If you want to implement a bean method that accesses or
modifies the incoming message body, you must define a method
signature that takes a single String argument and
returns a String value. For example:
// Java
package com.acme;
public class MyBeanProcessor {
public String processBody(String body) {
// Do whatever you like to 'body'...
return newBody;
}
}For greater flexibility, you can implement a bean method that
accesses the incoming exchange. This enables you to access or
modify all headers, bodies, and exchange properties. For
processing exchanges, the method signature takes a single
org.apache.camel.Exchange parameter and returns
void. For example:
// Java
package com.acme;
public class MyBeanProcessor {
public void processExchange(Exchange exchange) {
// Do whatever you like to 'exchange'...
exchange.getIn().setBody("Here is a new message body!");
}
}Instead of creating a bean instance in Java, you can create an
instance using Spring XML. In fact, this is the only feasible
approach if you are defining your routes in XML. To define a
bean in XML, use the standard Spring bean element.
The following example shows how to create an instance of
MyBeanProcessor:
<beans ...>
...
<bean id="myBeanId" class="com.acme.MyBeanProcessor"/>
</beans>It is also possible to pass data to the bean's constructor
arguments using Spring syntax. For full details of how to use
the Spring bean element, see The IoC Container from the Spring reference
guide.
When you create an object instance using the bean
element, you can reference it later using the bean's ID (the
value of the bean element's id
attribute). For example, given the bean element
with ID equal to myBeanId, you can reference the
bean in a Java DSL route using the beanRef()
processor, as follows:
from("file:data/inbound").beanRef("myBeanId", "processBody").to("file:data/outbound");Where the beanRef() processor invokes the
MyBeanProcessor.processBody() method on the
specified bean instance. You can also invoke the bean from
within a Spring XML route, using the Camel schema's
bean element. For example:
<camelContext id="CamelContextID" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:data/inbound"/>
<bean ref="myBeanId" method="processBody"/>
<to uri="file:data/outbound"/>
</route>
</camelContext>The basic parameter bindings described in Basic method signatures might not always be convenient to use. For example, if you have a legacy Java class that performs some data manipulation, you might want to extract data from an inbound exchange and map it to the arguments of an existing method signature. For this kind of parameter binding, Apache Camel provides the following kinds of Java annotation:
Table 4
shows the annotations from the org.apache.camel
Java package that you can use to inject message data into the
arguments of a bean method.
Table 4. Basic Bean Annotations
| Annotation | Meaning | Parameter? |
|---|---|---|
@Attachments
| Binds to a list of attachments. | |
@Body
| Binds to an inbound message body. | |
@Header
| Binds to an inbound message header. | String name of the header. |
@Headers
| Binds to a java.util.Map of the
inbound message headers. | |
@OutHeaders
| Binds to a java.util.Map of the
outbound message headers. | |
@Property
| Binds to a named exchange property. | String name of the property. |
@Properties
| Binds to a java.util.Map of the
exchange properties. |
For example, the following class shows you how to use basic
annotations to inject message data into the
processExchange() method arguments.
// Java
import org.apache.camel.*;
public class MyBeanProcessor {
public void processExchange(
@Header(name="user") String user,
@Body String body,
Exchange exchange
) {
// Do whatever you like to 'exchange'...
exchange.getIn().setBody(body + "UserName = " + user);
}
}Notice how you are able to mix the annotations with the
default conventions. As well as injecting the annotated
arguments, the parameter binding also automatically injects the
exchange object into the org.apache.camel.Exchange
argument.
The expression language annotations provide a powerful
mechanism for injecting message data into a bean method's
arguments. Using these annotations, you can invoke an arbitrary
script, written in the scripting language of your choice, to
extract data from an inbound exchange and inject the data into a
method argument. Table 5 shows
the annotations from the org.apache.camel.language
package (and sub-packages, for the non-core annotations) that
you can use to inject message data into the arguments of a bean
method.
Table 5. Expression Language Annotations
| Annotation | Description |
|---|---|
@Bean
| Injects a Bean expression. |
@Constant
| Injects a Constant expression |
@EL
| Injects an EL expression. |
@Groovy
| Injects a Groovy expression. |
@Header
| Injects a Header expression. |
@JavaScript
| Injects a JavaScript expression. |
@OGNL
| Injects an OGNL expression. |
@PHP
| Injects a PHP expression. |
@Python
| Injects a Python expression. |
@Ruby
| Injects a Ruby expression. |
@Simple
| Injects a Simple expression. |
@XPath
| Injects an XPath expression. |
@XQuery
| Injects an XQuery expression. |
For example, the following class shows you how to use the
@XPath annotation to extract a username and a
password from the body of an incoming message in XML
format:
// Java
import org.apache.camel.language.*;
public class MyBeanProcessor {
public void checkCredentials(
@XPath("/credentials/username/text()") String user,
@XPath("/credentials/password/text()") String pass
) {
// Check the user/pass credentials...
...
}
}The @Bean annotation is a special case, because
it enables you to inject the result of invoking a registered
bean. For example, to inject a correlation ID into a method
argument, you can use the @Bean annotation to
invoke an ID generator class, as follows:
// Java
import org.apache.camel.language.*;
public class MyBeanProcessor {
public void processCorrelatedMsg(
@Bean("myCorrIdGenerator") String corrId,
@Body String body
) {
// Check the user/pass credentials...
...
}
}Where the string, myCorrIdGenerator, is the bean
ID of the ID generator instance. The ID generator class can be
instantiated using the spring bean element, as
follows:
<beans ...>
...
<bean id="myCorrIdGenerator" class="com.acme.MyIdGenerator"/>
</beans>Where the MySimpleIdGenerator class could be
defined as follows:
// Java
package com.acme;
public class MyIdGenerator {
private UserManager userManager;
public String generate(
@Header(name = "user") String user,
@Body String payload
) throws Exception {
User user = userManager.lookupUser(user);
String userId = user.getPrimaryId();
String id = userId + generateHashCodeForPayload(payload);
return id;
}
}Notice that you can also use annotations in the referenced
bean class, MyIdGenerator. The only restriction on
the generate() method signature is that it must
return the correct type to inject into the argument annotated by
@Bean. Because the @Bean
annotation does not let you specify a method name, the injection
mechanism simply invokes the first method in the referenced bean
that has the matching return type.
![]() | Note |
|---|---|
Some of the language annotations are available in the core
component ( |
Parameter binding annotations can be inherited from an
interface or from a superclass. For example, if you define a
Java interface with a Header annotation and a
Body annotation, as follows:
// Java
import org.apache.camel.*;
public interface MyBeanProcessorIntf {
void processExchange(
@Header(name="user") String user,
@Body String body,
Exchange exchange
);
}The overloaded methods defined in the implementation class,
MyBeanProcessor, now inherit the annotations
defined in the base interface, as follows:
// Java
import org.apache.camel.*;
public class MyBeanProcessor implements MyBeanProcessorIntf {
public void processExchange(
String user, // Inherits Header annotation
String body, // Inherits Body annotation
Exchange exchange
) {
...
}
}The class that implements a Java interface is often
protected, private or in
package-only scope. If you try to invoke a
method on an implementation class that is restricted in this
way, the bean binding falls back to invoking the corresponding
interface method, which is publicly accessible.
For example, consider the following public
BeanIntf interface:
// Java
public interface BeanIntf {
void processBodyAndHeader(String body, String title);
}Where the BeanIntf interface is implemented by
the following protected BeanIntfImpl class:
// Java
protected class BeanIntfImpl implements BeanIntf {
void processBodyAndHeader(String body, String title) {
...
}
}The following bean invocation would fall back to invoking the
public BeanIntf.processBodyAndHeader method:
from("file:data/inbound")
.bean(BeanIntfImpl.class, "processBodyAndHeader(${body}, ${header.title})")
.to("file:data/outbound");Bean integration has the capability to invoke static methods
without creating an instance of the
associated class. For example, consider the following Java class
that defines the static method,
changeSomething():
// Java
...
public final class MyStaticClass {
private MyStaticClass() {
}
public static String changeSomething(String s) {
if ("Hello World".equals(s)) {
return "Bye World";
}
return null;
}
public void doSomething() {
// noop
}
}You can use bean integration to invoke the static
changeSomething method, as follows:
from("direct:a")
.bean(MyStaticClass.class, "changeSomething")
.to("mock:a");Note that, although this syntax looks identical to the
invocation of an ordinary function, bean integration exploits
Java reflection to identify the method as static and proceeds to
invoke the method without instantiating
MyStaticClass.
In the special case where a route is deployed into a Red Hat JBoss Fuse container,
it is possible to invoke an OSGi service directly
using bean integration. For example, assuming that one of the
bundles in the OSGi container has exported the service,
org.fusesource.example.HelloWorldOsgiService,
you could invoke the sayHello method using the
following bean integration code:
from("file:data/inbound")
.bean(org.fusesource.example.HelloWorldOsgiService.class, "sayHello")
.to("file:data/outbound");You could also invoke the OSGi service from within a Spring or blueprint XML file, using the bean component, as follows:
<to uri="bean:org.fusesource.example.HelloWorldOsgiService?method=sayHello"/>
The way this works is that Apache Camel sets up a chain of registries when it is deployed in the OSGi container. First of all, it looks up the specified class name in the OSGi service registry; if this lookup fails, it then falls back to the local Spring DM or blueprint registry.






![[Note]](imagesdb/note.gif)


