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