001
014
015 package com.liferay.portal.spring.transaction;
016
017 import com.liferay.portal.cache.transactional.TransactionalPortalCacheHelper;
018 import com.liferay.portal.kernel.dao.orm.EntityCacheUtil;
019 import com.liferay.portal.kernel.dao.orm.FinderCacheUtil;
020 import com.liferay.portal.spring.hibernate.LastSessionRecorderUtil;
021
022 import org.aopalliance.intercept.MethodInvocation;
023
024 import org.springframework.transaction.PlatformTransactionManager;
025 import org.springframework.transaction.TransactionStatus;
026 import org.springframework.transaction.interceptor.TransactionAttribute;
027 import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
028 import org.springframework.transaction.support.TransactionCallback;
029
030
034 public class CallbackPreferringTransactionExecutor
035 extends BaseTransactionExecutor {
036
037 @Override
038 public Object execute(
039 PlatformTransactionManager platformTransactionManager,
040 TransactionAttribute transactionAttribute,
041 MethodInvocation methodInvocation)
042 throws Throwable {
043
044 CallbackPreferringPlatformTransactionManager
045 callbackPreferringPlatformTransactionManager =
046 (CallbackPreferringPlatformTransactionManager)
047 platformTransactionManager;
048
049 try {
050 Object result =
051 callbackPreferringPlatformTransactionManager.execute(
052 transactionAttribute,
053 new CallbackPreferringTransactionCallback(
054 transactionAttribute, methodInvocation));
055
056 if (result instanceof ThrowableHolder) {
057 ThrowableHolder throwableHolder = (ThrowableHolder)result;
058
059 throw throwableHolder.getThrowable();
060 }
061
062 return result;
063 }
064 catch (ThrowableHolderException the) {
065 throw the.getCause();
066 }
067 }
068
069 protected static class ThrowableHolder {
070
071 public ThrowableHolder(Throwable throwable) {
072 _throwable = throwable;
073 }
074
075 public Throwable getThrowable() {
076 return _throwable;
077 }
078
079 private Throwable _throwable;
080
081 }
082
083 protected static class ThrowableHolderException extends RuntimeException {
084
085 public ThrowableHolderException(Throwable cause) {
086 super(cause);
087 }
088
089 }
090
091 private class CallbackPreferringTransactionCallback
092 implements TransactionCallback<Object> {
093
094 private CallbackPreferringTransactionCallback(
095 TransactionAttribute transactionAttribute,
096 MethodInvocation methodInvocation) {
097
098 _transactionAttribute = transactionAttribute;
099 _methodInvocation = methodInvocation;
100 }
101
102 @Override
103 public Object doInTransaction(TransactionStatus transactionStatus) {
104 boolean newTransaction = transactionStatus.isNewTransaction();
105
106 if (newTransaction) {
107 TransactionalPortalCacheHelper.begin();
108
109 TransactionCommitCallbackUtil.pushCallbackList();
110 }
111
112 boolean rollback = false;
113
114 try {
115 if (newTransaction) {
116 LastSessionRecorderUtil.syncLastSessionState();
117 }
118
119 return _methodInvocation.proceed();
120 }
121 catch (Throwable throwable) {
122 if (_transactionAttribute.rollbackOn(throwable)) {
123 if (newTransaction) {
124 TransactionalPortalCacheHelper.rollback();
125
126 TransactionCommitCallbackUtil.popCallbackList();
127
128 EntityCacheUtil.clearLocalCache();
129 FinderCacheUtil.clearLocalCache();
130
131 rollback = true;
132 }
133
134 if (throwable instanceof RuntimeException) {
135 throw (RuntimeException)throwable;
136 }
137 else {
138 throw new ThrowableHolderException(throwable);
139 }
140 }
141 else {
142 return new ThrowableHolder(throwable);
143 }
144 }
145 finally {
146 if (newTransaction && !rollback) {
147 TransactionalPortalCacheHelper.commit();
148
149 invokeCallbacks();
150 }
151 }
152 }
153
154 private MethodInvocation _methodInvocation;
155 private TransactionAttribute _transactionAttribute;
156
157 }
158
159 }