de.thksystems.container.spring.BaseService Maven / Gradle / Ivy
Show all versions of mugwort Show documentation
/*
* tksCommons / mugwort
*
* Author : Thomas Kuhlmann (ThK-Systems, http://oss.thk-systems.de) License : LGPL (https://www.gnu.org/licenses/lgpl.html)
*/
package de.thksystems.container.spring;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import de.thksystems.exception.ServiceRuntimeException;
import de.thksystems.util.function.CheckedRunnable;
import de.thksystems.util.function.CheckedSupplier;
public abstract class BaseService {
private final static Logger LOG = LoggerFactory.getLogger(BaseService.class);
@Autowired
private PlatformTransactionManager transactionManager;
/**
* Throws given exception as {@link ServiceRuntimeException}.
*/
protected T throwAsServiceRuntimeExceptionAndLog(Throwable cause, String message) {
String msg = message + ": " + cause.toString();
LOG.error(msg, cause);
throw new ServiceRuntimeException(msg, cause);
}
/**
* Start transaction manually.
*
* Use it with caution!
* Do not mix annotation based transaction handling and programmatically one!
*
* @param readonly
* For readonly transactions.
* @param propagation
* For special propagations (like REQUIRES_NEW)
*/
protected TransactionStatus startTransaction(boolean readonly, Propagation propagation) {
LOG.trace("Starting new transaction");
DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
transactionDefinition.setReadOnly(readonly);
transactionDefinition.setPropagationBehavior(propagation.value());
return transactionManager.getTransaction(transactionDefinition);
}
/**
* Start transaction manually.
*
* Use it with caution!
* Do not mix annotation based transaction handling and programmatically one!
*
* @param readonly
* For readonly transactions.
*/
protected TransactionStatus startTransaction(boolean readonly) {
return startTransaction(readonly, Propagation.REQUIRED);
}
/**
* Start transaction manually.
*
* Use it with caution!
* Do not mix annotation based transaction handling and programmatically one!
*
* @param propagation
* For special propagations (like REQUIRES_NEW)
*/
protected TransactionStatus startTransaction(Propagation propagation) {
return startTransaction(false, propagation);
}
/**
* Start transaction manually.
*
* Use it with caution!
* Do not mix annotation based transaction handling and programmatically one!
*/
protected TransactionStatus startTransaction() {
return startTransaction(false, Propagation.REQUIRED);
}
/**
* Start transacation manually, if required.
*
* @see #startTransaction()
*/
protected TransactionStatus startTransactionIfRequired(TransactionStatus transactionStatus) {
if (transactionStatus == null || transactionStatus.isCompleted()) {
return startTransaction();
}
return transactionStatus;
}
/**
* Commit transaction manually.
*
* If the transaction is set rollbackOnly, a rollback is done.
*
* @see #startTransaction() for notes and warning.
*/
protected void commitTransaction(TransactionStatus transactionStatus) {
if (transactionStatus != null && !transactionStatus.isCompleted()) {
if (transactionStatus.isRollbackOnly()) {
LOG.trace("Transaction is set rollback only.");
rollbackTransaction(transactionStatus);
} else {
LOG.trace("Transaction commited");
transactionManager.commit(transactionStatus);
}
}
}
/**
* Rollback transaction manually.
*
* @see #startTransaction() for notes and warning.
*/
protected void rollbackTransaction(TransactionStatus transactionStatus) {
if (transactionStatus != null && !transactionStatus.isCompleted()) {
LOG.trace("Transaction rollbacked.");
transactionManager.rollback(transactionStatus);
}
}
/**
* Runs in transaction.
*/
protected void runInTransaction(CheckedRunnable runnable) throws X {
runInTransaction(Propagation.REQUIRED, runnable);
}
/**
* Runs in transaction.
*/
protected void runInTransaction(Propagation propagation, CheckedRunnable runnable) throws X {
TransactionStatus transactionStatus = null;
try {
transactionStatus = startTransaction(propagation);
runnable.run();
commitTransaction(transactionStatus);
} catch (Throwable t) { // NOSONAR
rollbackTransaction(transactionStatus);
throw t;
}
}
/**
* Runs in transaction.
*/
protected R runInTransaction(CheckedSupplier supplier) throws X {
return runInTransaction(Propagation.REQUIRED, supplier);
}
/**
* Runs in transaction.
*/
protected R runInTransaction(Propagation propagation, CheckedSupplier supplier) throws X {
TransactionStatus transactionStatus = null;
try {
transactionStatus = startTransaction(propagation);
R result = supplier.get();
commitTransaction(transactionStatus);
return result;
} catch (Throwable t) { // NOSONAR
rollbackTransaction(transactionStatus);
throw t;
}
}
/**
* Returns true
, if scheduling, should be enabled.
*/
protected boolean enableScheduling() {
return !isJUnitTest();
}
/**
* Returns true
, if we are running in the context of a junit-test.
*
* @see "Source: http://stackoverflow.com/a/12717377/1869090"
*/
protected boolean isJUnitTest() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
List list = Arrays.asList(stackTrace);
for (StackTraceElement element : list) {
if (element.getClassName().startsWith("org.junit.")) {
return true;
}
}
return false;
}
}