Enlisting multiple 1-phase aware participants in the same transaction
In some cases it may be necessary to enlist participants that aren't two-phase commit aware into a two-phase commit transaction. If there is only a single resource then there is no need for two-phase commit. However, what if there are multiple resources in the transaction? In this case, the Last Resource Commit optimization (LRCO) comes into play. It is possible for a single resource that is one-phase aware (i.e., can only commit or roll back, with no prepare), to be enlisted in a transaction with two-phase commit aware resources. The coordinator treats the one-phase aware resource slightly differently, in that it executes the prepare phase on all other resource first, and if it then intends to commit the transaction it passes control to the one-phase aware resource. If it commits, then the coordinator logs the decision to commit and attempts to commit the other resources as well.
In order to use the LRCO, your XAResource implementation must extend the com.arjuna.ats.jta.resources.LastResourceCommitOptimisation marker interface (it provides no methods). When enlisting the resource via Transaction.enlistResource, JBossTS will ensure that only a single instance of this type of participant is used within each transaction. Your resource will be driven last in the commit protocol: no invocation of prepare will occur.
Note: By default an attempt to enlist more than one instance of a LastResourceCommitOptimisation class will fail and false will be returned from Transaction.enlistResource. This behaviour can be overridden by setting the propertycom.arjuna.ats.jta.allowMultipleLastResources in conf/jbossjta-properties.xml (JBoss-4.x) or conf/jbossts-properies.xml (JBoss 5) to "true" (not "YES"). This property goes in the JTA properties section (name="arjuna"). However, before doing so you should read the Section on enlisting multiple one-phase aware resources.
WARNING: setting com.arjuna.ats.jta.allowMultipleLastResources to true when using 1pc resources will increase your chances of getting a heuristic outcome.(outcome in which some resources are committed and others aren't).
In order to utilize the LRCO in a distributed environment, it is necessary to disable interposition support. It is still possible to use implicit context propagation.
Enlisting multiple one-phase aware resources
As discussed in the Transaction Core documentation, in order to guarantee consistency (atomicity) of outcome between multiple participants (resources) within the same transaction, the two-phase commit protocol is used with a durable transaction log. In the case of possessing a single one-phase aware resource, it is still possible to achieve an atomic (all or nothing) outcome across resources by utilizing the Last Resource Commit Optimization, as explained earlier.
However, there may be situations where multiple one-phase aware resources are enlisted within the same transaction. For example, a legacy database running within the same transaction as a legacy JMS implementation. In these situations it is not possible to achieve atomicity of transaction outcome across multiple resources because none of them enter the prepare (waiting for final outcome) state: they commit or rollback immediately when instructed by the transaction coordinator, without knowledge of other resource states and without any way of undoing should subsequent resources make a different choice. This can result in data corruption or heuristic outcomes.
If you see this warning, then you have run into this problem:
WARN Adding multiple last resources is disallowed. Current resource is <resource>
In these situations we recommend one of the following approaches:
-
Wrap the resources in compensating transactions. See the Web Services transactions guides for further details.
-
Migrate the legacy implementations to two-phase aware equivalents. For DataSources deployed on JBoss Application Server, this is as simple as changing from <local-tx-datasource> to <xa-datasource>. See ConfigDataSources for more information.
-
Refactor the code to use separate transactions. If you simply need to read from one DataSource and insert processed results into another, you may not want or need 2-phase commit (and thus the above optimization). In an EJB3 session bean, this can be accomplished by simply delegating the read to a separate method and annotating it with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW). This causes the calling method's Transaction to suspend, wait for the read to complete, and resume.
In the cases where neither of these options are viable, JBossTS does support the enlistment of multiple one-phase aware resources within the same transaction. In order to do this, see the section on the Last Resource Commit Optimization (JBossTS Programmers Guide 4.2.3, Chapter 3, Extended XAResource control).
Caution: Even when this support is enabled, JBossTS will issue warnings when it detects that the option has been enabled (You have chosen to enable multiple last resources in the transaction manager. This is transactionally unsafe and should not be relied upon.) and when multiple one-phase resources are enlisted within the transaction (This is transactionally unsafe and should not be relied on.).