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