root/head/ambra/webapp/src/main/java/org/topazproject/ambra/struts2/TransactionInterceptor.java

Revision 8549, 5.8 KB (checked in by ssterling, 2 months ago)

Updated the copyright information for all the Java classes in the Ambra project.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id HeadURL Revision
Line 
1/* $HeadURL$
2 * $Id$
3 *
4 * Copyright (c) 2006-2010 by Public Library of Science
5 * http://plos.org
6 * http://ambraproject.org
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 *     http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21package org.topazproject.ambra.struts2;
22
23import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
24import com.opensymphony.xwork2.ActionInvocation;
25import com.opensymphony.xwork2.Action;
26import com.opensymphony.xwork2.ActionProxy;
27
28import org.springframework.transaction.annotation.Transactional;
29import org.springframework.transaction.PlatformTransactionManager;
30import org.springframework.transaction.TransactionStatus;
31import org.springframework.transaction.support.TransactionTemplate;
32import org.springframework.transaction.support.TransactionCallback;
33import org.springframework.beans.factory.annotation.Required;
34
35import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
38import java.lang.reflect.Method;
39import java.lang.annotation.Annotation;
40
41/**
42 * Struts interceptor that will wrap a Spring managed transaction around action and result.
43 * Transaction parameters are specified in nested annotation.
44 * <p/>
45 * Use when you want transaction to span beyond your action method into result.
46 *
47 * @author Dragisa Krsmanovic
48 */
49public class TransactionInterceptor extends AbstractInterceptor {
50  private static final Logger log = LoggerFactory.getLogger(TransactionInterceptor.class);
51
52  private PlatformTransactionManager txManager;
53
54  public String intercept(final ActionInvocation actionInvocation) throws Exception {
55
56    Action action = (Action) actionInvocation.getAction();
57    ActionProxy actionProxy = actionInvocation.getProxy();
58    String methodName = actionProxy.getMethod();
59
60    Span span = getAnnotation(action.getClass(), methodName, Span.class);
61    if (span == null) {
62      return actionInvocation.invoke();
63    }
64
65    if (log.isDebugEnabled())
66      log.debug("Interceped " + action.getClass().getName() + "." + methodName + "(...)");
67
68    final Transactional transactional = span.value();
69
70    TransactionTemplate txTemplate = new TransactionTemplate(txManager);
71    txTemplate.setReadOnly(transactional.readOnly());
72    txTemplate.setTimeout(transactional.timeout());
73    txTemplate.setIsolationLevel(transactional.isolation().value());
74    txTemplate.setPropagationBehavior(transactional.propagation().value());
75
76    CallbackResult callbackResult = (CallbackResult) txTemplate.execute(new TransactionCallback() {
77      public CallbackResult doInTransaction(TransactionStatus transactionStatus) {
78        CallbackResult result = new CallbackResult();
79        try {
80          result.setResult(actionInvocation.invoke());
81        } catch (Exception e) {
82          /*
83           * Callback does not throw exception. We need to pass Exception object in the return
84           * parameter so we can throw it in the calling method.
85           */
86          boolean noRollback = false;
87
88          if (transactional.noRollbackFor() != null) {
89            for (Class<? extends Throwable> exception : transactional.noRollbackFor()) {
90              if (exception.isInstance(e)) {
91                noRollback = true;
92                break;
93              }
94            }
95          }
96
97          if (!noRollback && transactional.rollbackFor() != null) {
98            for (Class<? extends Throwable> exception : transactional.rollbackFor()) {
99              if (exception.isInstance(e)) {
100                transactionStatus.setRollbackOnly();
101                break;
102              }
103            }
104          }
105          result.setException(e);
106        }
107        return result;
108      }
109    });
110
111    if (callbackResult.getException() != null)
112      throw callbackResult.getException();
113
114    return callbackResult.getResult();
115  }
116
117  private <A extends Annotation> A getAnnotation(Class<? extends Action> actionClass,
118    String methodName, Class<A> annotationType) throws Exception {
119    A annotation = actionClass.getAnnotation(annotationType);
120    if (annotation == null) {
121      annotation = getMethodAnnotation(actionClass, methodName, annotationType);
122    }
123
124    return annotation;
125  }
126
127  private <A extends Annotation> A getMethodAnnotation(Class<? extends Action> actionClass,
128    String methodName, Class<A> annotationType) {
129    try {
130      Method method = actionClass.getDeclaredMethod(methodName);
131      A annotation = method.getAnnotation(annotationType);
132      if (annotation == null) {
133        Class parent = actionClass.getSuperclass();
134        if (Action.class.isAssignableFrom(parent)) {
135          annotation = getMethodAnnotation((Class<? extends Action>) parent,
136              methodName, annotationType);
137        }
138      }
139      return annotation;
140    } catch (NoSuchMethodException e) {
141      return null;
142    }
143  }
144
145  /**
146   * Spring setter method. Sets Spring transaction manager
147   *
148   * @param txManager Transaction manager
149   */
150  @Required
151  public void setTxManager(PlatformTransactionManager txManager) {
152    this.txManager = txManager;
153  }
154
155  /**
156   * Return value from TransactionTemplate callback. Encapsulates possible Exception.
157   */
158  private static class CallbackResult {
159
160    private String result;
161    private Exception exception;
162
163    public String getResult() {
164      return result;
165    }
166
167    public void setResult(String result) {
168      this.result = result;
169    }
170
171    public Exception getException() {
172      return exception;
173    }
174
175    public void setException(Exception exception) {
176      this.exception = exception;
177    }
178  }
179}
Note: See TracBrowser for help on using the browser.