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 Fuse Mediation Router 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.
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, Fuse Mediation Router provides the following kinds of Java annotation:
Table 2.2 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 2.2. 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 2.3 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 2.3. 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 the Fuse ESB 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 Fuse Mediation Router 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)


