jmsactivemq-classicxa

Wildfly 10 jms send Message to queue as part of XA transaction


I have recently had to support a colleague in verifying why some system tests are not passing in wildfly, system tests that pass consistently on weblogic and glass fish.

After analysing the log, it became clear the reason is related to a JMS message sent by a backed thread getting committed to a queue too soon, when the expectation was the message would be committed when the entry point Container Managed Transaction of an MDB commits. So the message is going out before the MDB that sends it is done running.

In weblogic, to achieve the expected behaviour, you need to make sure that when you take the connection factory given by the container , which is XA configured, you set the connection.createseesion with transacted = true and acknowledgement = session transacted.

In a process similar to the one depicted in this URL http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as Except in the snippet above auto acknowledge is set and the first parameter is set to false.

In wildly when our weblogic and glass fish configuration is used, nothing is committed and the system behaves as if the JMS message sent were to be rolled back.

If configuration as in the example above were to be used, instead what would happen is that the JMS message is immediately and the consumer MDB immediately launches being trigerred before the producer transaction actually ends, causing the system test to fail.

According to the official JMS configuration, by using a connection-pooled factory with the transaction=XA attribute, the container should immediately bind the commit of the transaction to the lifecycle of the parent transaction.

See official documentation bellow in particular in respect to the Java:/JmsXa connection factory.

https://docs.jboss.org/author/display/WFLY10/Messaging+configuration

My colleague was initially using a non pooled connection factory, but the injection info reference has since then been fixed. I have tried all possible combinations of parameters in the shed message, but my outcome is sitll: Either sent too soon or never sent.

To conclude all the other resources are XA. Namely the oracle db is using the XA driver.

Can anyone confirm if in wildly the send JMS message only when parent transaction commits is working and if so how the session is being configured?

I will check if perhaps my colleague has not made a mistake in terms of the configuration of the connection factory used by the Men's themselves to consume messages out of the queue.but if that one is also XA... Then it is a big problem.


Solution

  • So the issues is fixed.

    The commit of the JMS message to the queue at the end of the transaction works perfectly.

    The issue was two fold: (a) First spot of code I was looking at address the issue was not correct. Someone had decided to write his own send telegram to queue API elsewhere, and was not using the central API for sneding telegrams, so any modification I to the injection connection factory was actually not taking effect. The stale connection factories were still being used.

    (b) Once the correct API was spotted it was easy to make the mechanism work by using the widlfy XA pooled connection factory mentioned in the post above. The one thing that was tweaked was the connection.CreationSession api.

    The API in JEE 7 has been enlarged and it is now better documented than in jEE 6. To send a JMS message in a container as part of an XA transaction one should do: connection.createSession() without any parameters.

    This can easily be seen in the connection javadoc:

    https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html

    QUOTE 1:

    This method has been superseded by the method createSession(int sessionMode) which specifies the same information using a single argument, and by the method createSession() which is for use in a Java EE JTA transaction. Applications should consider using those methods instead of this one.

    QUOTE 2:

    In a Java EE web or EJB container, when there is an active JTA transaction in progress:

    Both arguments transacted and acknowledgeMode are ignored. The session will participate in the JTA transaction and will be committed or rolled back when that transaction is committed or rolled back, not by calling the session's commit or rollback methods. Since both arguments are ignored, developers are recommended to use createSession(), which has no arguments, instead of this method.

    Which means, the code snippet in: http://www.mastertheboss.com/jboss-server/jboss-jms/sending-jms-messages-over-xa-with-wildfly-jboss-as

    Is not appropriate. What one should be doing is creating the session without any parameter and leting the container handle the rest. Which it does just fine.