001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
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.spring.hibernate.LastSessionRecorderUtil;
023    
024    import org.aopalliance.intercept.MethodInvocation;
025    
026    import org.springframework.transaction.PlatformTransactionManager;
027    import org.springframework.transaction.TransactionStatus;
028    import org.springframework.transaction.TransactionSystemException;
029    import org.springframework.transaction.interceptor.TransactionAttribute;
030    
031    /**
032     * @author Michael C. Han
033     * @author Shuyang Zhou
034     */
035    public class DefaultTransactionExecutor extends BaseTransactionExecutor {
036    
037            @Override
038            public Object execute(
039                            PlatformTransactionManager platformTransactionManager,
040                            TransactionAttribute transactionAttribute,
041                            MethodInvocation methodInvocation)
042                    throws Throwable {
043    
044                    TransactionStatus transactionStatus =
045                            platformTransactionManager.getTransaction(transactionAttribute);
046    
047                    boolean newTransaction = transactionStatus.isNewTransaction();
048    
049                    if (newTransaction) {
050                            TransactionalPortalCacheHelper.begin();
051    
052                            TransactionCommitCallbackUtil.pushCallbackList();
053                    }
054    
055                    Object returnValue = null;
056    
057                    try {
058                            if (newTransaction) {
059                                    LastSessionRecorderUtil.syncLastSessionState();
060                            }
061    
062                            returnValue = methodInvocation.proceed();
063                    }
064                    catch (Throwable throwable) {
065                            processThrowable(
066                                    platformTransactionManager, throwable, transactionAttribute,
067                                    transactionStatus);
068                    }
069    
070                    processCommit(platformTransactionManager, transactionStatus);
071    
072                    return returnValue;
073            }
074    
075            protected void processCommit(
076                    PlatformTransactionManager platformTransactionManager,
077                    TransactionStatus transactionStatus) {
078    
079                    boolean hasError = false;
080    
081                    try {
082                            platformTransactionManager.commit(transactionStatus);
083                    }
084                    catch (TransactionSystemException tse) {
085                            _log.error(
086                                    "Application exception overridden by commit exception", tse);
087    
088                            hasError = true;
089    
090                            throw tse;
091                    }
092                    catch (RuntimeException re) {
093                            _log.error(
094                                    "Application exception overridden by commit exception", re);
095    
096                            hasError = true;
097    
098                            throw re;
099                    }
100                    catch (Error e) {
101                            _log.error("Application exception overridden by commit error", e);
102    
103                            hasError = true;
104    
105                            throw e;
106                    }
107                    finally {
108                            if (transactionStatus.isNewTransaction()) {
109                                    if (hasError) {
110                                            TransactionalPortalCacheHelper.rollback();
111    
112                                            TransactionCommitCallbackUtil.popCallbackList();
113    
114                                            EntityCacheUtil.clearLocalCache();
115                                            FinderCacheUtil.clearLocalCache();
116                                    }
117                                    else {
118                                            TransactionalPortalCacheHelper.commit();
119    
120                                            invokeCallbacks();
121                                    }
122                            }
123                    }
124            }
125    
126            protected void processThrowable(
127                            PlatformTransactionManager platformTransactionManager,
128                            Throwable throwable, TransactionAttribute transactionAttribute,
129                            TransactionStatus transactionStatus)
130                    throws Throwable {
131    
132                    if (transactionAttribute.rollbackOn(throwable)) {
133                            try {
134                                    platformTransactionManager.rollback(transactionStatus);
135                            }
136                            catch (TransactionSystemException tse) {
137                                    _log.error(
138                                            "Application exception overridden by rollback exception",
139                                            tse);
140    
141                                    throw tse;
142                            }
143                            catch (RuntimeException re) {
144                                    _log.error(
145                                            "Application exception overridden by rollback exception",
146                                            re);
147    
148                                    throw re;
149                            }
150                            catch (Error e) {
151                                    _log.error(
152                                            "Application exception overridden by rollback error", e);
153    
154                                    throw e;
155                            }
156                            finally {
157                                    if (transactionStatus.isNewTransaction()) {
158                                            TransactionalPortalCacheHelper.rollback();
159    
160                                            TransactionCommitCallbackUtil.popCallbackList();
161    
162                                            EntityCacheUtil.clearLocalCache();
163                                            FinderCacheUtil.clearLocalCache();
164                                    }
165                            }
166                    }
167                    else {
168                            processCommit(platformTransactionManager, transactionStatus);
169                    }
170    
171                    throw throwable;
172            }
173    
174            private static Log _log = LogFactoryUtil.getLog(
175                    DefaultTransactionExecutor.class);
176    
177    }