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: */package org.apache.geronimo.timer;
017:
018: import javax.transaction.TransactionManager;
019: import javax.transaction.Status;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023:
024: /**
025: * @version $Rev: 476049 $ $Date: 2006-11-16 20:35:17 -0800 (Thu, 16 Nov 2006) $
026: */
027: public class TransactionalExecutorTask implements ExecutorTask {
028: private static final Log log = LogFactory
029: .getLog(TransactionalExecutorTask.class);
030:
031: private final Runnable userTask;
032: private final WorkInfo workInfo;
033: private final ThreadPooledTimer threadPooledTimer;
034:
035: private final TransactionManager transactionManager;
036: private final int repeatCount;
037:
038: public TransactionalExecutorTask(Runnable userTask,
039: WorkInfo workInfo, ThreadPooledTimer threadPooledTimer,
040: 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(
075: "RuntimeException occured while running user task",
076: e);
077: throw e;
078: } catch (Error e) {
079: log.warn("Error occured while running user task", e);
080: throw e;
081: }
082: }
083:
084: private boolean beginWork() {
085: try {
086: transactionManager.begin();
087: } catch (Exception e) {
088: log
089: .warn(
090: "Exception occured while starting container transaction",
091: e);
092: return false;
093: }
094: return true;
095: }
096:
097: private void work() {
098: try {
099: userTask.run();
100: } catch (Exception e) {
101: log.warn("Exception occured while running user task", e);
102: }
103: }
104:
105: private boolean completeWork() {
106: try {
107: if (transactionManager.getStatus() == Status.STATUS_ACTIVE) {
108: // clean up the work persistent data
109: try {
110: threadPooledTimer.workPerformed(workInfo);
111: } catch (PersistenceException e) {
112: log
113: .warn(
114: "Exception occured while updating timer persistent state",
115: e);
116: }
117:
118: // commit the tx
119: transactionManager.commit();
120:
121: // all is cool
122: return true;
123: } else {
124: // tx was marked rollback, so roll it back
125: transactionManager.rollback();
126: }
127: } catch (Exception e) {
128: log
129: .warn(
130: "Exception occured while completing container transaction",
131: e);
132: }
133: // something bad happened
134: return false;
135: }
136:
137: }
|