001
014
015 package com.liferay.portal.spring.transaction;
016
017 import org.aopalliance.intercept.MethodInvocation;
018
019 import org.springframework.transaction.PlatformTransactionManager;
020 import org.springframework.transaction.TransactionStatus;
021 import org.springframework.transaction.interceptor.TransactionAttribute;
022 import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
023 import org.springframework.transaction.support.TransactionCallback;
024
025
029 public class CallbackPreferringTransactionExecutor
030 extends BaseTransactionExecutor {
031
032 @Override
033 public Object execute(
034 PlatformTransactionManager platformTransactionManager,
035 TransactionAttribute transactionAttribute,
036 MethodInvocation methodInvocation)
037 throws Throwable {
038
039 CallbackPreferringPlatformTransactionManager
040 callbackPreferringPlatformTransactionManager =
041 (CallbackPreferringPlatformTransactionManager)
042 platformTransactionManager;
043
044 try {
045 Object result =
046 callbackPreferringPlatformTransactionManager.execute(
047 transactionAttribute,
048 createTransactionCallback(
049 transactionAttribute, methodInvocation));
050
051 if (result instanceof ThrowableHolder) {
052 ThrowableHolder throwableHolder = (ThrowableHolder)result;
053
054 throw throwableHolder.getThrowable();
055 }
056
057 return result;
058 }
059 catch (ThrowableHolderException the) {
060 throw the.getCause();
061 }
062 }
063
064 protected TransactionCallback<Object> createTransactionCallback(
065 TransactionAttribute transactionAttribute,
066 MethodInvocation methodInvocation) {
067
068 return new CallbackPreferringTransactionCallback(
069 transactionAttribute, methodInvocation);
070 }
071
072 protected static class ThrowableHolder {
073
074 public ThrowableHolder(Throwable throwable) {
075 _throwable = throwable;
076 }
077
078 public Throwable getThrowable() {
079 return _throwable;
080 }
081
082 private final Throwable _throwable;
083
084 }
085
086 protected static class ThrowableHolderException extends RuntimeException {
087
088 public ThrowableHolderException(Throwable cause) {
089 super(cause);
090 }
091
092 }
093
094 private class CallbackPreferringTransactionCallback
095 implements TransactionCallback<Object> {
096
097 @Override
098 public Object doInTransaction(TransactionStatus transactionStatus) {
099 boolean newTransaction = transactionStatus.isNewTransaction();
100
101 if (newTransaction) {
102 fireTransactionCreatedEvent(
103 _transactionAttribute, transactionStatus);
104 }
105
106 boolean rollback = false;
107
108 try {
109 return _methodInvocation.proceed();
110 }
111 catch (Throwable throwable) {
112 if (_transactionAttribute.rollbackOn(throwable)) {
113 if (newTransaction) {
114 fireTransactionRollbackedEvent(
115 _transactionAttribute, transactionStatus,
116 throwable);
117
118 rollback = true;
119 }
120
121 if (throwable instanceof RuntimeException) {
122 throw (RuntimeException)throwable;
123 }
124 else {
125 throw new ThrowableHolderException(throwable);
126 }
127 }
128 else {
129 return new ThrowableHolder(throwable);
130 }
131 }
132 finally {
133 if (newTransaction && !rollback) {
134 fireTransactionCommittedEvent(
135 _transactionAttribute, transactionStatus);
136 }
137 }
138 }
139
140 private CallbackPreferringTransactionCallback(
141 TransactionAttribute transactionAttribute,
142 MethodInvocation methodInvocation) {
143
144 _transactionAttribute = transactionAttribute;
145 _methodInvocation = methodInvocation;
146 }
147
148 private final MethodInvocation _methodInvocation;
149 private final TransactionAttribute _transactionAttribute;
150
151 }
152
153 }