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 processThrowable(
112 Throwable throwable, TransactionAttribute transactionAttribute,
113 TransactionStatus transactionStatus)
114 throws Throwable {
115
116 if (transactionAttribute.rollbackOn(throwable)) {
117 try {
118 _platformTransactionManager.rollback(transactionStatus);
119 }
120 catch (TransactionSystemException tse) {
121 _log.error(
122 "Application exception overridden by rollback exception",
123 tse);
124
125 throw tse;
126 }
127 catch (RuntimeException re) {
128 _log.error(
129 "Application exception overridden by rollback exception",
130 re);
131
132 throw re;
133 }
134 catch (Error e) {
135 _log.error(
136 "Application exception overridden by rollback error", e);
137
138 throw e;
139 }
140 finally {
141 if (transactionStatus.isNewTransaction()) {
142 TransactionalPortalCacheHelper.rollback();
143
144 TransactionCommitCallbackUtil.popCallbackList();
145 }
146 }
147 }
148 else {
149 boolean hasError = false;
150
151 try {
152 _platformTransactionManager.commit(transactionStatus);
153 }
154 catch (TransactionSystemException tse) {
155 _log.error(
156 "Application exception overridden by commit exception",
157 tse);
158
159 hasError = true;
160
161 throw tse;
162 }
163 catch (RuntimeException re) {
164 _log.error(
165 "Application exception overridden by commit exception", re);
166
167 hasError = true;
168
169 throw re;
170 }
171 catch (Error e) {
172 _log.error(
173 "Application exception overridden by commit error", e);
174
175 hasError = true;
176
177 throw e;
178 }
179 finally {
180 if (transactionStatus.isNewTransaction()) {
181 if (hasError) {
182 TransactionalPortalCacheHelper.rollback();
183
184 TransactionCommitCallbackUtil.popCallbackList();
185 }
186 else {
187 TransactionalPortalCacheHelper.commit();
188
189 invokeCallbacks();
190 }
191 }
192 }
193 }
194
195 throw throwable;
196 }
197
198 private void invokeCallbacks() {
199 List<Callable<?>> callables =
200 TransactionCommitCallbackUtil.popCallbackList();
201
202 for (Callable<?> callable : callables) {
203 try {
204 callable.call();
205 }
206 catch (Exception e) {
207 _log.error("Failed to execute transaction commit callback", e);
208 }
209 }
210 }
211
212 protected TransactionAttributeSource transactionAttributeSource;
213
214 private static Log _log = LogFactoryUtil.getLog(
215 TransactionInterceptor.class);
216
217 private PlatformTransactionManager _platformTransactionManager;
218
219 }