Support for XA operations with ActiveMQ

Added by Shrikant 6 months ago

Hi Team

We don't see any libraries provided for distributed transaction processing with ActiveMQ in following link
https://www.endurox.org/dokuwiki/doku.php?id=endurox:v7.5.x:guides:ex_adminman#_configuring_distributed_transactions_support

Do you have any samples or guides on how to configure ActiveMQ as resource manager with Endurox as Transaction manager

Thanks


Replies (2)

RE: Support for XA operations with ActiveMQ - Added by Madars 6 months ago

Hi,

Currently we do not have any clients running XA with ActiveMQ.

What I see there is no official XA driver for C from ActiveMQ. And also AMQ support for XA is limited.

You may try to use our Java JDBC XA Driver, which basically requires following classes to be provided:

I guess one way would be that if you manually implement javax.sql.XADataSource interface in some class and also implement subsequent javax.sql.XAConnection, and then Enduro/X should be able to start to manage XA transactions via XAConnection.getXAResource() returned object. Thought there might be further issues with AMQ due to their limited support of XA operations, maybe in Enduro/X some change would be required to strip off some XA functionality.

So call chain would be following:

  • Enduro/X jdbc loader would instantiate your.custom.xa.AMQDataSource
  • Enduro/X loader would set properties to this object from the config (bellow)
  • When AtmiCtx.tpopen() is called by user code, Enduro/X internally would call: your.javax.sql.XAConnection xaConn = your.custom.xa.AMQDataSource.getXAConnection(); XADataSource xads = xaConn.getXAResource();
  • At this point Enduro/X AtmiCtx is associated with XA data source and transaction management is done by your business java code & tmsrv where both have completed above steps and xads is available for XA command dispatching.
  • At Java business code, XATMI client or server mode, you can call AtmiCtx.tpgetconn() which would return xaConn.getConnection() value which can be used for your Java code to work with AMQ.
  • When you do AtmiCtx.tpclose(), Enduro/X would internally call xaConn.close();
  • Any other cleanups of the connections (e.g. result of the tpgetconn()) prior tpclose() shall be done by the user, according the XAConnection implementation.

Sample config would look like:

[@global/DB1_JDBC]
NDRX_XA_RES_ID=1

# so Enduro/X would instantiate this class
NDRX_XA_OPEN_STR={"class":"your.custom.xa.AMQDataSource", 
        "set": {
                "setProperty":"SomeValue" 
                ,"setPassword":"SomePassword, etc.." 
                ,"setOtherProperty":"Someother value" 
                }
        }
NDRX_XA_CLOSE_STR=-
NDRX_XA_DRIVERLIB=libndrxxajdbc.so
NDRX_XA_RMLIB=libexjava.so
NDRX_XA_LAZY_INIT=1
# Set the limited work mode:
NDRX_XA_FLAGS=NOJOIN;NOSTARTXID;NOSUSPEND

PS,
You can check how we do this with Postgres in Java env here: https://github.com/endurox-dev/endurox-java/blob/master/tests/03_xapostgres/conf/java.ini and https://github.com/endurox-dev/endurox-java/blob/master/tests/03_xapostgres/src/jserver03/JServer03.java

For tmsrv, there will be embedded JVM instance started by the libndrxxajdbc.so/libexjava.so and settings would be used from ini file [@java] section, e.g.:


[@java]
opts stack=-Xss64m
#opts max mem=-XX:MaxDirectMemorySize=50m
opts max mem=-Xmx50m
opts osfreemin=-XX:MinHeapFreeRatio=5
opts osfreemax=-XX:MaxHeapFreeRatio=20
# tmsrv requires endurox jar in CP
#opts classpath=-classpath ${NDRX_APPHOME}/../../libsrc/enduroxjava.jar:${NDRX_APPHOME}/jdbcdrivers/pgjdbc.jar
# IBM Java...:
opts classpath=-Djava.class.path=${NDRX_APPHOME}/../../libsrc/enduroxjava.jar:${NDRX_APPHOME}/jdbcdrivers/pgjdbc.jar

So this means that ApacheMQ and your classes shall be put here in class path. And for your business Java binaries, it depends how you will start them. If link them by exjld, then this section would apply too to your xatmi java client or server.

PS2,

There is no guarantee that this all will work. It depends, on AMQ XA implementation. Does it allow different processes/sessions to perform commit or abort on transaction by given id?
For example MySQL does not allow that. For MySQL all XA activity must be done over the same connection. And if disconnect happens, everything is lost.
As Enduro/X architecture is different, it cannot share the same connection between user code and transaction manager, as having separate binaries (transaction manager is different pid). It might be a case that AMQ does not allow some activities (like prepare/abort/commit) to be done from other process than user code, like for MySQL.

But you never know, unless you try ;)

Thought if we run in this mode NDRX_XA_FLAGS=NOJOIN;NOSTARTXID;NOSUSPEND then at end of the user code Enduor/X would perform xa_prepare, and what I see from AMQ docs, that AMQ persists the state somewhere. Thus there might be a chance that the tmsrv executable would see the prepared transaction and would be able to commit or abort it.

RE: Support for XA operations with ActiveMQ - Added by Madars 6 months ago

I see that activemq-cpp module provides similar XA classes for C++.
In that case you can try to implement the xa switch over activemq-cpp API, basically needs to implement following function according to X/Open XA API:

struct xa_switch_t {
    char name[RMNAMESZ]; /* name of resource manager */
    long flags; /* options specific to the resource manager */
    long version; /* must be 0 */
    int (*xa_open_entry)(char *, int, long); /* xa_open function pointer*/
    int (*xa_close_entry)(char *, int, long); /* xa_close function pointer*/
    int (*xa_start_entry)(XID *, int, long); /* xa_start function pointer*/
    int (*xa_end_entry)(XID *, int, long); /* xa_end function pointer*/
    int (*xa_rollback_entry)(XID *, int, long);
                                          /* xa_rollback function pointer*/
    int (*xa_prepare_entry)(XID *, int, long);/* xa_prepare function pointer*/
    int (*xa_commit_entry)(XID *, int, long); /* xa_commit function pointer*/
    int (*xa_recover_entry)(XID *, long, int, long);
                                          /* xa_recover function pointer*/
    int (*xa_forget_entry)(XID *, int, long); /* xa_forget function pointer*/
    int (*xa_complete_entry)(int *, int *, int, long);
                                          /* xa_complete function pointer*/
};

Once that is done, there would be no need for java and you could operate completely from in C/C++ world.

But still question as for java stays, can tmsrv commit/abort outside the actual business process. If so then all could look promising.

Another option is that Mavimax could do investigation + implementation, but it could be done only as a workorder.

(1-2/2)