001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
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.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.search.buffer.IndexerRequestBufferTransactionLifecycleListener;
023    import com.liferay.portal.spring.hibernate.LastSessionRecorderUtil;
024    
025    import org.aopalliance.intercept.MethodInvocation;
026    
027    import org.springframework.transaction.PlatformTransactionManager;
028    import org.springframework.transaction.TransactionStatus;
029    import org.springframework.transaction.TransactionSystemException;
030    import org.springframework.transaction.interceptor.TransactionAttribute;
031    
032    /**
033     * @author Michael C. Han
034     * @author Shuyang Zhou
035     */
036    public class DefaultTransactionExecutor extends BaseTransactionExecutor {
037    
038            @Override
039            public Object execute(
040                            PlatformTransactionManager platformTransactionManager,
041                            TransactionAttribute transactionAttribute,
042                            MethodInvocation methodInvocation)
043                    throws Throwable {
044    
045                    TransactionStatus transactionStatus =
046                            platformTransactionManager.getTransaction(transactionAttribute);
047    
048                    boolean newTransaction = transactionStatus.isNewTransaction();
049    
050                    if (newTransaction) {
051                            TransactionalPortalCacheHelper.begin();
052    
053                            TransactionCommitCallbackUtil.pushCallbackList();
054    
055                            IndexerRequestBufferTransactionLifecycleListener.created();
056                    }
057    
058                    Object returnValue = null;
059    
060                    try {
061                            if (newTransaction) {
062                                    LastSessionRecorderUtil.syncLastSessionState();
063                            }
064    
065                            returnValue = methodInvocation.proceed();
066                    }
067                    catch (Throwable throwable) {
068                            processThrowable(
069                                    platformTransactionManager, throwable, transactionAttribute,
070                                    transactionStatus);
071                    }
072    
073                    processCommit(platformTransactionManager, transactionStatus);
074    
075                    return returnValue;
076            }
077    
078            protected void processCommit(
079                    PlatformTransactionManager platformTransactionManager,
080                    TransactionStatus transactionStatus) {
081    
082                    boolean hasError = false;
083    
084                    try {
085                            platformTransactionManager.commit(transactionStatus);
086                    }
087                    catch (TransactionSystemException tse) {
088                            _log.error(
089                                    "Application exception overridden by commit exception", tse);
090    
091                            hasError = true;
092    
093                            throw tse;
094                    }
095                    catch (RuntimeException re) {
096                            _log.error(
097                                    "Application exception overridden by commit exception", re);
098    
099                            hasError = true;
100    
101                            throw re;
102                    }
103                    catch (Error e) {
104                            _log.error("Application exception overridden by commit error", e);
105    
106                            hasError = true;
107    
108                            throw e;
109                    }
110                    finally {
111                            if (transactionStatus.isNewTransaction()) {
112                                    if (hasError) {
113                                            TransactionalPortalCacheHelper.rollback();
114    
115                                            TransactionCommitCallbackUtil.popCallbackList();
116    
117                                            IndexerRequestBufferTransactionLifecycleListener.
118                                                    rollbacked();
119    
120                                            EntityCacheUtil.clearLocalCache();
121                                            FinderCacheUtil.clearLocalCache();
122                                    }
123                                    else {
124                                            TransactionalPortalCacheHelper.commit();
125    
126                                            invokeCallbacks();
127                                    }
128                            }
129                    }
130            }
131    
132            protected void processThrowable(
133                            PlatformTransactionManager platformTransactionManager,
134                            Throwable throwable, TransactionAttribute transactionAttribute,
135                            TransactionStatus transactionStatus)
136                    throws Throwable {
137    
138                    if (transactionAttribute.rollbackOn(throwable)) {
139                            try {
140                                    platformTransactionManager.rollback(transactionStatus);
141                            }
142                            catch (TransactionSystemException tse) {
143                                    _log.error(
144                                            "Application exception overridden by rollback exception",
145                                            tse);
146    
147                                    throw tse;
148                            }
149                            catch (RuntimeException re) {
150                                    _log.error(
151                                            "Application exception overridden by rollback exception",
152                                            re);
153    
154                                    throw re;
155                            }
156                            catch (Error e) {
157                                    _log.error(
158                                            "Application exception overridden by rollback error", e);
159    
160                                    throw e;
161                            }
162                            finally {
163                                    if (transactionStatus.isNewTransaction()) {
164                                            TransactionalPortalCacheHelper.rollback();
165    
166                                            TransactionCommitCallbackUtil.popCallbackList();
167    
168                                            IndexerRequestBufferTransactionLifecycleListener.
169                                                    rollbacked();
170    
171                                            EntityCacheUtil.clearLocalCache();
172                                            FinderCacheUtil.clearLocalCache();
173                                    }
174                            }
175                    }
176                    else {
177                            processCommit(platformTransactionManager, transactionStatus);
178                    }
179    
180                    throw throwable;
181            }
182    
183            private static Log _log = LogFactoryUtil.getLog(
184                    DefaultTransactionExecutor.class);
185    
186    }