Bean
...
Binding
The Bean Binding in Camel defines both which methods are invoked and also how the Message is converted into the parameters of the method when it is invoked.
Choosing the method to invoke
The binding of a Camel Message to a bean method call can occur in different ways
- the method name can be specified explicitly in the DSL or when using POJO Consuming
- if the bean can be converted to a Processor using the Type Converter mechanism then this is used to process the message. This mechanism is used by the ActiveMQ component to allow any MessageListener to be invoked by the Bean component
- if the body of the message can be converted to a BeanInvocation (the default payload used by the ProxyHelper) - then that its used to invoke the method and pass the arguments
- if the message contains the header org.apache.camel.MethodName then that method is invoked, converting the body to whatever the argument is to the method
- otherwise the type of the method body is used to try find a method which matches; an error is thrown if a single method cannot be chosen unambiguously.
- you can also use Exchange as the parameter itself, but then the return type must be void.
By default the return value is set on the outbound message body.
Binding Annotations
You can use the Binding Annotations to customize how paramter values are created from the Message
Examples
For example a POJO such as:
...
Here Camel with subscribe to an ActiveMQ queue, then convert the message payload to a String (so dealing with TextMessage, ObjectMessage and BytesMessage in JMS), then process this method.
Using Annotations to bind parameters to the Exchange
Info | ||
---|---|---|
| ||
The annotations below is part of camel-core and its Bean component and thus does not require camel-spring. These annotations is to be used with the Bean component. |
The annotations can be used to bind in situations where traditional methods would result in ambiguous methods. So by adding annotations you can decorate your bean to help Camel invoke the correct method.
You can also use the following annotations to bind parameters to different kinds of Expression
Annotation | Meaning |
---|---|
To bind to an inbound message body | |
To bind to an inbound message header | |
To bind to the Map of the inbound message headers | |
To bind to the Map of the outbound message headers | |
To bind to a named property on the exchange | |
To bind to the property map on the exchange |
For example:
Code Block |
---|
public class Foo {
@MessageDriven(uri = "activemq:my.queue")
public void doSomething(@Header('JMSCorrelationID') String correlationID, @Body String body) {
// process the inbound message here
}
}
|
In the above you can now pass the Message.getJMSCorrelationID() as a parameter to the method (using the Type Converter to adapt the value to the type of the parameter).
Finally you don't need the @MessageDriven annotation; as the Camel route could describe which method to invoke.
e.g. a route could look like
Code Block |
---|
from("activemq:someQueue").
to("bean:myBean");
|
Here myBean would be looked up in the Registry (such as JNDI or the Spring ApplicationContext), then the body of the message would be used to try figure out what method to call.
If you want to be explicit you can use
Code Block |
---|
from("activemq:someQueue").
to("bean:myBean?methodName=doSomething");
|
And here we have a nifty example for you to show some great power in Camel. You can mix and match the annotations with the normal parameters, so we can have this example with annotations and the Exchange also:
Code Block |
---|
public void doSomething(@Header(name = "user") String user, @Body String body, Exchange exchange) {
exchange.getIn().setBody(body + "MyBean");
}
|
Using Expression Languages
You can also use any of the Languages supported in Camel to bind expressions to method parameters when using bean integration. For example you can use any of these annotations:
Annotation | Description |
---|---|
Inject a Bean expression | |
Inject a BeanShell expression | |
Inject a Constant expression | |
Inject an EL expression | |
Inject a Groovy expression | |
Inject a Header expression | |
Inject a JavaScript expression | |
Inject an OGNL expression | |
Inject a PHP expression | |
Inject a Python expression | |
Inject a Ruby expression | |
Inject an Simple expression | |
Inject an XPath expression | |
Inject an XQuery expression |
For example:
Code Block |
---|
public class Foo {
@MessageDriven(uri = "activemq:my.queue")
public void doSomething(@XPath("/foo/bar/text()") String correlationID, @Body String body) {
// process the inbound message here
}
}
|
Advanced example using @Bean
And an example of using the the @Bean binding annotation, where you can use a POJO where you can do whatever java code you like:
Code Block |
---|
public class Foo {
@MessageDriven(uri = "activemq:my.queue")
public void doSomething(@Bean("myCorrelationIdGenerator") String correlationID, @Body String body) {
// process the inbound message here
}
}
|
And then we can have a spring bean with the id myCorrelationIdGenerator where we can compute the id.
...
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;
}
}
The POJO MyIdGenerator has one public method that accepts two parameters. However we have also annotated this one with the @Header and @Body annotation to help Camel know what to bind here from the Message from the Exchange being processed.
Of course this could be simplified a lot if you for instance just have a simple id generator. But we wanted to demonstrate that you can use the Bean Binding annotations anywhere.
...
public class MySimpleIdGenerator {
public static int generate() {
// generate a unique id
return 123;
}
}
And finally we just need to remember to have our bean registered in the Spring Registry:
...