I'm new to JTA and currently dive into its specification. I've also created some example projects to dive into this subject faster. I use IBM WebSphere 9 as a runtime.
I've created a simple project consists of EJB and MDB. The idea is that I sending some JMS to the queue, MDB then get this message, processing it and invoke EJB using local interface (both MDB and EJB are located at the same EAR). EJB in its turn will handle incoming object and write it to the Oracle database using JDBC via XA datasource.
MDB onMessage()
method has a TransactionAttributeType.NOT_SUPPORTED
defined, and as JTA says it should run outside the transaction context.
The process()
method of EJB, which is invoked from MDB hasn't any TransactionAttributes
defined, and as it comes from JTA it should have a default value which is TransactionAttributeType.REQUIRES_NEW
. Thus, if I'm not wrong, it starts a new global TX when being invoked, or am I wrong?
I've also created a simple DAO class, which gets a JDBC connection and runs statement to store the data received from EJB. It is located in a plain Java class at the package next to EJB.
The problem occurs when I try to run the project, to be more specific it occurs when I'm trying to get a connection from the datasource. Since I use the XA datasource, XAER_PROTO exception occurs:
[7/17/18 16:32:52:771 GMT+01:00] 000001b4 WSRdbXaResour E DSRA0304E: XAException occurred. XAException contents and details are:
The XA Error is: -6 The XA Error message is: Routine was invoked in an improper context. The Oracle > Error code is: 24776 The Oracle Error message is: Internal XA Error
After some time spent on investigating this issue I've figured out, that this problem is possibly related to this statements from JTA specification:
3.4.7 Local and Global Transactions
...
When using the same connection to perform both local and global transactions, the following rules apply:
• The local transaction must be committed (or rolled back) before starting a global transaction in the connection.
• The global transaction must be disassociated from the connection before any local transaction is started.
So my questions are:
Is an EJB method, annotated with a
TransactionAttributeType.REQUIRES_NEW
starts a global TX in terms of JTA?Am I right in my assumptions that retrieving of new JDBC connection from datasource initiates new local transaction in terms of JTA?
If all above is right than is it actually possible to use plain JDBC in EJB under a global TX? Or I should invoke JDBC-related methods only from non-transactional EJBs?
Should I consider the described above approach as a faulty one?
Should I use more abstract JTA interfaces to work with database instead of use of "plain" JDBC methods? If so then which way would be preferable?