View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.web.controller;
17  
18  import org.springframework.beans.factory.annotation.Autowired;
19  import org.springframework.beans.factory.annotation.Qualifier;
20  import org.springframework.transaction.PlatformTransactionManager;
21  import org.springframework.transaction.TransactionDefinition;
22  import org.springframework.transaction.TransactionStatus;
23  import org.springframework.transaction.support.DefaultTransactionDefinition;
24  import org.springframework.web.servlet.HandlerInterceptor;
25  import org.springframework.web.servlet.ModelAndView;
26  
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  
30  /**
31   * Spring interceptor class that will start the Rice configured transaction on pre handle (before binding
32   * and controller) and commit after controller execution.
33   * <p/>
34   * <p>For KRAD, this interceptor should be listed first
35   * (before {@link org.kuali.rice.krad.web.controller.UifControllerHandlerInterceptor})</p>
36   *
37   * @author Kuali Rice Team (rice.collab@kuali.org)
38   * @see org.kuali.rice.core.framework.persistence.jta.Jta
39   */
40  public class TransactionHandlerInterceptor implements HandlerInterceptor {
41  
42      private static final ThreadLocal<TransactionStatus> context = new ThreadLocal<TransactionStatus>();
43  
44      @Autowired()
45      @Qualifier("transactionManager")
46      PlatformTransactionManager txManager;
47  
48      /**
49       * {@inheritDoc}
50       */
51      @Override
52      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
53              throws Exception {
54          DefaultTransactionDefinition def = new DefaultTransactionDefinition();
55          def.setName("request");
56          def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
57  
58          TransactionStatus status = txManager.getTransaction(def);
59          context.set(status);
60  
61          return true;
62      }
63  
64      /**
65       * {@inheritDoc}
66       */
67      @Override
68      public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
69              ModelAndView modelAndView) throws Exception {
70          completeTransaction(null);
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      @Override
77      public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
78              throws Exception {
79          completeTransaction(ex);
80      }
81  
82      /**
83       * Completes the request transaction if needed.
84       *
85       * @param ex any exception that might have been thrown, will cause a rollback
86       */
87      protected void completeTransaction(Exception ex) {
88          TransactionStatus status = context.get();
89  
90          if (status == null) {
91              return;
92          }
93  
94          try {
95              if (!status.isCompleted()) {
96                  if (ex == null && !status.isRollbackOnly()) {
97                      txManager.commit(status);
98                  } else {
99                      txManager.rollback(status);
100                 }
101             }
102         } finally {
103             context.remove();
104         }
105     }
106 }