本文简单介绍一下在Spring通过声明管理一个有数据库和ActiveMQ参入的全局事务,事务管理器的实现为Atomikos.全局事务的步骤为
1,更新数据库操作.
2访问ActiveMQ资源.
3,提交在数据库A中的操作.
4,提交在ActiveMQ中的操作.
上面的所有步骤应该保证要么全部成功,要么全部回滚.下面是实现的步骤:
1,配置Spring文件:
1,更新数据库操作.
2访问ActiveMQ资源.
3,提交在数据库A中的操作.
4,提交在ActiveMQ中的操作.
上面的所有步骤应该保证要么全部成功,要么全部回滚.下面是实现的步骤:
1,配置Spring文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="db1jdbcDAO" class="com.test.spring.tx.xaatomikos.DB1jdbcDAO">
<property name="dataSource" ref="xaDataSource" />
</bean>
<bean id="buzSingleService" class="com.test.spring.tx.xaatomikos.BuzSingleService">
<property name="db1jdbcDAO" ref="db1jdbcDAO" />
<property name="jmsAccessor" ref="jmsAccessor" />
</bean>
<bean id="xaDataSource"
class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName"><value>XADBMS</value></property>
<property name="xaDataSourceClassName">
<value>oracle.jdbc.xa.client.OracleXADataSource</value>
</property>
<property name="xaProperties">
<props>
<prop key="user">xxx</prop>
<prop key="password">xxx</prop>
<prop key="URL">jdbc:oracle:thin:@147.151.240.xx:1521:orcl</prop>
</props>
</property>
<property name="poolSize" value="1"/>
</bean>
<bean id="jmsAccessor" class="com.test.spring.tx.xaatomikos.JmsAccessor">
<property name="jmsTemplate" ref="jmsTemplate"/>
<property name="destination" ref="destination"/>
</bean>
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="example.yorker" />
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="atomikosConnectionFactory"/>
<property name="defaultDestination" ref="destination"/>
<property name="receiveTimeout" value="10000"/>
<property name="sessionTransacted" value="true" />
</bean>
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory" >
<property name="brokerURL" value="tcp://localhost:61616"/>
</bean>
<bean id="atomikosConnectionFactory"
class="com.atomikos.jms.AtomikosConnectionFactoryBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="amq1"/>
<property name="xaConnectionFactory" ref="amqConnectionFactory"/>
</bean>
<!--
<bean id="jmsConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="atomikosConnectionFactory" />
</bean>
-->
<bean id="atomikosTransactionManager"
class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" >
<property name="forceShutdown" value="false"/>
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" >
<property name="transactionTimeout" value="300"/>
</bean>
<!--
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp"
init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<props>
<prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory
</prop>
</props>
</constructor-arg>
</bean>
-->
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager"/>
<property name="userTransaction" ref="atomikosUserTransaction"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="jtaTransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* com.test.spring.tx.xaatomikos.*Service*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
</beans>
2,Java操作数据库的代码Dao
public class DB1jdbcDAO {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public void testInsert(int id, String val) {
this.jdbcTemplate.update("insert into A (ID, VAL) values (?, ?)", id, val);
}
3,Java操作MQ的代码JMS accessor:
public class JmsAccessor {
JmsTemplate jmsTemplate;
Destination destination;
public void send() {
MessageCreator messageCreator = new MessageCreator() {
public Message createMessage(Session session) {
System.out.println("confactory type:" + jmsTemplate.getConnectionFactory().getClass().getName());
TextMessage message = null;
try {
message = session.createTextMessage("Hello message");
} catch (JMSException e) {
e.printStackTrace();
}
return message;
}
};
jmsTemplate.send(this.destination, messageCreator);
}
public void receive() {
System.out.println("confactory type:" + jmsTemplate.getConnectionFactory().getClass().getName());
TextMessage message = (TextMessage) jmsTemplate.receive();
try {
System.out.println("Message received:" + message.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
public JmsTemplate getJmsTemplate() {
return jmsTemplate;
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public Destination getDestination() {
return destination;
}
public void setDestination(Destination destination) {
this.destination = destination;
}
}
4客户访问端代码:
public class BuzSingleService {
DB1jdbcDAO db1jdbcDAO;
JmsAccessor jmsAccessor;
public void testTX1() throws Exception {
db1jdbcDAO.testInsert(0, "db1jdbcDAO val0");
jmsAccessor.send();
........下面是main 方法中的代码
ApplicationContext ctx = new ClassPathXmlApplicationContext("config/xaAtomikosAppcontext.xml");
BuzSingleService serv =(BuzSingleService)ctx.getBean("buzSingleService");
try {
serv.testTX1();
*一个问题是,在数据库操作和MQ操作都完成后,程序没有退出,不断有如下log输出:
DEBUG 2012-02-16 15:35:37,182 [InactivityMonitor WriteCheck] org.apache.activemq.transport.InactivityMonitor: 10000 ms elapsed since last write check.
DEBUG 2012-02-16 15:35:39,511 [InactivityMonitor WriteCheck] org.apache.activemq.transport.InactivityMonitor: 10000 ms elapsed since last write check.
DEBUG 2012-02-16 15:35:47,183 [InactivityMonitor WriteCheck] org.apache.activemq.transport.InactivityMonitor: 10001 ms elapsed since last write check.