1 package com.atlassian.xwork.interceptors;
2
3 import com.opensymphony.xwork.ActionInvocation;
4 import com.opensymphony.xwork.interceptor.Interceptor;
5 import com.opensymphony.xwork.interceptor.PreResultListener;
6 import org.apache.log4j.Logger;
7 import org.springframework.transaction.PlatformTransactionManager;
8 import org.springframework.transaction.TransactionStatus;
9
10 /**
11 * Manages two separate database transactions around the action execution and result execution
12 * in XWork, using the Spring PlatformTransactionManager.
13 * <p/>
14 * The first transaction begins as soon as this interceptor executes. It is committed in a {@link
15 * PreResultListener} which runs just before the result executes. The second transaction is opened
16 * in the same listener. The second transaction is committed when control returns to the interceptor
17 * after the action and result executions are both complete.
18 * <p/>
19 * The active transaction will be rolled back if an exception is caught by this interceptor during
20 * the execution of either the action or the result.
21 * <p/>
22 * Implementations should override {@link #getTransactionManager()} to provide the Spring transaction
23 * manager, and {@link #shouldIntercept(ActionInvocation)} to configure when transactions should be
24 * applied to actions.
25 */
26 public abstract class XWorkTransactionInterceptor implements Interceptor
27 {
28 /**
29 * Template method for retrieving the transaction manager for the current application.
30 *
31 * @return the transaction manager for this application
32 */
33 public abstract PlatformTransactionManager getTransactionManager();
34
35 /**
36 * Determine if a certain action should be wrapped in a transaction. Applications should override this method
37 * if they want to prevent specific actions from being intercepted, or want to prevent transactions from being
38 * created before the system is fully set up.
39 *
40 * @param invocation the action being invoked
41 * @return true if the action should be wrapped in a transaction
42 */
43 protected abstract boolean shouldIntercept(ActionInvocation invocation);
44
45 public void destroy()
46 {
47 }
48
49 public void init()
50 {
51 }
52
53 public String intercept(final ActionInvocation invocation) throws Exception
54 {
55 if (shouldIntercept(invocation))
56 return new TransactionalInvocation(getTransactionManager()).invokeInTransaction(invocation);
57 else
58 return invocation.invoke();
59 }
60
61 /**
62 * Return the transaction status of the current method invocation.
63 * Mainly intended for code that wants to set the current transaction
64 * rollback-only but not throw an application exception.
65 *
66 * @throws RuntimeException
67 * if the invocation cannot be found, because the method was invoked
68 * outside an AOP invocation context
69 * @return the status of the current transaction
70 * @deprecated since atlassian-xwork 1.1 - you should really use Spring directly for this sort of thing
71 */
72 public static TransactionStatus currentTransactionStatus() throws RuntimeException
73 {
74 TransactionStatus status = (TransactionStatus) TransactionalInvocation.currentTransactionThreadLocal.get();
75 if (status == null)
76 throw new RuntimeException("No transaction status in scope");
77 return status;
78 }
79
80 }