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