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