View Javadoc

1   /**
2    * Copyright 2012 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   *
15   * Created by Daniel on 8/8/12
16   */
17  package org.kuali.student.enrollment.class2.courseofferingset.service.impl;
18  
19  import org.apache.log4j.Logger;
20  import org.springframework.transaction.support.TransactionSynchronization;
21  import org.springframework.transaction.support.TransactionSynchronizationManager;
22  
23  import java.util.ArrayList;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  /**
28   * This class //TODO ...
29   *
30   * @author Kuali Student Team
31   */
32  public class KSThreadRunnerAfterTransactionSynchronization implements TransactionSynchronization {
33      final static Logger LOGGER = Logger.getLogger(KSThreadRunnerAfterTransactionSynchronization.class);
34  
35      public static final String THREAD_LIST_KEY ="org.kuali.student.ThreadList";
36  
37      private static final KSThreadRunnerAfterTransactionSynchronization instance = new KSThreadRunnerAfterTransactionSynchronization();
38  
39      @Override
40      public void suspend() {
41          //To change body of implemented methods use File | Settings | File Templates.
42      }
43  
44      @Override
45      public void resume() {
46          //To change body of implemented methods use File | Settings | File Templates.
47      }
48  
49      @Override
50      public void flush() {
51          //To change body of implemented methods use File | Settings | File Templates.
52      }
53  
54      @Override
55      public void beforeCommit(boolean readOnly) {
56          //To change body of implemented methods use File | Settings | File Templates.
57      }
58  
59      @Override
60      public void beforeCompletion() {
61          //To change body of implemented methods use File | Settings | File Templates.
62      }
63  
64      @Override
65      public void afterCommit() {
66          //To change body of implemented methods use File | Settings | File Templates.
67      }
68  
69      @Override
70      //After the transaction has ended, run the threads that have been added to the ThreadList
71      public void afterCompletion(int status) {
72          List<Runnable> threads = (List<Runnable>) TransactionSynchronizationManager.getResource(THREAD_LIST_KEY);
73          if(threads == null){
74              LOGGER.error("The list of threads has not been initialized.");
75          }else{
76              //Execute each of the runners
77              for(Iterator<Runnable> iter = threads.iterator(); iter.hasNext(); ){
78                  Runnable runner = iter.next();
79                  iter.remove();
80                  Thread thread = new Thread(runner);
81                  thread.start();
82              }
83          }
84      }
85  
86      public static void runAfterTransactionCompletes(Runnable runnable){
87          instance._runAfterTransactionCompletes(runnable);
88      }
89  
90      private void _runAfterTransactionCompletes(Runnable runnable){
91          if(!TransactionSynchronizationManager.isSynchronizationActive()){
92              //If there is no transaction then just run normally although there might be a race condition
93              //It is possible the thread will start before the transaction is complete so that persisted entities are not
94              //in the DB in time for the thread to use
95              Thread thread = new Thread(runnable);
96              thread.start();
97          }else{
98  
99              //Register this synchronization manager after the application context has started
100             TransactionSynchronizationManager.registerSynchronization(this);
101 
102             List<Runnable> runnables = (List<Runnable>) TransactionSynchronizationManager.getResource(THREAD_LIST_KEY);
103 
104             if(runnables == null){
105                 runnables = new ArrayList<Runnable>();
106                 //Register the list of threads as a transactional resource
107                 TransactionSynchronizationManager.bindResource(THREAD_LIST_KEY, runnables);
108             }
109 
110             runnables.add(runnable);
111         }
112     }
113 }