当前位置: 代码迷 >> J2EE >> 在JMS中使用JTA事宜,为什么会失效
  详细解决方案

在JMS中使用JTA事宜,为什么会失效

热度:95   发布时间:2016-04-17 23:05:12.0
在JMS中使用JTA事务,为什么会失效
        我写了一段JMS发送消息的代码,想使用JTA来管理事务,但是使用了JTA事务,还是没起作用。前面一条信息照常发送出去了,在创建session的时候也确实指定了是非事务性session,就是没弄懂为什么JTA失效了,还是直接看代码吧:

package cn.producer;

import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

public class ExceptionMessageSender {
/**
 * 本地获取Context
 * 需要添加wlclient.jar , webservices.jar , wljmsclient.jar
 * @return
 */
private Context getInitialContext(){
Context context = null;
final String INIT_FACTORY = "weblogic.jndi.WLInitialContextFactory";
final String SERVER_URL = "t3://localhost:7001";
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, INIT_FACTORY);
props.put(Context.PROVIDER_URL, SERVER_URL);
try {
context = new InitialContext(props);
} catch (NamingException e) {
e.printStackTrace();
}
return context;
}

public void sendMessage() throws NamingException, JMSException, NotSupportedException, SystemException, SecurityExceptionIllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException{
//定义默认的weblogic的JNDI
final String CONNECTION_FACTORY_JNDI = "weblogic.jms.ConnectionFactory";
//获取Context
Context context = getInitialContext();
//获取连接工厂
ConnectionFactory cf = (ConnectionFactory) context.lookup(CONNECTION_FACTORY_JNDI);
//获取连接
Connection conn = cf.createConnection();
//监听JMS服务器异常情况(只有当JMS服务器运行时发生的异常才会触发异常监听器)
conn.setExceptionListener(new ExceptionListener(){
@Override
public void onException(JMSException e) {
System.out.println("JMS服务器发生异常,异常信息如下:");
e.printStackTrace();
}
});
//获取JTA事务
UserTransaction tx = (UserTransaction) context.lookup("javax.transaction.UserTransaction");
tx.begin();
//获取会话,如果设置为事务性会话,那么JTA不起作用
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
//获取消息目的
Destination dest = (Destination) context.lookup("MessageQueue");
//通过会话获取消息生产者
MessageProducer sender = session.createProducer(dest);
//通过会话创建一个空格JMS消息
TextMessage msg = session.createTextMessage();
msg.setText("你好,我是路人甲!");
//通过消息生产者发送消息
sender.send(msg);
try{
int num = 4/0;//-----------这里会抛出异常,引发JTA全局事务回滚
msg.setText(num+":number");
sender.send(msg);
tx.commit();
}catch(Exception e){
tx.rollback();
}finally{
//关闭资源
session.close();
conn.close();
}

}
}


package cn.consumer;

import java.util.Properties;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

public class ExceptionConsumer {
/**
 * 本地获取Context
 * 需要添加wlclient.jar , webservices.jar , wljmsclient.jar
 * @return
 */
private Context getInitialContext(){
Context context = null;
final String INIT_FACTORY = "weblogic.jndi.WLInitialContextFactory";
final String SERVER_URL = "t3://localhost:7001";
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, INIT_FACTORY);
props.put(Context.PROVIDER_URL, SERVER_URL);
try {
context = new InitialContext(props);
} catch (NamingException e) {
e.printStackTrace();
}
return context;
}

public void receiveMessage() throws NamingException, JMSException, NotSupportedException, SystemException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException{
//定义默认的weblogic连接工程的JNDI
final String CONNECTION_FACTORY_JNDI = "weblogic.jms.ConnectionFactory";
//获取Context
Context context = getInitialContext();
//通过JNDI获取连接工厂
ConnectionFactory cf = (ConnectionFactory) context.lookup(CONNECTION_FACTORY_JNDI);
//通过连接工厂获取连接
Connection conn = cf.createConnection();
//开始JMS传输
conn.start();
//设置异常监听器,监听JMS服务器上的异常
conn.setExceptionListener(new ExceptionListener(){
public void onException(JMSException e){
System.out.println("JMS服务器发生异常,异常信息如下:");
e.printStackTrace();
}
});
//打开全局事务
UserTransaction tx = (UserTransaction) context.lookup("javax.transaction.UserTransaction");
tx.begin();
//通过连接获取会话,使用全局事务了,就不应该设置为事务性会话,否则全局事务会失效,使用的事务还是事务性会话的事务
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
//获取消息目的(消息队列)
Destination dest = (Destination) context.lookup("MessageQueue");
//创建消息消费者
MessageConsumer receiver = session.createConsumer(dest);
//消息消费者同步接收消息
TextMessage msg = (TextMessage) receiver.receiveNoWait();
System.out.println(msg);
if(msg != null){
System.out.println("同步接收到信息:"+msg.getText());
}
//确认事务
tx.commit();
//关闭资源
session.close();
conn.close();
}
}


package cn.test;

import javax.jms.JMSException;
import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;

import cn.producer.ExceptionMessageSender;

public class TestExceptionProducer {
public static void main(String[] args) {
ExceptionMessageSender ems = new ExceptionMessageSender();
try {
ems.sendMessage();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
} catch (NotSupportedException e) {
e.printStackTrace();
} catch (SystemException e) {
e.printStackTrace();
} catch (RollbackException e) {
e.printStackTrace();
} catch (HeuristicMixedException e) {
e.printStackTrace();
} catch (HeuristicRollbackException e) {
e.printStackTrace();
}
}
}

package cn.test;

import javax.jms.JMSException;
import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;

import cn.consumer.ExceptionConsumer;

public class TestExceptionConsumer {
public static void main(String[] args) {
ExceptionConsumer ec = new ExceptionConsumer();
try {
ec.receiveMessage();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
} catch (JMSException e) {
e.printStackTrace();
} catch (NotSupportedException e) {
e.printStackTrace();
} catch (SystemException e) {
e.printStackTrace();
} catch (RollbackException e) {
e.printStackTrace();
} catch (HeuristicMixedException e) {
e.printStackTrace();
} catch (HeuristicRollbackException e) {
e.printStackTrace();
}
}
}

          代码全都在上面了,真的没弄懂才来这里文的,求大神指点。
------解决思路----------------------
在ExceptionMessageSender 类里面,把weblogic.jms.ConnectionFactory换成weblogic.jms.XAConnectionFactory,因为XAConnectionFactory是默认开启JTA事务支持的,ConnectionFactory默认没有开启。具体详情可以参考这里:

http://docs.oracle.com/cd/E13222_01/wls/docs81/ConsoleHelp/jms_config.html
  相关解决方案