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.spring.hibernate.LastSessionRecorderUtil;
021
022 import org.aopalliance.intercept.MethodInvocation;
023
024 import org.springframework.transaction.PlatformTransactionManager;
025 import org.springframework.transaction.TransactionStatus;
026 import org.springframework.transaction.interceptor.TransactionAttribute;
027 import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
028 import org.springframework.transaction.support.TransactionCallback;
029
030
034 public class CallbackPreferringTransactionExecutor
035 extends BaseTransactionExecutor {
036
037 @Override
038 public Object execute(
039 PlatformTransactionManager platformTransactionManager,
040 TransactionAttribute transactionAttribute,
041 MethodInvocation methodInvocation)
042 throws Throwable {
043
044 CallbackPreferringPlatformTransactionManager
045 callbackPreferringPlatformTransactionManager =
046 (CallbackPreferringPlatformTransactionManager)
047 platformTransactionManager;
048
049 try {
050 Object result =
051 callbackPreferringPlatformTransactionManager.execute(
052 transactionAttribute,
053 createTransactionCallback(
054 transactionAttribute, methodInvocation));
055
056 if (result instanceof ThrowableHolder) {
057 ThrowableHolder throwableHolder = (ThrowableHolder)result;
058
059 throw throwableHolder.getThrowable();
060 }
061
062 return result;
063 }
064 catch (ThrowableHolderException the) {
065 throw the.getCause();
066 }
067 }
068
069 protected TransactionCallback<Object> createTransactionCallback(
070 TransactionAttribute transactionAttribute,
071 MethodInvocation methodInvocation) {
072
073 return new CallbackPreferringTransactionCallback(
074 transactionAttribute, methodInvocation);
075 }
076
077 protected static class ThrowableHolder {
078
079 public ThrowableHolder(Throwable throwable) {
080 _throwable = throwable;
081 }
082
083 public Throwable getThrowable() {
084 return _throwable;
085 }
086
087 private Throwable _throwable;
088
089 }
090
091 protected static class ThrowableHolderException extends RuntimeException {
092
093 public ThrowableHolderException(Throwable cause) {
094 super(cause);
095 }
096
097 }
098
099 private class CallbackPreferringTransactionCallback
100 implements TransactionCallback<Object> {
101
102 private CallbackPreferringTransactionCallback(
103 TransactionAttribute transactionAttribute,
104 MethodInvocation methodInvocation) {
105
106 _transactionAttribute = transactionAttribute;
107 _methodInvocation = methodInvocation;
108 }
109
110 @Override
111 public Object doInTransaction(TransactionStatus transactionStatus) {
112 boolean newTransaction = transactionStatus.isNewTransaction();
113
114 if (newTransaction) {
115 TransactionalPortalCacheHelper.begin();
116
117 TransactionCommitCallbackUtil.pushCallbackList();
118 }
119
120 boolean rollback = false;
121
122 try {
123 if (newTransaction) {
124 LastSessionRecorderUtil.syncLastSessionState();
125 }
126
127 return _methodInvocation.proceed();
128 }
129 catch (Throwable throwable) {
130 if (_transactionAttribute.rollbackOn(throwable)) {
131 if (newTransaction) {
132 TransactionalPortalCacheHelper.rollback();
133
134 TransactionCommitCallbackUtil.popCallbackList();
135
136 EntityCacheUtil.clearLocalCache();
137 FinderCacheUtil.clearLocalCache();
138
139 rollback = true;
140 }
141
142 if (throwable instanceof RuntimeException) {
143 throw (RuntimeException)throwable;
144 }
145 else {
146 throw new ThrowableHolderException(throwable);
147 }
148 }
149 else {
150 return new ThrowableHolder(throwable);
151 }
152 }
153 finally {
154 if (newTransaction && !rollback) {
155 TransactionalPortalCacheHelper.commit();
156
157 invokeCallbacks();
158 }
159 }
160 }
161
162 private MethodInvocation _methodInvocation;
163 private TransactionAttribute _transactionAttribute;
164
165 }
166
167 }