BATCH-1708: optimize TaskletStep

This commit is contained in:
Dave Syer
2011-03-11 13:04:57 +00:00
parent 9ccb4c022f
commit c97b50d64b
2 changed files with 70 additions and 44 deletions

View File

@@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.Semaphore;
@@ -32,7 +31,10 @@ import org.springframework.batch.core.JobInterruptedException;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.job.JobSupport;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.core.repository.dao.MapExecutionContextDao;
import org.springframework.batch.core.repository.dao.MapJobExecutionDao;
import org.springframework.batch.core.repository.dao.MapJobInstanceDao;
@@ -43,7 +45,6 @@ import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.util.ReflectionUtils;
public class StepExecutorInterruptionTests {
@@ -56,17 +57,18 @@ public class StepExecutorInterruptionTests {
private StepExecution stepExecution;
private JobRepository jobRepository;
private Field semaphore;
@Before
public void setUp() throws Exception {
jobRepository = new SimpleJobRepository(new MapJobInstanceDao(), new MapJobExecutionDao(),
new MapStepExecutionDao(), new MapExecutionContextDao());
}
private void configureStep(TaskletStep step) throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException {
this.step = step;
JobSupport job = new JobSupport();
step = new TaskletStep("interruptedStep");
job.addStep(step);
job.setBeanName("testJob");
jobExecution = jobRepository.createJobExecution(job.getName(), new JobParameters());
@@ -77,12 +79,13 @@ public class StepExecutorInterruptionTests {
}
};
stepExecution = new StepExecution(step.getName(), jobExecution);
semaphore = ReflectionUtils.findField(step.getClass(), "semaphore");
}
@Test
public void testInterruptStep() throws Exception {
configureStep(new TaskletStep("step"));
Thread processingThread = createThread(stepExecution);
RepeatTemplate template = new RepeatTemplate();
@@ -124,6 +127,28 @@ public class StepExecutorInterruptionTests {
@Test
public void testInterruptOnInterruptedException() throws Exception {
// This simulates the unlikely sounding, but in practice all too common
// in Bamboo situation where the thread is interrupted before the lock
// is taken.
configureStep(new TaskletStep("step") {
@Override
protected Semaphore createSemaphore() {
return new Semaphore(1) {
@Override
public void acquire() throws InterruptedException {
Thread.currentThread().interrupt();
throw new InterruptedException();
}
@Override
public void release() {
}
};
}
});
Thread processingThread = createThread(stepExecution);
step.setTasklet(new TestingChunkOrientedTasklet<Object>(new ItemReader<Object>() {
@@ -132,24 +157,6 @@ public class StepExecutorInterruptionTests {
}
}, itemWriter));
// This simulates the unlikely sounding, but in practice all too common
// in Bamboo situation where the thread is interrupted before the lock
// is taken.
ReflectionUtils.makeAccessible(semaphore);
ReflectionUtils.setField(semaphore, step, new Semaphore(1) {
@Override
public void acquire() throws InterruptedException {
Thread.currentThread().interrupt();
throw new InterruptedException();
}
@Override
public void release() {
}
});
processingThread.start();
Thread.sleep(100);
@@ -168,27 +175,31 @@ public class StepExecutorInterruptionTests {
@Test
public void testLockNotReleasedIfChunkFails() throws Exception {
configureStep(new TaskletStep("step") {
@Override
protected Semaphore createSemaphore() {
return new Semaphore(1) {
private boolean locked = false;
@Override
public void acquire() throws InterruptedException {
locked = true;
}
@Override
public void release() {
assertTrue("Lock released before it is acquired", locked);
}
};
}
});
step.setTasklet(new TestingChunkOrientedTasklet<Object>(new ItemReader<Object>() {
public Object read() throws Exception {
throw new RuntimeException("Planned!");
}
}, itemWriter));
ReflectionUtils.makeAccessible(semaphore);
ReflectionUtils.setField(semaphore, step, new Semaphore(1) {
private boolean locked = false;
@Override
public void acquire() throws InterruptedException {
locked = true;
}
@Override
public void release() {
assertTrue("Lock released before it is acquired", locked);
}
});
jobRepository.add(stepExecution);
step.execute(stepExecution);