简体   繁体   中英

JMS and Java EE transactions

If you have a some java code (kicked off by JMS message delivery) running inside an EJB container and that code puts another JMS message into the same queue, how do you prevent that message from being delivered until the code that kicked it off is complete and its transaction is committed? Basically, I'm experiencing a transaction concurrency issue. I've got code (in EJB) that gets kicked off by JMS message A. This code does some stuff, then it does a database insert (which wont commit until all of this code is done executing because of container managed EJB transactions). Then it puts a message (message B) that has the id of the DB row that was just inserted into the queue. Then it does some other stuff in the same transaction that takes a little while.

Well, shortly after this message with the ID of the database row is put into the queue, it gets delivered and kicks off code that tries to query that row that got inserted by code that got kicked off by message A. The trouble is, that code that inserted that row is still executing and its transaction hasn't committed yet. So the database row in question isn't in the DB to be queried. The result is that code that is kicked off by message B errors out because it can't find the DB row it needs.

How do I prevent this? I've done hours of research on JMS and transactions in Java EE container. This one tutorial I've read is saying that you can't receive a message and send a reply in the same transaction. So shouldn't the container not commit the message to the queue until all of the transaction is complete?

Sorry if this question is garbled. I'm trying to explain the best I can. There's way too much code to be pasted in here. But the environment is WildFly 8.1, the executable code is inside stateless EJBs, JPA is used for database access, and the messages are in queues, not topics. I hope that's enough info.

// 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

I had to change regular connection factory:

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

To XA connection factory:

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

This made things stop working at first, because I was initializing the connection only once per EJB in an @PostConstruct and closing it in @PreDestroy annotated methods. So in addition to that, I had to move connection and session generation to the beginning of each method and close them at the end of each method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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