001 /**
002 * Copyright 2004-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.hr.time.batch;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.apache.log4j.Logger;
020 import org.kuali.hr.time.service.base.TkServiceLocator;
021 import org.kuali.hr.time.util.TkConstants;
022 import org.springframework.transaction.TransactionStatus;
023 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
024
025 public abstract class BatchJobEntryRunnable implements Runnable{
026
027 private Logger LOG = Logger.getLogger(BatchJobEntryRunnable.class);
028
029 long startTime;
030 long endTime;
031 Long tkBatchJobEntryId;
032 Long tkBatchJobId;
033 BatchJobEntry batchJobEntry;
034
035 public BatchJobEntryRunnable(BatchJobEntry entry) {
036 this.batchJobEntry = entry;
037 this.tkBatchJobEntryId = entry.getTkBatchJobEntryId();
038 this.tkBatchJobId = entry.getTkBatchJobId();
039 }
040
041 /**
042 * Method that is called before the user function doWork() is called. Any
043 * pre-work maintenance can be done in this method.
044 */
045 void doBeforeRun() {
046 startTime = System.currentTimeMillis();
047 LOG.debug("Before run.");
048 batchJobEntry.setBatchJobEntryStatus(TkConstants.BATCH_JOB_ENTRY_STATUS.RUNNING);
049 TkServiceLocator.getBatchJobEntryService().saveBatchJobEntry(batchJobEntry);
050 }
051
052 @Override
053 public final void run() {
054 TkServiceLocator.getTransactionTemplate().execute(new TransactionCallbackWithoutResult() {
055 @Override
056 protected void doInTransactionWithoutResult(TransactionStatus status) {
057 try {
058 doBeforeRun();
059 doWork();
060 doAfterRun();
061 } catch (Throwable t) {
062 LOG.warn("BatchJobEntry: " + batchJobEntry.getTkBatchJobEntryId() + " in Exception status.");
063 batchJobEntry.setBatchJobException(t.getStackTrace().toString());
064 }
065 };
066 });
067 }
068
069 /**
070 * Implement this method in your subclass. Place business logic here to handle
071 * whatever needs to be done for this unit of work.
072 *
073 * @throws Exception when problem encountered during work processing, exception
074 * stored in BatchJobEntry, and transaction rolled back.
075 */
076 public abstract void doWork() throws Exception;
077
078 /**
079 * Method that is called after the user function doWork() is called. Any
080 * post-work maintenance can be done in this method.
081 */
082 void doAfterRun() {
083 endTime = System.currentTimeMillis();
084 long runtime = endTime - startTime;
085 runtime = (runtime > 0) ? runtime : 1; // hack around 0 length job... just in case.
086 LOG.debug("Job finished in " + runtime / 1000 + " seconds.");
087
088 if (StringUtils.isEmpty(batchJobEntry.getBatchJobException())) {
089 batchJobEntry.setBatchJobEntryStatus(TkConstants.BATCH_JOB_ENTRY_STATUS.FINISHED);
090 } else {
091 batchJobEntry.setBatchJobEntryStatus(TkConstants.BATCH_JOB_ENTRY_STATUS.EXCEPTION);
092 }
093 TkServiceLocator.getBatchJobEntryService().saveBatchJobEntry(batchJobEntry);
094 }
095
096 public Long getTkBatchJobEntryId() {
097 return tkBatchJobEntryId;
098 }
099
100 public Long getTkBatchJobId() {
101 return tkBatchJobId;
102 }
103
104 public BatchJobEntry getBatchJobEntry() {
105 return batchJobEntry;
106 }
107 }