import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.impl.DefaultCamelContext;
public final class CamelJmsToBean {
private CamelJmsToBean () {
}
public static void main(String args[]) throws Exception {
CamelContext context = new DefaultCamelContext();
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
context.addComponent("test-jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
context.addRoutes(new RouteBuilder() {
public void configure() {
//from("test-jms:queue:test.queue").to("file://test");
from("test-jms:queue:test.queue").bean(new ProcMsg(), "show");
}
});
ProducerTemplate template = context.createProducerTemplate();
context.start();
for (int i = 0; i < 3; i++) {
template.sendBody("test-jms:queue:test.queue", "这个消息: " + (i+1));
}
Thread.sleep(100);
context.stop();
}
}
import java.util.Date;
public class ProcMsg {
public ProcMsg(){
super();
}
public void show(Object v){
System.out.println(new Date()+":"+v);
}
}
//用配置方式设置 消息的处理步骤
<route id="move-airMonitor">
<from uri="timer:airMonitor?period=10m;delay=10000"/>
<transform>
<method ref="lastBean" method="getLast('airall')"/>
</transform>
<log message="last query airMonitor: ${body}"/>
<to uri="bean:sqlAirFrom?method=select('select_airall','airall')"/>
<!-- <log message="airMonitor read data: ${body}"/> -->
<to uri="bean:airBean?method=moveDataBatch(${body},'exists_airall','insert_airall','update_airall','type_airall')"/>
<to uri="bean:lastBean?method=updateLastA(${body},'airall')"/>
<log message="AirMonitor update result: ${body}"/>
</route>
// Exchange 数据的 使用
Bean Binding
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, in the following order of importance:
- if the message contains the header CamelBeanMethodName then that method is invoked, converting the body to the type of the method's argument.
- From Camel 2.8 onwards you can qualify parameter types to select exactly which method to use among overloads with the same name (see below for more details).
- From Camel 2.9 onwards you can specify parameter values directly in the method option (see below for more details).
- you can explicitly specify the method name in the DSL or when using POJO Consuming or POJO Producing
- if the bean has a method marked with the
@Handler
annotation, then that method is selected - if the bean can be converted to a Processor using the Type Converter mechanism, then this is used to process the message. The ActiveMQ component uses this mechanism to allow any JMS MessageListener to be invoked directly by Camel without having to write any integration glue code. You can use the same mechanism to integrate Camel into any other messaging/remoting frameworks.
- if the body of the message can be converted to a BeanInvocation (the default payload used by the ProxyHelper) component - then that is used to invoke the method and pass its arguments
- otherwise the type of the body is used to find a matching method; 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.
- if the bean class is private (or package-private), interface methods will be preferred (from Camel 2.9 onwards) since Camel can't invoke class methods on such beans
In cases where Camel cannot choose a method to invoke, an AmbiguousMethodCallException
is thrown.
By default the return value is set on the outbound message body.
Parameter binding
When a method has been chosen for invocation, Camel will bind to the parameters of the method.
The following Camel-specific types are automatically bound:
org.apache.camel.Exchange
org.apache.camel.Message
org.apache.camel.CamelContext
org.apache.camel.TypeConverter
org.apache.camel.spi.Registry
java.lang.Exception
So, if you declare any of these types, they will be provided by Camel. Note that Exception
will bind to the caught exception of the Exchange - so it's often usable if you employ a Pojo to handle, e.g., an onException
route.
What is most interesting is that Camel will also try to bind the body of the Exchange to the first parameter of the method signature (albeit not of any of the types above). So if, for instance, we declare a parameter as String body
, then Camel will bind the IN body to this type. Camel will also automatically convert to the type declared in the method signature.
Let's review some examples:
Below is a simple method with a body binding. Camel will bind the IN body to the body
parameter and convert it to a String
.
public String doSomething(String body)
|
In the following sample we got one of the automatically-bound types as well - for instance, a Registry
that we can use to lookup beans.
public String doSomething(String body, Registry registry)
|
We can use Exchange as well:
public String doSomething(String body, Exchange exchange)
|
You can also have multiple types:
public String doSomething(String body, Exchange exchange, TypeConverter converter)
|
And imagine you use a Pojo to handle a given custom exception InvalidOrderException
- we can then bind that as well:
public String badOrder(String body, InvalidOrderException invalid)
|
Notice that we can bind to it even if we use a sub type of java.lang.Exception
as Camel still knows it's an exception and can bind the cause (if any exists).
So what about headers and other stuff? Well now it gets a bit tricky - so we can use annotations to help us, or specify the binding in the method name option.
See the following sections for more detail.
Binding Annotations
You can use the Parameter Binding Annotations to customize how parameter values are created from the Message
Examples
For example, a Bean such as:
public class Bar {
public String doSomething(String body) {
// process the in body and return whatever you want
return "Bye World";
}
|
Or the Exchange example. Notice that the return type must be void when there is only a single parameter of the type org.apache.camel.Exchange
:
public class Bar {
public void doSomething(Exchange exchange) {
// process the exchange
exchange.getIn().setBody("Bye World");
}
|
@Handler
You can mark a method in your bean with the @Handler annotation to indicate that this method should be used for Bean Binding.
This has an advantage as you need not specify a method name in the Camel route, and therefore do not run into problems after renaming the method in an IDE that can't find all its references.
public class Bar {
@Handler
public String doSomething(String body) {
// process the in body and return whatever you want
return "Bye World";
}
|
Parameter binding using method option
Available as of Camel 2.9
Camel uses the following rules to determine if it's a parameter value in the method option
- The value is either
true
orfalse
which denotes a boolean value - The value is a numeric value such as
123
or7
- The value is a String enclosed with either single or double quotes
- The value is null which denotes a
null
value - It can be evaluated using the Simple language, which means you can use, e.g., body, header.foo and other Simple tokens. Notice the tokens must be enclosed with ${ }.
Any other value is consider to be a type declaration instead - see the next section about specifying types for overloaded methods.
When invoking a Bean you can instruct Camel to invoke a specific method by providing the method name:
.bean(OrderService. class , "doSomething")
|
Here we tell Camel to invoke the doSomething method - Camel handles the parameters' binding. Now suppose the method has 2 parameters, and the 2nd parameter is a boolean where we want to pass in a true value:
public void doSomething(String payload, boolean highPriority) {
...
} |
This is now possible in Camel 2.9 onwards:
.bean(OrderService. class , "doSomething(*, true )")
|
In the example above, we defined the first parameter using the wild card symbol *, which tells Camel to bind this parameter to any type, and let Camel figure this out. The 2nd parameter has a fixed value of true
. Instead of the wildcard symbol we can instruct Camel to use the message body as shown:
.bean(OrderService. class , "doSomething(${body}, true )")
|
The syntax of the parameters is using the Simple expression language so we have to use ${ } placeholders in the body to refer to the message body.
If you want to pass in a null
value, then you can explicit define this in the method option as shown below:
.to("bean:orderService?method=doSomething( null , true )")
|
Specifying null
as a parameter value instructs Camel to force passing a null
value.
Besides the message body, you can pass in the message headers as a java.util.Map
:
.bean(OrderService. class , "doSomethingWithHeaders(${body}, ${headers})")
|
You can also pass in other fixed values besides booleans. For example, you can pass in a String and an integer:
.bean(MyBean. class , "echo(&# 39 ;World&# 39 ;, 5 )")
|
In the example above, we invoke the echo method with two parameters. The first has the content 'World' (without quotes), and the 2nd has the value of 5.
Camel will automatically convert these values to the parameters' types.
Having the power of the Simple language allows us to bind to message headers and other values such as:
.bean(OrderService. class , "doSomething(${body}, ${header.high})")
|
You can also use the OGNL support of the Simple expression language. Now suppose the message body is an object which has a method named asXml
. To invoke the asXml
method we can do as follows:
.bean(OrderService. class , "doSomething(${body.asXml}, ${header.high})")
|
Instead of using .bean
as shown in the examples above, you may want to use .to
instead as shown:
.to("bean:orderService?method=doSomething(${body.asXml}, ${header.high})") |
Using type qualifiers to select among overloaded methods
Available as of Camel 2.8
If you have a Bean with overloaded methods, you can now specify parameter types in the method name so Camel can match the method you intend to use.
Given the following bean:
public static final class MyBean {
public String hello(String name) {
return "Hello " + name;
}
public String hello(String name, @Header ("country") String country) {
return "Hello " + name + " you are from " + country;
}
public String times(String name, @Header ("times") int times) {
StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < times; i++) {
sb.append(name);
}
return sb.toString();
}
public String times( byte [] data, @Header ("times") int times) {
String s = new String(data);
StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < times; i++) {
sb.append(s);
if (i < times - 1 ) {
sb.append(",");
}
}
return sb.toString();
}
public String times(String name, int times, char separator) {
StringBuilder sb = new StringBuilder();
for ( int i = 0 ; i < times; i++) {
sb.append(name);
if (i < times - 1 ) {
sb.append(separator);
}
}
return sb.toString();
}
} |
Then the MyBean
has 2 overloaded methods with the names hello
and times
. So if we want to use the method which has 2 parameters we can do as follows in the Camel route:
from("direct:start") .bean(MyBean. class , "hello(String,String)")
.to("mock:result");
|
We can also use a *
as wildcard so we can just say we want to execute the method with 2 parameters we do
from("direct:start") .bean(MyBean. class , "hello(*,*)")
.to("mock:result");
|
By default Camel will match the type name using the simple name, e.g. any leading package name will be disregarded. However if you want to match using the FQN, then specify the FQN type and Camel will leverage that. So if you have a com.foo.MyOrder
and you want to match against the FQN, and not the simple name "MyOrder", then follow this example:
.bean(OrderService. class , "doSomething(com.foo.MyOrder)")
|
Camel currently only supports either specifying parameter binding or type per parameter in the method name option. You cannot specify both at the same time, such as
doSomething(com.foo.MyOrder ${body}, boolean ${header.high})
|
This may change in the future.
相关推荐
这些模式是解决企业系统集成中常见问题的最佳实践,而Apache Camel则将这些模式实现为可重用的组件,使得开发者可以通过简单的DSL(Domain Specific Language)来应用这些模式。 1. **DSL与路由定义**:Apache ...
- 第二章深入探讨了 Camel 中的路由机制,并展示了如何使用 Camel 进行数据转换。 - **使用 Beans** - 第四章介绍了如何在 Camel 应用程序中使用 Java Beans 来处理业务逻辑。 - **错误处理** - 第五章专门...
本篇文章将详细介绍如何使用CXF和camel-cxf调用Web服务,以及这两个工具的核心功能和使用场景。 Apache CXF是一个全面的服务开发框架,它支持多种Web服务标准,如SOAP、WS-*协议栈、RESTful服务等。CXF提供了丰富的...
- **简单表达式语言 (Simple, the expression language)**:介绍了Camel中使用的简单表达式语言及其应用。 - **表达式和谓词 (Expressions and predicates)**:详细讨论了如何在Camel中使用表达式和谓词。 - **生产...
Apache Camel 是一个流行的开源集成框架,它允许开发者以声明式的方式定义路由和转换数据,使得在不同的软件组件之间实现通信变得更加简单。JDBC(Java Database Connectivity)是Java平台中的一个标准API,用于与...
Camel 关注在简易集成。 1.1.1 Camel 是什么 Camel 框架的核心是一个路由引擎,它允许你定义自己的路由规则,决定接受哪些消息,做出决定如何处理,发送这些消息给其他目标。Camel 用这种集成语言允许你定义复杂的...
Camel与Spring框架有很好的集成,可以在Spring应用中方便地使用Camel。这使得Camel能够利用Spring的依赖注入、配置管理和事务管理等功能。 10. **Camel开发指南** 提供的“Apache Camel 开发指南”将详细介绍如何...
#### 五、使用bean的简单方式 **简单方式** 主要是指通过Spring XML配置来实现bean的自动调用,这种方式减少了手动编码的需求,使得消息处理流程更加简洁明了。 示例配置如下: ```xml <camelContext id="camel" ...
- 快速入门:引导读者通过一个简单的例子快速开始使用Camel。 - 架构介绍:深入解释Camel的内部架构和工作原理。 - 企业集成模式:详细介绍了Camel支持的各种企业集成模式。 - CookBook:提供了一系列可复用的集成...
- **消息处理与转换:** 讲解了如何使用 Camel 进行复杂的数据处理和转换操作,包括使用 XSLT 转换 XML 数据、解析 JSON 数据等。 - **异步与并发处理:** 探讨了 Camel 如何支持异步和并发消息处理,这对于提高...
- **高可测试性**:由于其声明式的路由定义,单元测试和模拟变得更加简单。 - **社区支持**:拥有广泛的社区支持和丰富的文档资源。 5. **实战应用示例** - 文件迁移:从一个 FTP 服务器下载文件,处理后上传到...
它使用基于DSL(领域特定语言)的路由语句,称为Camel Route,使得集成工作变得简单直观。该框架的核心是其强大的路由引擎,可以处理各种数据流,并将它们转换和路由到不同的目的地。 二、路由表达式 Camel 的路由...
Apache Camel 是一个强大的开源集成框架,它允许开发者通过声明式的方式定义路由和转换数据流,使得构建企业级应用变得更加简单。Timer 组件是 Apache Camel 中的一个重要部分,它提供了定时触发事件的功能,类似于 ...
- **入门示例**:通过一个简单的示例来演示如何快速启动并运行Camel应用程序。 - **第2章:使用Camel进行路由** - **基本概念**:讲解路由的基本原理以及Camel中用于构建路由的组件。 - **高级路由策略**:深入...
本书是Apache Camel使用者和开发者的必备指南,详细介绍了Camel的各种特性和使用方法,帮助读者掌握企业级集成系统的构建技巧。 #### 二、Apache Camel概述 Apache Camel是一个强大的开源企业服务总线(ESB)和...
Apache Camel 提供了丰富的组件和模式,使得数据同步变得简单高效。以下将详细介绍Apache Camel在数据同步中的核心知识点: 1. **组件**:Apache Camel 包含了大量的预构建组件,如JDBC(Java Database ...
第三部分则提供了在真实环境中使用Camel的经验分享。 #### 二、章节概览 - **第一章:Meet Camel**(遇见Camel) - **介绍Camel** - Camel是一款基于Java的企业级集成框架。 - 它提供了一种简洁且强大的API来...
Apache Camel 是一个强大的开源企业集成库,它提供了一种声明式的方式来定义路由和转换数据,使得构建复杂的分布式系统变得更加简单。Camel 使用一种名为“DSL”(Domain Specific Language)的语法规则,允许开发者...
6. **Camel的DSL(领域特定语言)**:Camel 使用基于Java、XML或Groovy的DSL来编写路由规则,使得配置代码更加直观和简洁。例如,一个简单的HTTP调用可以这样表示: ```java from("direct:start") .to(...