文档章节

Spring整合JMS(四)——事务管理

JTA的阿呆
 JTA的阿呆
发布于 2016/09/18 19:54
字数 1106
阅读 37
收藏 1

Spring提供了一个JmsTransactionManager用于对JMS ConnectionFactory做事务管理。这将允许JMS应用利用Spring的事务管理特性。JmsTransactionManager在执行本地资源事务管理时将从指定的ConnectionFactory绑定一个ConnectionFactory/Session这样的配对到线程中。JmsTemplate会自动检测这样的事务资源,并对它们进行相应操作。

在Java EE环境中,ConnectionFactory会池化Connection和Session,这样这些资源将会在整个事务中被有效地重复利用。在一个独立的环境中,使用Spring的SingleConnectionFactory时所有的事务将公用一个Connection,但是每个事务将保留自己独立的Session。

JmsTemplate可以利用JtaTransactionManager和能够进行分布式的 JMS ConnectionFactory处理分布式事务。

       在Spring整合JMS的应用中,如果我们要进行本地的事务管理的话非常简单,只需要在定义对应的消息监听容器时指定其sessionTransacted属性为true,如:

  1. <bean id="jmsContainer"  
  2.     class="org.springframework.jms.listener.DefaultMessageListenerContainer">  
  3.     <property name="connectionFactory" ref="connectionFactory" />  
  4.     <property name="destination" ref="queueDestination" />  
  5.     <property name="messageListener" ref="consumerMessageListener" />  
  6.     <property name="sessionTransacted" value="true"/>  
  7. </bean>  

 

  1. 该属性值默认为false,这样JMS在进行消息监听的时候就会进行事务控制,当在接收消息时监听器执行失败时JMS就会对接收到的消息进行回滚,对于SessionAwareMessageListener在接收到消息后发送一个返回消息时也处于同一事务下,但是对于其他操作如数据库访问等将不属于该事务控制。
  2. 这里我们可以来做一个这样的测试:我们如上配置监听在queueDestination的消息监听容器的sessionTransacted属性为true,然后把我们前面提到的消息监听器ConsumerMessageListener改成这样:

  3. public class ConsumerMessageListener implements MessageListener {  
  4.    
  5.     public void onMessage(Message message) {  
  6.             //这里我们知道生产者发送的就是一个纯文本消息,所以这里可以直接进行强制转换,或者直接把onMessage方法的参数改成Message的子类TextMessage  
  7.             TextMessage textMsg = (TextMessage) message;  
  8.             System.out.println("接收到一个纯文本消息。");  
  9.             try {  
  10.                 System.out.println("消息内容是:" + textMsg.getText());  
  11.                 if (1 == 1) {  
  12.                     throw new RuntimeException("Error");  
  13.                 }  
  14.             } catch (JMSException e) {  
  15.                 e.printStackTrace();  
  16.             }  
  17.     }  
  18.    

我们可以看到在上述代码中我们的ConsumerMessageListener在进行消息接收的时候抛出了一个RuntimeException,根据我们上面说的,因为我们已经在对应的监听容器上定义了其sessionTransacted属性为true,所以当这里抛出异常的时候JMS将对接收到的消息进行回滚,即下次进行消息接收的时候该消息仍然能够被接收到。为了验证这一点,我们先执行一遍测试代码,往queueDestination发送一个文本消息,这个时候ConsumerMessageListener在进行接收的时候将会抛出一个RuntimeException,已经接收到的纯文本消息将进行回滚;接着我们去掉上面代码中抛出异常的语句,即ConsumerMessageListener能够正常的进行消息接收,这个时候我们再运行一次测试代码,往ConsumerMessageListener监听的queueDestination发送一条消息。如果之前在接手时抛出了异常的那条消息已经回滚了的话,那么这个时候将能够接收到两条消息,控制台将输出接收到的两条消息的内容。

 如果想接收消息和数据库访问处于同一事务中,那么我们就可以配置一个外部的事务管理同时配置一个支持外部事务管理的消息监听容器(如DefaultMessageListenerContainer)。要配置这样一个参与分布式事务管理的消息监听容器,我们可以配置一个JtaTransactionManager,当然底层的JMS ConnectionFactory需要能够支持分布式事务管理,并正确地注册我们的JtaTransactionManager。这样消息监听器进行消息接收和对应的数据库访问就会处于同一数据库控制下,当消息接收失败或数据库访问失败都会进行事务回滚操作。

配置如下:

  1. <bean id="jmsContainer"  
  2.     class="org.springframework.jms.listener.DefaultMessageListenerContainer">  
  3.     <property name="connectionFactory" ref="connectionFactory" />  
  4.     <property name="destination" ref="queueDestination" />  
  5.     <property name="messageListener" ref="consumerMessageListener" />  
  6.     <property name="transactionManager" ref="jtaTransactionManager"/>  
  7. </bean>  
  8.   
  9. <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>  

当给消息监听容器指定了transactionManager时,消息监听容器将忽略sessionTransacted的值。

JMS进行消息接收抛出异常时我们的数据库也会回滚

 

原文:http://elim.iteye.com/blog/1983532

 

 

 

 

© 著作权归作者所有

JTA的阿呆
粉丝 1
博文 19
码字总数 19304
作品 0
闸北
后端工程师
私信 提问
加载中

评论(1)

Mr_SWang
Mr_SWang
26

暂无文章

非递归实现后序遍历二叉树

问题描述 从键盘接受输入先序序列,以二叉链表作为存储结构,建立二叉树(以先序来建立)并对其进行后序遍历,然后将遍历结果打印输出。要求采用非递归方法实现。 解题思路 Push根结点到第一...

niithub
10分钟前
0
0
IDEA 自动删除类中无用的import包

1.手动快捷键 Ctrl + Alt + O 2.配置自动清理 Ctrl + Alt + S 打开设置 然后,进行如下操作:

时刻在奔跑
12分钟前
0
0
cwRsync提示password file must be owned by root when running as root的解决方法

cwRsync提示password file must be owned by root when running as root的解决方法 更新时间:2015年08月30日 23:05:52 投稿:mdxy-dxy 我要评论 今天在配置服务器的时候,用了rsync4.10版本...

rootliu
17分钟前
0
0
Java 交换两个参数

目前有一个小需求: 定义一个函数,交换两个值。于是,有人就写了这样一个函数。 public class exchange_01 { public static void main(String[] args) { // TODO Auto-gen...

hellation_
26分钟前
0
0
ExoPlayer简单使用

一、介绍 ExoPlayer是google开源的应用级媒体播放器项目,该开源项目包含ExoPlayer库和演示demo,github地址:https://github.com/google/ExoPlayer。 二、概述 ExoPlayer库的核心是ExoPlay...

零点B5
35分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部