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.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022 import com.liferay.portal.spring.hibernate.LastSessionRecorderUtil;
023
024 import java.lang.reflect.Method;
025
026 import java.util.List;
027 import java.util.concurrent.Callable;
028
029 import org.aopalliance.intercept.MethodInterceptor;
030 import org.aopalliance.intercept.MethodInvocation;
031
032 import org.springframework.transaction.PlatformTransactionManager;
033 import org.springframework.transaction.TransactionStatus;
034 import org.springframework.transaction.TransactionSystemException;
035 import org.springframework.transaction.interceptor.TransactionAttribute;
036 import org.springframework.transaction.interceptor.TransactionAttributeSource;
037
038
041 public class TransactionInterceptor implements MethodInterceptor {
042
043 public Object invoke(MethodInvocation methodInvocation) throws Throwable {
044 Method method = methodInvocation.getMethod();
045
046 Class<?> targetClass = null;
047
048 Object targetBean = methodInvocation.getThis();
049
050 if (targetBean != null) {
051 targetClass = targetBean.getClass();
052 }
053
054 TransactionAttribute transactionAttribute =
055 transactionAttributeSource.getTransactionAttribute(
056 method, targetClass);
057
058 if (transactionAttribute == null) {
059 return methodInvocation.proceed();
060 }
061
062 TransactionStatus transactionStatus =
063 _platformTransactionManager.getTransaction(transactionAttribute);
064
065 boolean newTransaction = transactionStatus.isNewTransaction();
066
067 if (newTransaction) {
068 TransactionalPortalCacheHelper.begin();
069
070 TransactionCommitCallbackUtil.pushCallbackList();
071 }
072
073 Object returnValue = null;
074
075 try {
076 if (newTransaction) {
077 LastSessionRecorderUtil.syncLastSessionState();
078 }
079
080 returnValue = methodInvocation.proceed();
081 }
082 catch (Throwable throwable) {
083 processThrowable(
084 throwable, transactionAttribute, transactionStatus);
085 }
086
087 processCommit(transactionStatus);
088
089 return returnValue;
090 }
091
092 public void setPlatformTransactionManager(
093 PlatformTransactionManager platformTransactionManager) {
094
095 _platformTransactionManager = platformTransactionManager;
096 }
097
098 public void setTransactionAttributeSource(
099 TransactionAttributeSource transactionAttributeSource) {
100
101 this.transactionAttributeSource = transactionAttributeSource;
102 }
103
104
108 public void setTransactionManager(
109 PlatformTransactionManager platformTransactionManager) {
110
111 _platformTransactionManager = platformTransactionManager;
112 }
113
114 protected void invokeCallbacks() {
115 List<Callable<?>> callables =
116 TransactionCommitCallbackUtil.popCallbackList();
117
118 for (Callable<?> callable : callables) {
119 try {
120 callable.call();
121 }
122 catch (Exception e) {
123 _log.error("Failed to execute transaction commit callback", e);
124 }
125 }
126 }
127
128 protected void processCommit(TransactionStatus transactionStatus) {
129 boolean hasError = false;
130
131 try {
132 _platformTransactionManager.commit(transactionStatus);
133 }
134 catch (TransactionSystemException tse) {
135 _log.error(
136 "Application exception overridden by commit exception", tse);
137
138 hasError = true;
139
140 throw tse;
141 }
142 catch (RuntimeException re) {
143 _log.error(
144 "Application exception overridden by commit exception", re);
145
146 hasError = true;
147
148 throw re;
149 }
150 catch (Error e) {
151 _log.error("Application exception overridden by commit error", e);
152
153 hasError = true;
154
155 throw e;
156 }
157 finally {
158 if (transactionStatus.isNewTransaction()) {
159 if (hasError) {
160 TransactionalPortalCacheHelper.rollback();
161
162 TransactionCommitCallbackUtil.popCallbackList();
163
164 EntityCacheUtil.clearLocalCache();
165 FinderCacheUtil.clearLocalCache();
166 }
167 else {
168 TransactionalPortalCacheHelper.commit();
169
170 invokeCallbacks();
171 }
172 }
173 }
174 }
175
176 protected void processThrowable(
177 Throwable throwable, TransactionAttribute transactionAttribute,
178 TransactionStatus transactionStatus)
179 throws Throwable {
180
181 if (transactionAttribute.rollbackOn(throwable)) {
182 try {
183 _platformTransactionManager.rollback(transactionStatus);
184 }
185 catch (TransactionSystemException tse) {
186 _log.error(
187 "Application exception overridden by rollback exception",
188 tse);
189
190 throw tse;
191 }
192 catch (RuntimeException re) {
193 _log.error(
194 "Application exception overridden by rollback exception",
195 re);
196
197 throw re;
198 }
199 catch (Error e) {
200 _log.error(
201 "Application exception overridden by rollback error", e);
202
203 throw e;
204 }
205 finally {
206 if (transactionStatus.isNewTransaction()) {
207 TransactionalPortalCacheHelper.rollback();
208
209 TransactionCommitCallbackUtil.popCallbackList();
210
211 EntityCacheUtil.clearLocalCache();
212 FinderCacheUtil.clearLocalCache();
213 }
214 }
215 }
216 else {
217 processCommit(transactionStatus);
218 }
219
220 throw throwable;
221 }
222
223 protected TransactionAttributeSource transactionAttributeSource;
224
225 private static Log _log = LogFactoryUtil.getLog(
226 TransactionInterceptor.class);
227
228 private PlatformTransactionManager _platformTransactionManager;
229
230 }