GenericJMSRA svn rev 107 (with minor cleanup in 108) introduced FirstXAResourceProxy and the UseFirstXAForRedelivery ActivationSpec property to address the following conundrum:
In XA mode, asynchronously feeding an MDB, and with the RA's redelivery feature turned on (RedeliveryAttempts > 0), WebSphere MQ Classes for JMS expects the transaction to be started even before the JMS Session is run and the message accessed on the host. From the MDB container's point of view, however, the relevant transaction xid is the one that demarks the successful onMessage() call, even if one or more earlier transacted onMessage() calls for the same message had failed with exceptions.
Trying to run the JMS session without first starting the transaction in the WMQ XA resource results at once in a
com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2072' ('MQRC_SYNCPOINT_NOT_AVAILABLE').
and the MDB's onMessage() would never be called.
Setting UseFirstXAForRedelivery to "true" instructs the RA's DeliveryHelper to instantiate a FirstXAResourceProxy instead of an InboundXAResourceProxy. FirstXAResourceProxy starts the WMQ XA resource's transaction early enough and remembers the xid for a later commit or rollback.
Unfortunately, it seems this feature was never quite completed (and never documented in the User Guide). When UseFirstXAForRedelivery is "true", the MDB's onMessage() is properly called. Assume first that it failed with an exception. Then DeliveryHelper.deliver() proceeds to call
localXar.startDelayedXA();
(line 262 of DeliveryHelper.java trunk rev 240). Here, localXar is the instance of FirstXAResourceProxy, whose startDelayedXA() method amounts to throwing a java.lang.UnsupportedOperationException:
at com.sun.genericra.inbound.FirstXAResourceProxy.startDelayedXA(FirstXAResourceProxy.java:249)
at com.sun.genericra.inbound.async.DeliveryHelper.deliver(DeliveryHelper.java:262)
at com.sun.genericra.inbound.async.DeliveryHelper.deliver(DeliveryHelper.java:186)
at com.sun.genericra.inbound.async.EndpointConsumer.consumeMessage(EndpointConsumer.java:176)
at com.sun.genericra.inbound.async.MessageListener.onMessage(MessageListener.java:56)
at com.ibm.mq.jms.MQSession$FacadeMessageListener.onMessage(MQSession.java:147)
at com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2665)
at com.ibm.mq.jms.MQSession.run(MQSession.java:862)
at com.sun.genericra.inbound.async.WorkImpl.run(WorkImpl.java:53)
...
Moments later, the MDB container's attempt to commit the transaction it had started around the onMessage() call also fails, and the error code suggests that FirstXAResourceProxy was passing down a wrong xid of which the WMQ XA resource had not heard before:
JTS5067: Unexpected error occurred in commit
javax.transaction.xa.XAException: The method 'xa_commit' has failed with errorCode '-4'.
at com.ibm.mq.jmqi.JmqiXAResource.commit(JmqiXAResource.java:407)
at com.sun.genericra.inbound.FirstXAResourceProxy.commit(FirstXAResourceProxy.java:62)
at com.sun.jts.jtsxa.OTSResourceImpl.commit_one_phase(OTSResourceImpl.java:174)
...
Assume now that the onMessage() call had returned successfully. Next thing, DeliveryHelper.deliver() will also call
localXar.startDelayedXA();
(line 205). This will likewise incur the UnsupportedOperationException, and we end up in the catch block meant to handle exceptions thrown by the MDB's onMessage() even though this call had completed successfully. Thus we fail to break out of the redelivery loop in this case.
In short, as currently implemented, the call sequence in DeliveryHelper does not match the expectations of FirstXAResourceProxy.
Workaround: When using GenericJMSRA to adapt the WebSphere MQ JMS provider in XA mode, do not also turn on the RA's redelivery feature. (E.g., catch exceptions that look like retryable transient obstacles already inside the application's onMessage() method, and handle them as appropriate.)
Truly portable enterprise applications would not rely on this redelivery feature (or other GenericJMSRA peculiarities) anyway.
Environment
GlassFish 3.1.2.x or 2.1.1 Patch xx; WebSphere MQ Series 7.0.x.y
GenericJMSRA svn rev 107 (with minor cleanup in 108) introduced FirstXAResourceProxy and the UseFirstXAForRedelivery ActivationSpec property to address the following conundrum:
In XA mode, asynchronously feeding an MDB, and with the RA's redelivery feature turned on (RedeliveryAttempts > 0), WebSphere MQ Classes for JMS expects the transaction to be started even before the JMS Session is run and the message accessed on the host. From the MDB container's point of view, however, the relevant transaction xid is the one that demarks the successful onMessage() call, even if one or more earlier transacted onMessage() calls for the same message had failed with exceptions.
Trying to run the JMS session without first starting the transaction in the WMQ XA resource results at once in a com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2072' ('MQRC_SYNCPOINT_NOT_AVAILABLE'). and the MDB's onMessage() would never be called.
Setting UseFirstXAForRedelivery to "true" instructs the RA's DeliveryHelper to instantiate a FirstXAResourceProxy instead of an InboundXAResourceProxy. FirstXAResourceProxy starts the WMQ XA resource's transaction early enough and remembers the xid for a later commit or rollback.
Unfortunately, it seems this feature was never quite completed (and never documented in the User Guide). When UseFirstXAForRedelivery is "true", the MDB's onMessage() is properly called. Assume first that it failed with an exception. Then DeliveryHelper.deliver() proceeds to call localXar.startDelayedXA(); (line 262 of DeliveryHelper.java trunk rev 240). Here, localXar is the instance of FirstXAResourceProxy, whose startDelayedXA() method amounts to throwing a java.lang.UnsupportedOperationException: at com.sun.genericra.inbound.FirstXAResourceProxy.startDelayedXA(FirstXAResourceProxy.java:249) at com.sun.genericra.inbound.async.DeliveryHelper.deliver(DeliveryHelper.java:262) at com.sun.genericra.inbound.async.DeliveryHelper.deliver(DeliveryHelper.java:186) at com.sun.genericra.inbound.async.EndpointConsumer.consumeMessage(EndpointConsumer.java:176) at com.sun.genericra.inbound.async.MessageListener.onMessage(MessageListener.java:56) at com.ibm.mq.jms.MQSession$FacadeMessageListener.onMessage(MQSession.java:147) at com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2665) at com.ibm.mq.jms.MQSession.run(MQSession.java:862) at com.sun.genericra.inbound.async.WorkImpl.run(WorkImpl.java:53) ...
Moments later, the MDB container's attempt to commit the transaction it had started around the onMessage() call also fails, and the error code suggests that FirstXAResourceProxy was passing down a wrong xid of which the WMQ XA resource had not heard before:
JTS5067: Unexpected error occurred in commit javax.transaction.xa.XAException: The method 'xa_commit' has failed with errorCode '-4'. at com.ibm.mq.jmqi.JmqiXAResource.commit(JmqiXAResource.java:407) at com.sun.genericra.inbound.FirstXAResourceProxy.commit(FirstXAResourceProxy.java:62) at com.sun.jts.jtsxa.OTSResourceImpl.commit_one_phase(OTSResourceImpl.java:174) ...
Assume now that the onMessage() call had returned successfully. Next thing, DeliveryHelper.deliver() will also call localXar.startDelayedXA(); (line 205). This will likewise incur the UnsupportedOperationException, and we end up in the catch block meant to handle exceptions thrown by the MDB's onMessage() even though this call had completed successfully. Thus we fail to break out of the redelivery loop in this case.
In short, as currently implemented, the call sequence in DeliveryHelper does not match the expectations of FirstXAResourceProxy.
Workaround: When using GenericJMSRA to adapt the WebSphere MQ JMS provider in XA mode, do not also turn on the RA's redelivery feature. (E.g., catch exceptions that look like retryable transient obstacles already inside the application's onMessage() method, and handle them as appropriate.)
Truly portable enterprise applications would not rely on this redelivery feature (or other GenericJMSRA peculiarities) anyway.
Environment
GlassFish 3.1.2.x or 2.1.1 Patch xx; WebSphere MQ Series 7.0.x.y
Affected Versions
[2.1a, 2.1b, current]