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 fireTransactionCreatedEvent(
100 _transactionAttribute, transactionStatus);
101
102 boolean rollback = false;
103
104 try {
105 return _methodInvocation.proceed();
106 }
107 catch (Throwable throwable) {
108 if (_transactionAttribute.rollbackOn(throwable)) {
109 fireTransactionRollbackedEvent(
110 _transactionAttribute, transactionStatus, throwable);
111
112 if (transactionStatus.isNewTransaction()) {
113 rollback = true;
114 }
115
116 if (throwable instanceof RuntimeException) {
117 throw (RuntimeException)throwable;
118 }
119 else {
120 throw new ThrowableHolderException(throwable);
121 }
122 }
123 else {
124 return new ThrowableHolder(throwable);
125 }
126 }
127 finally {
128 if (!rollback) {
129 fireTransactionCommittedEvent(
130 _transactionAttribute, transactionStatus);
131 }
132 }
133 }
134
135 private CallbackPreferringTransactionCallback(
136 TransactionAttribute transactionAttribute,
137 MethodInvocation methodInvocation) {
138
139 _transactionAttribute = transactionAttribute;
140 _methodInvocation = methodInvocation;
141 }
142
143 private final MethodInvocation _methodInvocation;
144 private final TransactionAttribute _transactionAttribute;
145
146 }
147
148 }