Karaf教程第7部分- Camel JPA和JTA事务
来源:互联网 发布:log4j 只输出sql 编辑:程序博客网 时间:2024/05/22 02:04
Karaf教程第7部分- Camel JPA和JTA事务
Camel实践:轮询数据库表并发送XML内容到jms队列。路由使用JTA事务同步DB和JMS事务。错误案例演示了如何处理异常。
路由和概览
from("jpa://net.lr.tutorial.karaf.camel.jpa2jms.model.Person").id("jpa2jms")
.onException(Exception.class).maximumRedeliveries(3).backOffMultiplier(2).handled(true).to("file:error")
.transacted()
.marshal(df)
.bean(new ExceptionDecider())
.to("jms:person");
路由起始于jpa的终结点。它用JPA @Entity的全限定名配置。从这个实体camel中,我们知道要轮询的表格,如何读,如何删除行。Jpa终结点轮询表格,从它找到的每一行记录转换为Person实例。然后调用路由中的下一步,Person对象作为body。Jpa组件也需要分开设置,因为它需要EntityManagerFactory。
onException子句会让路由重试三次,每次用因子2增加补偿时间。如果仍然失败,那么消息就会被传递给error目录下的某个文件。
下一步中的transacted()标记路由为事务性的,它需要在camel上下文中设置 TransactedPolicy。然后它确保路由中的每一步都有机会参与到事务中。这样如果有错误发生,那么所有的动作都可以回滚。一旦都成功了,那么可以一起提交。
marshal(df)使用JAXB将Person对象转换为xml格式。它引用了数据格式对象df,它设置了JAXBContext。为了简化,这里设置不再说明。
ExceptionDecidet bean允许触发一个异常,如果Person的名字错误。这允许我们稍后测试错误处理。
最后一步("jms:person") 发送xml表示的person到jmx队列。它要求命名为jms的JmsComponent组件设置到camel上下文中。
from("jms:person").id("jms2log")
.transacted()
.convertBodyTo(String.class)
.to("log:personreceived");
第二条路由简单地监听person的队列,读取和显示队列的内容。在生产系统中,这一部分通常是在另一个模块中。
Person作为JPA实体JAXB类
Person类 是一个JPA实体,也是一个JAXB注解类。这允许我们在camel-jpa组件中使用它,也可以在marshall中使用它。记住,虽然可以这么干,但是这却是一个不良习惯,因为它将DB模型和JMS消息格式紧紧绑在一起。所以对于实际的集成,JPA和JAXB的Bean要分开,手动实现它们之间的转换时最好的。
@Entity
@XmlType
@XmlRootElement
public class Person {
private String name;
private String twitterName;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getTwitterName() { return twitterName; }
public void setTwitterName(String twitterName) { this.twitterName = twitterName; }
}
DataSource和ConnectionFactory设置
我们使用XADataSource作为Derby (参见 https://github.com/cschneider/Karaf-Tutorial/blob/master/db/datasource/datasource-derby.xml)的数据源。由于在Karaf中ActiveMQ提供的默认的ConnectionDactory不是XA,我们手动定义代理和ConnectionFactory (参见https://github.com/cschneider/Karaf-Tutorial/blob/master/cameljpa/jpa2jms/localhost-broker.xml)。与Karaf事务特性一起,这些提供了JTA事务的基础。
JPAComponent, JMSComponent和事务设置
这个例子的最重要部分就是在JTA事务中使用jpa和jms组件。这将允许在错误发生时进行双回滚。下面是我们使用的一个blueprint上下文。我们使用OSGi服务ConnectionFactory设置JMS组件。EntityManagerFactory 使用来自Aries JPA的jpa:unit配置设置JPAComponent。参见Apache Karaf教程第6部分–数据库访问,了解它的工作原理。Aries事务提供的TransactionManager被引用为OSGi服务,包装为spring 的PlattformTransactionManager,被注入到 JmsComponent和JPAComponent。
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.1.0"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://www.osgi.org/xmlns/blueprint-ext/v1.1.0 https://svn.apache.org/repos/asf/aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd
http://aries.apache.org/xmlns/jpa/v1.1.0 http://aries.apache.org/schemas/jpa/jpa_110.xsd
">
<reference id="connectionFactory" interface="javax.jms.ConnectionFactory" />
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="connectionFactory"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<argument ref="jmsConfig"/>
</bean>
<reference id="jtaTransactionManager" interface="javax.transaction.TransactionManager"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<argument ref="jtaTransactionManager"/>
</bean>
<bean id="jpa" class="org.apache.camel.component.jpa.JpaComponent">
<jpa:unit unitname="person2" property="entityManagerFactory"/>
<property name="transactionManager" ref="transactionManager"/>
</bean>
<bean id="jpa2jmsRoute" class="net.lr.tutorial.karaf.camel.jpa2jms.Jpa2JmsRoute"/>
<bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="transactionManager"/>
</bean>
<camelContext id="jpa2jms" xmlns="http://camel.apache.org/schema/blueprint">
<routeBuilder ref="jpa2jmsRoute" />
</camelContext>
</blueprint>
运行示例
你可以在github上找到完整的例子:JPA2JMS Example。跟着Readme.txt文件,安装必要的karaf特性、bundle、配置。
除了本示例工程,我们也安装了dbexamplejpa。这将允许我们使用那里定义的person:add命令添加到数据库表。
打开Karaf控制台,键入如下命令:
person:add "Christian Schneider" @schneider_chris
log:display
你应该能看到如下的日志:
2012-07-19 10:27:31,133 | INFO | Consumer[person] | personreceived ...
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<name>Christian Schneider</name>
<twitterName>@schneider_chris2</twitterName>
</person>
发生了什么?
我们使用命令person:add向person表中增加了一行记录。 我们的路由获得这条记录,读取并将其转换为Person对象。然后将它转换为xml,并发送到jms 队列。我们的第二条路由然后获得jms消息,并在日志中显示出来。
错误处理
这个例子中的路由包含一个小bean,它对Person对象的名字进行响应,如果名字是”error”,那么就会抛出异常。它也包含一个错误处理,所以一旦发生异常,xml会被转发到错误目录。
所以你可以在karaf中键入如下命令:
person:add error error
log:display
这次日志不应该显示xml了。取而代之的是,它应该出现在karaf安装目录下的错误目录中的文件中。
总结
在这个教程中,主要的事情就是学习如何使用camel-jpa组件写入,就像轮询数据库一样,如何设置和使用jta事务获取固定的错误处理。
- Karaf教程第7部分- Camel JPA和JTA事务
- Karaf教程第9部分基于注解的blueprint和JPA
- Karaf教程第5部分-在OSGi中运行 Apache Camel集成
- Servicemix,Karaf和Camel
- Servicemix,Karaf和Camel
- Karaf教程第6部分-数据库访问
- Karaf教程第8部分-分布式OSGi
- Karaf教程第3部分 使用OSGi Metatype服务和Felix Webconsole改善配置编辑
- (10) ejb学习: Jpa的JTA事务和RESOURCE_LOCAL事务
- Karaf教程第2部分 使用Configuration Admin服务
- Karaf教程第4部分 OSGi中的CXF服务
- Karaf教程第10部分 –声明式服务
- Karaf教程第2部分使用Configuration Admin服务
- Karaf教程第1部分 安装Karaf与第一个应用
- Karaf教程第1部分 安装Karaf与第一个应用
- JTA和JDBC事务
- JTA和JDBC事务
- JTA和JDBC事务
- 数据库的约束和对应关系
- java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()L
- 删除字符串中出现最少次数的字符
- 博一总结
- RecycleView的三种实现方式
- Karaf教程第7部分- Camel JPA和JTA事务
- 数据库的多表查询
- OJ---敌兵布阵
- maven中整合ueditor步骤与常见问题(一)
- lua脚本学习2
- 自定义View的多个情况
- 【缓存】缓存中常见的4种问题分析以及解决方案
- 用Springdata Jpa给指定字段排序
- Karaf教程第8部分-分布式OSGi