Transactions JMS和javaee事务

Transactions JMS和javaee事务,transactions,jms,Transactions,Jms,如果某个java代码(由JMS消息传递启动)在EJB容器中运行,并且该代码将另一条JMS消息放入同一队列,那么在启动该消息的代码完成并提交其事务之前,如何防止该消息被传递?基本上,我遇到了事务并发问题。我有一段代码(在EJB中)被JMS消息A启动。这段代码做了一些事情,然后它做了一个数据库插入(由于容器管理的EJB事务,在所有这些代码都执行完之前不会提交)。然后它放入一条消息(消息B),该消息具有刚刚插入队列的DB行的id。然后它在同一事务中做一些其他事情,这需要一点时间 好的,在这个ID为数据

如果某个java代码(由JMS消息传递启动)在EJB容器中运行,并且该代码将另一条JMS消息放入同一队列,那么在启动该消息的代码完成并提交其事务之前,如何防止该消息被传递?基本上,我遇到了事务并发问题。我有一段代码(在EJB中)被JMS消息A启动。这段代码做了一些事情,然后它做了一个数据库插入(由于容器管理的EJB事务,在所有这些代码都执行完之前不会提交)。然后它放入一条消息(消息B),该消息具有刚刚插入队列的DB行的id。然后它在同一事务中做一些其他事情,这需要一点时间

好的,在这个ID为数据库行的消息被放入队列后不久,它被传递并启动代码,该代码试图查询由消息A启动的代码插入的行。问题是,插入该行的代码仍在执行,其事务尚未提交。因此,所涉及的数据库行不在要查询的数据库中。结果是消息B启动的代码出错,因为它找不到所需的DB行

我如何防止这种情况?我对JavaEE容器中的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
//如何在java代码中声明工厂和队列:
@资源(mappedName=“java:/ConnectionFactory”)
连接工厂连接工厂;
@资源(mappedName=“java:jboss/exported/jms/queue/queue/queuea”)
队列a;
@资源(mappedName=“java:jboss/exported/jms/queue/queue”)
队列B;
//发送消息:
TextMessage=session.createTextMessage(“这里有一些消息”);
MessageProducer=session.createProducer(queueA);//队列B的samething
生产者。发送(消息);
//如何在WidlFly的standalone.conf中配置队列:
jms.queue.DLQ
5000
1.
10485760
1048576
页
10
//创建连接和会话:
connection=connectionFactory.createConnection();
session=connection.createSession(false,session.AUTO_ACKNOWLEDGE);//注意:应用程序在JavaEEWeb/EJB环境中运行,因此根据javadoc,“fasle”和auto_acknowledge参数都应该被忽略。我正在尝试将容器管理的事务用于所有事务

我必须更改常规连接工厂:

@Resource(mappedName = "java:/ConnectionFactory")
ConnectionFactory connectionFactory;
至XA连接工厂:

@Resource(mappedName = "java:/JmsXA")
XAConnectionFactory connectionFactory;

这使得事情一开始就停止了,因为我在@PostConstruct中对每个EJB只初始化了一次连接,并在@PreDestroy注释的方法中关闭了它。因此,除此之外,我还必须将连接和会话生成移到每个方法的开头,并在每个方法的结尾关闭它们。

我必须更改常规连接工厂:

@Resource(mappedName = "java:/ConnectionFactory")
ConnectionFactory connectionFactory;
至XA连接工厂:

@Resource(mappedName = "java:/JmsXA")
XAConnectionFactory connectionFactory;

这使得事情一开始就停止了,因为我在@PostConstruct中对每个EJB只初始化了一次连接,并在@PreDestroy注释的方法中关闭了它。因此,除此之外,我还必须将连接和会话生成移到每个方法的开头,并在每个方法的结尾关闭它们。

关于所有的消息,你确定你指的是JMX而不是JMS?对不起,JMS,你是对的。请参阅@home-该线程中描述的内容与我看到的内容不同。不仅消息不会回滚,而且消息会被传递,并且由该消息触发的作业会在原始事务完成之前开始执行。因此,无论原始事务是提交还是回滚,由消息触发的作业几乎总是失败,因为它试图在提交或回滚之前从数据库中抓取行。@生物:可能是您的配置错误,或者您发送了消息“未管理”?以及所有消息,你确定你指的是JMX而不是JMS?对不起,JMS,你是对的。请看@home——该线程中描述的不是我看到的。不仅消息不会回滚,而且消息会被传递,并且由该消息触发的作业会在原始事务完成之前开始执行。因此,无论原始事务是提交还是回滚,由消息触发的作业几乎总是失败,因为它试图在提交或回滚之前从数据库中获取行。@生物:可能是您的配置错误,或者您发送了消息“未管理”?您好,我只想澄清一下。为每条消息创建连接和会话是一项任务吗?因为我觉得新连接和会话生成的延迟正在解决您的竞争条件。我尝试了这个XA连接工厂,每个EJB初始化一次连接,但我仍然面临同样的问题,因为消费者在数据持久化到DB之前收到消息。为每条消息创建连接和会话是一项任务吗?因为我觉得新连接和会话生成的延迟正在解决您的竞争条件。我尝试了这个XA连接工厂,每个EJB初始化一次连接,但仍然面临着消费者在数据持久化到DB之前接收消息的问题。