/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.hp.mwtests.ts.jta.cdi.transactional;
import javax.ejb.TransactionManagementType;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.transaction.NotSupportedException;
import javax.transaction.SystemException;
import javax.transaction.Transactional.TxType;
import javax.transaction.UserTransaction;
/**
* @author <a href="mailto:Tomasz%20Krakowiak%20%3ctomasz.krakowiak@efish.pl%3c">Tomasz Krakowiak
* <tomasz.krakowiak@efish.pl></a>
*/
@ApplicationScoped
public class TestTransactionalInvokerHelper {
@Inject
private UserTransaction userTransaction;
@Inject
private TestTransactionalInvokerBean bean;
public Runnable runWithTransactionManagement(TransactionManagementType transactionManagementType, boolean startTransaction, Runnable runnable) {
switch (transactionManagementType) {
case CONTAINER:
if (startTransaction) {
return new RunInTxRequired(runnable);
} else {
return new RunInTxSupports(runnable);
}
case BEAN:
if (startTransaction) {
return new RunInTxNotSupported(new RunInBmtTransaction(runnable));
} else {
return new RunInTxNotSupported(runnable);
}
default:
throw new RuntimeException("Unexpected transaction management type " + transactionManagementType);
}
}
public Runnable runInTxType(TxType txType, Runnable runnable) {
switch (txType) {
case REQUIRED:
return new RunInTxRequired(runnable);
case REQUIRES_NEW:
return new RunInTxRequiresNew(runnable);
case MANDATORY:
return new RunInTxMandatory(runnable);
case NOT_SUPPORTED:
return new RunInTxNotSupported(runnable);
case SUPPORTS:
return new RunInTxSupports(runnable);
case NEVER:
return new RunInTxNever(runnable);
default:
throw new RuntimeException("Unexpected tx type " + txType);
}
}
public Runnable runAndCheckUserTransactionAvailability(Runnable runnable, boolean expectedAvailable) {
return new RunAndCheckUserTransactionAvailability(runnable, expectedAvailable);
}
private class RunAndCheckUserTransactionAvailability implements Runnable {
Runnable runnable;
boolean expectedAvailable;
public RunAndCheckUserTransactionAvailability(Runnable runnable, boolean expectedAvailable) {
this.runnable = runnable;
this.expectedAvailable = expectedAvailable;
}
@Override
public void run() {
runnable.run();
try {
userTransaction.getStatus();
if (!expectedAvailable) {
throw new AssertionError("Expected user transaction to be not available.");
}
} catch (IllegalStateException e) {
if (expectedAvailable) {
throw new AssertionError("Expected user transaction to be available.");
}
} catch (SystemException e) {
throw new RuntimeException(e);
}
}
}
private class RunInTxRequired implements Runnable {
Runnable runnable;
public RunInTxRequired(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
bean.invokeInTxRequired(runnable);
}
}
private class RunInTxRequiresNew implements Runnable {
Runnable runnable;
public RunInTxRequiresNew(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
bean.invokeInTxRequiresNew(runnable);
}
}
private class RunInTxMandatory implements Runnable {
Runnable runnable;
public RunInTxMandatory(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
bean.invokeInTxMandatory(runnable);
}
}
private class RunInTxNotSupported implements Runnable {
Runnable runnable;
public RunInTxNotSupported(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
bean.invokeInTxNotSupported(runnable);
}
}
private class RunInTxSupports implements Runnable {
Runnable runnable;
public RunInTxSupports(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
bean.invokeInTxSupports(runnable);
}
}
private class RunInTxNever implements Runnable {
Runnable runnable;
public RunInTxNever(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
bean.invokeInTxNever(runnable);
}
}
private class RunInBmtTransaction implements Runnable {
Runnable runnable;
public RunInBmtTransaction(Runnable runnable) {
this.runnable = runnable;
}
@Override
public void run() {
try {
userTransaction.begin();
try {
runnable.run();
} catch (RuntimeException e) {
try {
userTransaction.rollback();
} catch (Throwable e1) {
e.addSuppressed(e1);
}
}
} catch (NotSupportedException | SystemException e) {
throw new RuntimeException(e);
}
}
}
}