001
014
015 package com.liferay.portal.spring.transaction;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.transaction.TransactionAttribute;
020 import com.liferay.portal.kernel.transaction.TransactionLifecycleListener;
021 import com.liferay.portal.kernel.transaction.TransactionStatus;
022 import com.liferay.portal.kernel.util.AutoResetThreadLocal;
023
024 import java.util.ArrayList;
025 import java.util.Collections;
026 import java.util.List;
027 import java.util.concurrent.Callable;
028
029
032 public class TransactionCommitCallbackUtil {
033
034 public static final TransactionLifecycleListener
035 TRANSACTION_LIFECYCLE_LISTENER = new TransactionLifecycleListener() {
036
037 @Override
038 public void created(
039 TransactionAttribute transactionAttribute,
040 TransactionStatus transactionStatus) {
041
042 pushCallbackList();
043 }
044
045 @Override
046 public void committed(
047 TransactionAttribute transactionAttribute,
048 TransactionStatus transactionStatus) {
049
050 List<Callable<?>> callables = popCallbackList();
051
052 for (Callable<?> callable : callables) {
053 try {
054 callable.call();
055 }
056 catch (Exception e) {
057 _log.error(
058 "Unable to execute transaction commit callback", e);
059 }
060 }
061 }
062
063 @Override
064 public void rollbacked(
065 TransactionAttribute transactionAttribute,
066 TransactionStatus transactionStatus, Throwable throwable) {
067
068 popCallbackList();
069 }
070
071 };
072
073 public static void registerCallback(Callable<?> callable) {
074 List<List<Callable<?>>> callbackListList =
075 _callbackListListThreadLocal.get();
076
077 if (callbackListList.isEmpty()) {
078
079
080
081
082 try {
083 callable.call();
084 }
085 catch (Exception e) {
086 throw new RuntimeException(e);
087 }
088 }
089 else {
090 int index = callbackListList.size() - 1;
091
092 List<Callable<?>> callableList = callbackListList.get(index);
093
094 if (callableList == Collections.<Callable<?>>emptyList()) {
095 callableList = new ArrayList<Callable<?>>();
096
097 callbackListList.set(index, callableList);
098 }
099
100 callableList.add(callable);
101 }
102 }
103
104 protected static List<Callable<?>> popCallbackList() {
105 List<List<Callable<?>>> callbackListList =
106 _callbackListListThreadLocal.get();
107
108 return callbackListList.remove(callbackListList.size() - 1);
109 }
110
111 protected static void pushCallbackList() {
112 List<List<Callable<?>>> callbackListList =
113 _callbackListListThreadLocal.get();
114
115 callbackListList.add(Collections.<Callable<?>>emptyList());
116 }
117
118 private static final Log _log = LogFactoryUtil.getLog(
119 TransactionCommitCallbackUtil.class);
120
121 private static final ThreadLocal<List<List<Callable<?>>>>
122 _callbackListListThreadLocal =
123 new AutoResetThreadLocal<List<List<Callable<?>>>>(
124 TransactionCommitCallbackUtil.class +
125 "._callbackListListThreadLocal") {
126
127 @Override
128 protected List<List<Callable<?>>> initialValue() {
129 return new ArrayList<List<Callable<?>>>();
130 }
131
132 };
133
134 }