Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WFLY-2651 If there is a transaction active when the setup action first r... #5677

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -27,6 +27,7 @@
import java.util.Set;

import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;

import org.jboss.as.server.deployment.SetupAction;
Expand All @@ -45,7 +46,7 @@
*/
public class TransactionRollbackSetupAction implements SetupAction, Service<TransactionRollbackSetupAction> {

private static final ThreadLocal<Integer> depth = new ThreadLocal<Integer>();
private static final ThreadLocal<Holder> depth = new ThreadLocal<Holder>();

private final InjectedValue<TransactionManager> transactionManager = new InjectedValue<TransactionManager>();

Expand All @@ -62,7 +63,7 @@ public void setup(final Map<String, Object> properties) {

@Override
public void teardown(final Map<String, Object> properties) {
if (changeDepth(-1) == 0) {
if (changeDepth(-1)) {
checkTransactionStatus();
}
}
Expand Down Expand Up @@ -96,42 +97,70 @@ public InjectedValue<TransactionManager> getTransactionManager() {
return transactionManager;
}

private int changeDepth(int increment) {
Integer now = depth.get();
int newVal = now == null ? increment : now.intValue() + increment;
if (newVal == 0) {
private boolean changeDepth(int increment) {
Holder holder = depth.get();
if (holder == null) {
//if there is a transaction active initially we just track the depth
//and don't actually close it, because we don't 'own' the transaction
//this can happen when running async listeners outside the context of a request
holder = new Holder();
try {
final TransactionManager tm = transactionManager.getOptionalValue();
if (tm != null) {
holder.actuallyCleanUp = !isTransactionActive(tm, tm.getStatus());
}
depth.set(holder);
} catch (Exception e) {
TransactionLogger.ROOT_LOGGER.unableToGetTransactionStatus(e);
}
}

holder.depth += increment;
if (holder.depth == 0) {
depth.set(null);
} else {
depth.set(Integer.valueOf(newVal));
return holder.actuallyCleanUp;
}
return newVal;
return false;
}

private void checkTransactionStatus() {
try {
final TransactionManager tm = transactionManager.getOptionalValue();
if(tm == null) {
if (tm == null) {
return;
}
final int status = tm.getStatus();

switch (status) {
case Status.STATUS_ACTIVE:
case Status.STATUS_COMMITTING:
case Status.STATUS_MARKED_ROLLBACK:
case Status.STATUS_PREPARING:
case Status.STATUS_ROLLING_BACK:
case Status.STATUS_ROLLEDBACK:
case Status.STATUS_PREPARED:
try {
TransactionLogger.ROOT_LOGGER.transactionStillOpen(status);
tm.rollback();
} catch (Exception ex) {
TransactionLogger.ROOT_LOGGER.unableToRollBack(ex);
}
final boolean active = isTransactionActive(tm, status);
if (active) {
try {
TransactionLogger.ROOT_LOGGER.transactionStillOpen(status);
tm.rollback();
} catch (Exception ex) {
TransactionLogger.ROOT_LOGGER.unableToRollBack(ex);
}
}
} catch (Exception e) {
TransactionLogger.ROOT_LOGGER.unableToGetTransactionStatus(e);
}
}

private boolean isTransactionActive(TransactionManager tm, int status) throws SystemException {

switch (status) {
case Status.STATUS_ACTIVE:
case Status.STATUS_COMMITTING:
case Status.STATUS_MARKED_ROLLBACK:
case Status.STATUS_PREPARING:
case Status.STATUS_ROLLING_BACK:
case Status.STATUS_ROLLEDBACK:
case Status.STATUS_PREPARED:
return true;
}
return false;
}

private static class Holder {
int depth;
boolean actuallyCleanUp = true;
}
}