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