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