简体   繁体   English

在JMS和EJB中正确使用事务

[英]Correct usage of transactions in JMS and EJB

I wonder how to use JMS transactions correctly inside an EJB container. 我想知道如何在EJB容器内正确使用JMS事务。 I found this code, that sends messages using JMS in a stateless bean: 我找到了以下代码,该代码在无状态Bean中使用JMS发送消息:

@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);
            }
        }
    }
  }

(from When should I close a JMS connection that was created in a stateless session bean? ) (来自何时应关闭在无状态会话Bean中创建的JMS连接?

At default the transactions are container managed with transaction attribute 'required'. 默认情况下,事务是使用事务属性“必需”进行容器管理的。 Suppose a client calls sendEvent() directly, so that the transaction starts at the beginning and ends at the end of sendEvent() (-> a commit is executed at the very end of the method). 假设客户端直接调用sendEvent(),则事务从sendEvent()的开始处开始,并在sendEvent()的结尾处结束(->在该方法的末尾执行一次提交)。 Isn't it wrong to close the connection (jmsConnection.close()) BEFORE the commit occurs at the very end of the method? 在方法的最后进行提交之前关闭连接(jmsConnection.close())是否不是错误的?

Furthermore I'm wondering how setting the transactional attribute and setting true/false at createSession() interacts. 此外,我想知道如何在createSession()上设置事务属性和设置true / false。

Does it make sense setting createSession(true,...) if there is already a transaction started by the container (using container managed transactions)? 如果容器已经存在一个事务(使用容器管理的事务),那么设置createSession(true,...)是否有意义? Does this create a new transaction just for JMS messages (and not for DB also) inside the JTA transaction? 这是否仅在JTA事务内为JMS消息创建了一个新事务(对于DB也没有)?

And with createSession(false, ...) am I right, that messages are nevertheless transactional because of the transaction started by the container? 通过createSession(false,...)我是对的,但是由于容器启动了事务,因此消息是事务性的吗?

Isn't it wrong to close the connection (jmsConnection.close()) BEFORE the commit occurs at the very end of the method? 在方法的最后进行提交之前关闭连接(jmsConnection.close())是否不是错误的?

No. Closing connections has got nothing to do with commit within a JTA transaction (which is the case here, it being an ejb with CMT). 否。关闭连接与JTA事务中的提交无关(在这种情况下,这是带有CMT的ejb)。 It is just proper and essential cleanup. 这只是适当且必要的清理。 Note these are connections returned by the container and the underlying transaction manager knows how to work with the resource to commit the transactions. 请注意,这些是容器返回的连接,基础事务管理器知道如何使用资源来提交事务。 Same goes for JDBC connections as well. JDBC连接也是如此。

Does it make sense setting createSession(true,...) if there is already a transaction started by the container (using container managed transactions)? 如果容器已经存在一个事务(使用容器管理的事务),那么设置createSession(true,...)是否有意义?

For Weblogic, you should definitely be using non transacted sessions. 对于Weblogic,您绝对应该使用非事务处理会话。 But what is important to use XA connection factories for your JMS connections. 但是,对于XMS连接使用XA连接工厂很重要。

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

However articles related to JBOSS suggests setting the createSession(true...) as a good practise even within a CMT ejb 但是,与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 https://developer.jboss.org/thread/213629?tstart=0&_sscc=t http://www.coderanch.com/t/606786/EJB-JEE/java/EJB-CMT-sending-JMS-message

Irrespective of the setting, JCA/XA based connection factories have to be used compulsorily. 无论设置如何,都必须强制使用基于JCA / XA的连接工厂。

And with createSession(false, ...) am I right, that messages are nevertheless transactional because of the transaction started by the container? 通过createSession(false,...)我是对的,但是由于容器启动了事务,因此消息是事务性的吗?

No. As mentioned above, you will have to use XA connection factories. 否。如上所述,您将必须使用XA连接工厂。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM