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 }