001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.geronimo.timer; 020 021 import javax.transaction.TransactionManager; 022 import javax.transaction.Status; 023 024 import org.apache.commons.logging.Log; 025 import org.apache.commons.logging.LogFactory; 026 027 /** 028 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $ 029 */ 030 public class TransactionalExecutorTask implements ExecutorTask { 031 private static final Log log = LogFactory.getLog(TransactionalExecutorTask.class); 032 033 private final Runnable userTask; 034 private final WorkInfo workInfo; 035 private final ThreadPooledTimer threadPooledTimer; 036 037 private final TransactionManager transactionManager; 038 private final int repeatCount; 039 040 public TransactionalExecutorTask(Runnable userTask, WorkInfo workInfo, ThreadPooledTimer threadPooledTimer, TransactionManager transactionManager, int repeatCount) { 041 this.userTask = userTask; 042 this.workInfo = workInfo; 043 this.threadPooledTimer = threadPooledTimer; 044 this.transactionManager = transactionManager; 045 this.repeatCount = repeatCount; 046 } 047 048 public void run() { 049 try { 050 // try to do the work until it succeeded or we reach the repeat count 051 boolean succeeded = false; 052 for (int tries = 0; !succeeded && tries < repeatCount; tries++) { 053 try { 054 if (!beginWork()) { 055 break; 056 } 057 058 work(); 059 } finally { 060 succeeded = completeWork(); 061 } 062 } 063 064 // if this was a one time thing, remove the job 065 if (workInfo.isOneTime()) { 066 threadPooledTimer.removeWorkInfo(workInfo); 067 } 068 069 // if we didn't succeed, log it 070 if (!succeeded) { 071 log.warn("Failed to execute work successfully"); 072 } 073 } catch (RuntimeException e) { 074 log.warn("RuntimeException occured while running user task", e); 075 throw e; 076 } catch (Error e) { 077 log.warn("Error occured while running user task", e); 078 throw e; 079 } 080 } 081 082 private boolean beginWork() { 083 try { 084 transactionManager.begin(); 085 } catch (Exception e) { 086 log.warn("Exception occured while starting container transaction", e); 087 return false; 088 } 089 return true; 090 } 091 092 private void work() { 093 try { 094 userTask.run(); 095 } catch (Exception e) { 096 log.warn("Exception occured while running user task", e); 097 } 098 } 099 100 private boolean completeWork() { 101 try { 102 if (transactionManager.getStatus() == Status.STATUS_ACTIVE) { 103 // clean up the work persistent data 104 try { 105 threadPooledTimer.workPerformed(workInfo); 106 } catch (PersistenceException e) { 107 log.warn("Exception occured while updating timer persistent state", e); 108 } 109 110 // commit the tx 111 transactionManager.commit(); 112 113 // all is cool 114 return true; 115 } else { 116 // tx was marked rollback, so roll it back 117 transactionManager.rollback(); 118 } 119 } catch (Exception e) { 120 log.warn("Exception occured while completing container transaction", e); 121 } 122 // something bad happened 123 return false; 124 } 125 126 }