/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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 library 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.
*/
package com.liferay.portal.spring.transaction;
import com.liferay.portal.kernel.transaction.TransactionLifecycleManager;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
import org.springframework.transaction.support.TransactionCallback;
/**
* @author Michael C. Han
* @author Shuyang Zhou
*/
public class CallbackPreferringTransactionExecutor
implements TransactionExecutor {
@Override
public Object execute(
PlatformTransactionManager platformTransactionManager,
TransactionAttributeAdapter transactionAttributeAdapter,
MethodInvocation methodInvocation)
throws Throwable {
CallbackPreferringPlatformTransactionManager
callbackPreferringPlatformTransactionManager =
(CallbackPreferringPlatformTransactionManager)
platformTransactionManager;
try {
Object result =
callbackPreferringPlatformTransactionManager.execute(
transactionAttributeAdapter,
createTransactionCallback(
callbackPreferringPlatformTransactionManager,
transactionAttributeAdapter, methodInvocation));
if (result instanceof ThrowableHolder) {
ThrowableHolder throwableHolder = (ThrowableHolder)result;
throw throwableHolder.getThrowable();
}
return result;
}
catch (ThrowableHolderException the) {
throw the.getCause();
}
}
protected TransactionCallback<Object> createTransactionCallback(
CallbackPreferringPlatformTransactionManager
callbackPreferringPlatformTransactionManager,
TransactionAttributeAdapter transactionAttributeAdapter,
MethodInvocation methodInvocation) {
return new CallbackPreferringTransactionCallback(
callbackPreferringPlatformTransactionManager,
transactionAttributeAdapter, methodInvocation);
}
/**
* @deprecated As of 7.0.0, replaced by {@link
* #createTransactionCallback(
* CallbackPreferringPlatformTransactionManager,
* TransactionAttributeAdapter, MethodInvocation)}
*/
@Deprecated
protected TransactionCallback<Object> createTransactionCallback(
TransactionAttributeAdapter transactionAttributeAdapter,
MethodInvocation methodInvocation) {
return new CallbackPreferringTransactionCallback(
null, transactionAttributeAdapter, methodInvocation);
}
protected static class ThrowableHolder {
public ThrowableHolder(Throwable throwable) {
_throwable = throwable;
}
public Throwable getThrowable() {
return _throwable;
}
private final Throwable _throwable;
}
protected static class ThrowableHolderException extends RuntimeException {
public ThrowableHolderException(Throwable cause) {
super(cause);
}
}
private class CallbackPreferringTransactionCallback
implements TransactionCallback<Object> {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
TransactionStatusAdapter transactionStatusAdapter =
new TransactionStatusAdapter(
_platformTransactionManager, transactionStatus);
TransactionLifecycleManager.fireTransactionCreatedEvent(
_transactionAttributeAdapter, transactionStatusAdapter);
boolean rollback = false;
try {
return _methodInvocation.proceed();
}
catch (Throwable throwable) {
if (_transactionAttributeAdapter.rollbackOn(throwable)) {
TransactionLifecycleManager.fireTransactionRollbackedEvent(
_transactionAttributeAdapter, transactionStatusAdapter,
throwable);
if (transactionStatus.isNewTransaction()) {
rollback = true;
}
if (throwable instanceof RuntimeException) {
throw (RuntimeException)throwable;
}
else {
throw new ThrowableHolderException(throwable);
}
}
else {
return new ThrowableHolder(throwable);
}
}
finally {
if (!rollback) {
TransactionLifecycleManager.fireTransactionCommittedEvent(
_transactionAttributeAdapter, transactionStatusAdapter);
}
}
}
private CallbackPreferringTransactionCallback(
PlatformTransactionManager platformTransactionManager,
TransactionAttributeAdapter transactionAttributeAdapter,
MethodInvocation methodInvocation) {
_platformTransactionManager = platformTransactionManager;
_transactionAttributeAdapter = transactionAttributeAdapter;
_methodInvocation = methodInvocation;
}
private final MethodInvocation _methodInvocation;
private final PlatformTransactionManager _platformTransactionManager;
private final TransactionAttributeAdapter _transactionAttributeAdapter;
}
}