【问题标题】:Correct usage of transactions in JMS and EJB正确使用 JMS 和 EJB 中的事务
【发布时间】:2015-04-06 13:56:20
【问题描述】:

我想知道如何在 EJB 容器中正确使用 JMS 事务。我找到了这段代码,它使用 JMS 在无状态 bean 中发送消息:

@Stateless
public class SendEventsBean {

  private static final Logger log = Logger.getLogger(SendEventsBean.class);

  @Resource(mappedName = "jms/MyConnectionFactory")
  private ConnectionFactory jmsConnectionFactory;

  @Resource(mappedName = "jms/myApp/MyQueue")
  private Queue queue;

  public void sendEvent() {
    Connection jmsConnection = null;
    try {
        connection = jmsConnectionFactory.createConnection();
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer producer = session.createProducer(queue);
        MyObj obj = new MyObj(1, "Foo");
        ObjectMessage myObjMsg = session.createObjectMessage(obj);
        producer.send(myObjMsg);
    } catch (JMSException jmxEx) {
        log.error("Couldn't send JMS message: ", jmsEx);
    }finally{
        if (jmsConnection != null) {
            try {
                jmsConnection.close();
            }catch(JMSException ex) {
               log.warn("Couldn't close JMSConnection: ", ex);
            }
        }
    }
  }

(来自When should I close a JMS connection that was created in a stateless session bean?

默认情况下,事务由容器管理,事务属性为“必需”。假设客户端直接调用 sendEvent(),事务从 sendEvent() 的开头开始,在 sendEvent() 的结尾结束(-> 在方法的最后执行提交)。 在方法的最后发生提交之前关闭连接(jmsConnection.close())是不是错了?

此外,我想知道在 createSession() 中设置事务属性和设置真/假是如何交互的。

如果容器已经启动了一个事务(使用容器管理的事务),那么设置 createSession(true,...) 是否有意义?这是否会为 JTA 事务中的 JMS 消息(而不是 DB)创建一个新事务?

我说对了 createSession(false, ...) 是不是因为容器启动了事务,所以消息仍然是事务性的?

【问题讨论】:

    标签: java transactions ejb jms jta


    【解决方案1】:

    在方法的最后发生提交之前关闭连接(jmsConnection.close())是不是错了?

    没有。关闭连接与 JTA 事务中的提交无关(这里就是这种情况,它是带有 CMT 的 ejb)。这只是适当和必要的清理。请注意,这些是容器返回的连接,底层事务管理器知道如何使用资源来提交事务。 JDBC 连接也是如此。

    如果容器已经启动了一个事务(使用容器管理的事务),那么设置 createSession(true,...) 是否有意义?

    对于 Weblogic,您绝对应该使用非事务性会话。但是对于 JMS 连接使用 XA 连接工厂很重要。

    http://docs.oracle.com/cd/E11035_01/wls100/jms/trans.html#wp1031645 http://www.informit.com/articles/article.aspx?p=26137&seqNum=8

    然而,与 JBOSS 相关的文章建议即使在 CMT ejb 中也将 createSession(true...) 设置为一种好习惯

    https://developer.jboss.org/thread/213629?tstart=0&_sscc=t http://www.coderanch.com/t/606786/EJB-JEE/java/EJB-CMT-sending-JMS-message

    无论设置如何,都必须强制使用基于 JCA/XA 的连接工厂。

    并且使用 createSession(false, ...) 我是对的,消息是 仍然是事务性的,因为由 容器?

    没有。如上所述,您必须使用 XA 连接工厂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-05
      • 2018-09-05
      • 2019-10-21
      • 2015-01-20
      • 2017-01-30
      • 2011-03-24
      • 2011-10-27
      • 1970-01-01
      相关资源
      最近更新 更多