【发布时间】:2017-01-30 08:40:32
【问题描述】:
如果您在 EJB 容器中运行了一些 java 代码(由 JMS 消息传递启动),并且该代码将另一条 JMS 消息放入同一个队列中,您如何防止该消息被传递,直到启动它的代码off 完成并且它的事务被提交?基本上,我遇到了事务并发问题。我有由 JMS 消息 A 启动的代码(在 EJB 中)。此代码执行一些操作,然后执行数据库插入(由于容器管理的 EJB 事务,在所有此代码执行完成之前不会提交)。然后它会放置一条消息(消息 B),该消息具有刚刚插入队列的 DB 行的 id。然后它在同一个事务中做一些其他的事情,这需要一点时间。
好吧,在这条带有数据库行 ID 的消息被放入队列后不久,它就会被传递并启动代码,该代码尝试查询由消息 A 启动的代码插入的行。麻烦的是也就是说,插入该行的代码仍在执行,其事务尚未提交。因此,有问题的数据库行不在要查询的数据库中。结果是由消息 B 启动的代码由于找不到所需的 DB 行而出错。
如何防止这种情况发生?我已经对 Java EE 容器中的 JMS 和事务进行了数小时的研究。我读过的这个教程是说你不能在同一个事务中接收消息并发送回复。那么容器不应该在所有事务完成之前不将消息提交到队列吗?
对不起,如果这个问题是乱码。我正在尽力解释。这里要粘贴的代码太多了。但是环境是 WildFly 8.1,可执行代码在无状态 EJB 中,JPA 用于数据库访问,消息在队列中,而不是主题中。我希望这是足够的信息。
// How factory and queues are declared in java code:
@Resource(mappedName = "java:/ConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(mappedName = "java:jboss/exported/jms/queue/quequeA")
Queue queueA;
@Resource(mappedName = "java:jboss/exported/jms/queue/quequeB")
Queue queueB;
//Sending message:
TextMessage message = session.createTextMessage("some message goes here");
MessageProducer producer = session.createProducer(queueA); // samething for queueB
producer.send(message);
// how queues are configured in WidlFly's standalone.conf :
<jms-queue name="quequeA">
<entry name="queue/quequeA"/>
<entry name="java:jboss/exported/jms/queue/quequeA"/> <!-- same thing for queueB -->
</jms-queue>
<address-setting match="jms.queue.quequeA">
<dead-letter-address>jms.queue.DLQ</dead-letter-address>
<redelivery-delay>5000</redelivery-delay>
<max-delivery-attempts>1</max-delivery-attempts>
<max-size-bytes>10485760</max-size-bytes>
<page-size-bytes>1048576</page-size-bytes>
<address-full-policy>PAGE</address-full-policy>
<message-counter-history-day-limit>10</message-counter-history-day-limit>
</address-setting>
// creating connection and session:
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // note: the application is running in the Java EE web/EJB environment, so both "fasle" and auto_acknowledge arguments shoudl be ignored according to the javadoc. I'm trying to use container-managed transactions for everything
【问题讨论】:
-
说到消息,你确定你指的是 JMX 而不是 JMS 吗?
-
对不起,JMS,你是对的。
-
@home - 该线程中描述的不是我所看到的。不仅消息没有回滚,而且消息被传递,并且由该消息触发的作业甚至在原始事务完成之前就开始执行。因此,无论原始事务是提交还是回滚,由消息触发的作业几乎总是失败,因为它试图在提交或回滚之前从数据库中获取行。
-
@Creature: 可能你的配置错误或者你发送的信息是“unmanaged”?
标签: transactions jms