JMS的事务控制
JMS控制消息发送的事务有2种途径,一个是利用Connection接口建立事务性会话,另一个就是利用JTA标准接口控制事务了。
Session事务性会话
public void sendMessage() {
try { String Connection_Factory = "ConnectionFactory";
Context context = getInitialContext();
ConnectionFactory connectionFactory = (ConnectionFactory) context .lookup(Connection_Factory);
Destination dest = (Destination) context.lookup("jbossJMSTopic");
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
MessageProducer sender = session.createProducer(dest);
sender.setDeliveryMode(DeliveryMode.PERSISTENT); // sender.setTimeToLive(2000);
sender.setPriority(9);
TextMessage textMessage = session.createTextMessage();
textMessage.setStringProperty("ConType", "txt");
textMessage.setText("hello 速速");
sender.send(textMessage);
System.out.println("停顿5秒钟");
// 等待50秒 Thread.sleep(5000);
System.out.println("停顿5秒钟完毕");
textMessage.setText("welcome to JMS");
sender.send(textMessage);
//此处抛出运行时异常 int a = 1/0;
session.commit(); session.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); }
} |
此代码会抛出异常
java.lang.ArithmeticException: / by zero |
所以消费者是无法接收到此消息的,因为事务还没有提交呢,就抛出了异常,还有一点就是在建立session的时候如果是建立的事务性会话,必须手工代码让会话提交事务session.commit();消息才能送达到目的地!
JTA管理JMS消息事务
如果需要让JMS、数据库、EJB操作等参与到事务当中,则应该考虑JTA事务。因为Session事务性会话总会打开一个新的事务,在Session中未commit之前,全部都在一个Session事务中,而数据库操作、EJB操作等等不能参与、共享此会话性事务中。所以此时应该用JTA来包装此事务。
来看JTA控制的消息生产者的一个Servlet代码
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
UserTransaction userTransaction = null; java.sql.Connection connectionSQL = null; DataSource dataSource = null;
Statement statement = null;
Context context; try { context = new InitialContext();
dataSource = (DataSource) context.lookup("java:/jbossdemo");
String Connection_Factory = "ConnectionFactory";
ConnectionFactory connectionFactory = (ConnectionFactory) context .lookup(Connection_Factory);
Destination dest = (Destination) context.lookup("jbossJMSTopic");
// 获得JTA相关用户接口 userTransaction = (UserTransaction) context .lookup("UserTransaction");
// 开始事务 userTransaction.begin();
javax.jms.Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer sender = session.createProducer(dest);
sender.setDeliveryMode(DeliveryMode.PERSISTENT); // sender.setTimeToLive(2000);
sender.setPriority(9);
TextMessage textMessage = session.createTextMessage();
textMessage.setStringProperty("ConType", "txt");
textMessage.setText("hello 第一个消息");
sender.send(textMessage);
System.out.println("停顿5秒钟");
// 等待50秒 Thread.sleep(5000);
System.out.println("停顿5秒钟完毕");
textMessage.setText("welcome to JMS");
sender.send(textMessage);
// 执行插入数据业务 connectionSQL = dataSource.getConnection();
statement = connectionSQL.createStatement();
String insert1 = "insert into person values(13,'欧阳上智')";
String insert2 = "insert into person values(14,'欧阳尚智')";
statement.executeUpdate(insert1);
statement.executeUpdate(insert2);
int a = 1 / 0;
// 提交JTA事务 userTransaction.commit();
session.close();
connection.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); try { userTransaction.rollback(); } catch (IllegalStateException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (SecurityException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (SystemException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }finally{ try { statement.close(); connectionSQL.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }
} |
这里要说明的就是此处的上下文因为是在一个J2EE环境下调用的,所以改