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 }