"ARJUNA012140: Adding multiple last resources is disallowed" in JBoss EAP

Solution Verified - Updated

Environment

  • Red Hat JBoss Enterprise Application Platform (EAP)
    • 7
    • 6

Issue

The following WARN is being repeated in the server log:

WARN Adding multiple last resources is disallowed. Current resource is <resource>

Resolution

This error is due an attempt to enlist multiple one-phase (non-XA) resources within the same transaction.
In these situations we recommend one of the following approaches:

  1. Migrate legacy implementations to 2-phase commit (XA) equivalents. For DataSources deployed on JBoss Application Server, this is as simple as changing from a <datasource> to an <xa-datasource>. See Creating Datasources for more information.

  2. 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. Note that the invocation sequence from one @Stateful EJB to another @Stateful EJB will only work if you are in the same transaction.
    From the specification (EJB 3.1 4.6.4) there is a clear statement
    "A session bean instance can participate in at most a single transaction at a time."
    So @Stateful -> @Stateless is needed for this workaround.

In the cases where neither of these options are viable, JBossTS does permit unsafe enlistment of multiple one-phase resources within the same transaction. Note that when JBoss safeguards are disabled, JBossTS will issue warnings that unsafe transactional scenarios may result. Note that disabling the safeguard is not recommended for production systems as it opens a vulnerability throughout the JVM to inconsistent transaction outcomes. The impact of the setting will not be limited to read-only transactions so care should be taken (in application design/coding) to ensure that multiple non-XA resources are never used to perform write operations in any transaction in a system with the safeguard disabled if the outcome of the transaction needs to be consistent (i.e. if commit of writes to one resource but failure in commit of writes to another would be problematic).

Root Cause

As discussed in the Content from narayana.io is not included.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 resource, it is still possible to achieve an atomic (all or nothing) outcome across resources by utilizing the Last Resource Commit Optimization.

However, there may be situations where multiple one-phase 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.

Diagnostic Steps

The following warning appears in the log:

WARN Adding multiple last resources is disallowed.

A Byteman rule such as the below may be used to log (to standard out) an enlistment attempt message including detail of the resource and a complete stack trace showing the code path in which the attempt occurred.

RULE com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.enlistResource
CLASS com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple
METHOD enlistResource(javax.transaction.xa.XAResource)
IF true
DO traceStack("[BMAN] enlistResource(" + $1 + ")\n");
ENDRULE
Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.