BATCH-2009 - Stoppable tasklet
* Added the StoppableTasklet interface (an extension of the Tasklet interface). * Updated JobOperator#stop(long executionId) to call StoppableTasklet#stop() on any currently running tasklets (local executions only). * Updated the SystemCommandTasklet to implement StoppableTasklet
This commit is contained in:
committed by
Michael Minella
parent
dbc829273b
commit
81e0c38d52
@@ -19,10 +19,12 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -35,12 +37,17 @@ import org.junit.Test;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobExecutionException;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersIncrementer;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.configuration.JobRegistry;
|
||||
import org.springframework.batch.core.configuration.support.MapJobRegistry;
|
||||
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
|
||||
import org.springframework.batch.core.explore.JobExplorer;
|
||||
import org.springframework.batch.core.job.AbstractJob;
|
||||
import org.springframework.batch.core.job.JobSupport;
|
||||
import org.springframework.batch.core.launch.JobInstanceAlreadyExistsException;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
@@ -51,6 +58,10 @@ import org.springframework.batch.core.repository.JobExecutionAlreadyRunningExcep
|
||||
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.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.StoppableTasklet;
|
||||
import org.springframework.batch.core.step.tasklet.TaskletStep;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.batch.support.PropertiesConverter;
|
||||
|
||||
/**
|
||||
@@ -254,6 +265,7 @@ public class SimpleJobOperatorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testFindRunningExecutionsNoSuchJob() throws Exception {
|
||||
jobParameters = new JobParameters();
|
||||
when(jobExplorer.findRunningJobExecutions("no-such-job")).thenReturn(Collections.EMPTY_SET);
|
||||
@@ -348,6 +360,67 @@ public class SimpleJobOperatorTests {
|
||||
assertEquals(BatchStatus.STOPPING, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopTasklet() throws Exception {
|
||||
JobInstance jobInstance = new JobInstance(123L, job.getName());
|
||||
JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters, null);
|
||||
StoppableTasklet tasklet = mock(StoppableTasklet.class);
|
||||
TaskletStep taskletStep = new TaskletStep();
|
||||
taskletStep.setTasklet(tasklet);
|
||||
MockJob job = new MockJob();
|
||||
job.taskletStep = taskletStep;
|
||||
|
||||
JobRegistry jobRegistry = mock(JobRegistry.class);
|
||||
TaskletStep step = mock(TaskletStep.class);
|
||||
|
||||
when(step.getTasklet()).thenReturn(tasklet);
|
||||
when(step.getName()).thenReturn("test_job.step1");
|
||||
when(jobRegistry.getJob(anyString())).thenReturn(job);
|
||||
when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution);
|
||||
|
||||
jobOperator.setJobRegistry(jobRegistry);
|
||||
jobExplorer.getJobExecution(111L);
|
||||
jobRepository.update(jobExecution);
|
||||
jobOperator.stop(111L);
|
||||
assertEquals(BatchStatus.STOPPING, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopTaskletException() throws Exception {
|
||||
JobInstance jobInstance = new JobInstance(123L, job.getName());
|
||||
JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters, null);
|
||||
StoppableTasklet tasklet = new StoppableTasklet() {
|
||||
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution,
|
||||
ChunkContext chunkContext) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
throw new IllegalStateException();
|
||||
}};
|
||||
TaskletStep taskletStep = new TaskletStep();
|
||||
taskletStep.setTasklet(tasklet);
|
||||
MockJob job = new MockJob();
|
||||
job.taskletStep = taskletStep;
|
||||
|
||||
JobRegistry jobRegistry = mock(JobRegistry.class);
|
||||
TaskletStep step = mock(TaskletStep.class);
|
||||
|
||||
when(step.getTasklet()).thenReturn(tasklet);
|
||||
when(step.getName()).thenReturn("test_job.step1");
|
||||
when(jobRegistry.getJob(anyString())).thenReturn(job);
|
||||
when(jobExplorer.getJobExecution(111L)).thenReturn(jobExecution);
|
||||
|
||||
jobOperator.setJobRegistry(jobRegistry);
|
||||
jobExplorer.getJobExecution(111L);
|
||||
jobRepository.update(jobExecution);
|
||||
jobOperator.stop(111L);
|
||||
assertEquals(BatchStatus.STOPPING, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbort() throws Exception {
|
||||
JobInstance jobInstance = new JobInstance(123L, job.getName());
|
||||
@@ -369,4 +442,25 @@ public class SimpleJobOperatorTests {
|
||||
jobRepository.update(jobExecution);
|
||||
jobOperator.abandon(123L);
|
||||
}
|
||||
|
||||
class MockJob extends AbstractJob {
|
||||
|
||||
private TaskletStep taskletStep;
|
||||
|
||||
@Override
|
||||
public Step getStep(String stepName) {
|
||||
return taskletStep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getStepNames() {
|
||||
return Arrays.asList("test_job.step1");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doExecute(JobExecution execution) throws JobExecutionException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,26 @@ public class SystemCommandTaskletIntegrationTests {
|
||||
tasklet.setWorkingDirectory(directory.getCanonicalPath());
|
||||
}
|
||||
|
||||
/*
|
||||
* test stopping a tasklet
|
||||
*/
|
||||
@Test
|
||||
public void testStopped() throws Exception {
|
||||
String command = System.getProperty("os.name").toLowerCase().indexOf("win") >= 0 ?
|
||||
"ping 1.1.1.1 -n 1 -w 5000" :
|
||||
"sleep 5";
|
||||
tasklet.setCommand(command);
|
||||
tasklet.setTerminationCheckInterval(10);
|
||||
tasklet.afterPropertiesSet();
|
||||
|
||||
StepContribution contribution = stepExecution.createStepContribution();
|
||||
//send stop
|
||||
tasklet.stop();
|
||||
tasklet.execute(contribution, null);
|
||||
|
||||
assertEquals(contribution.getExitStatus().getExitCode(),ExitStatus.STOPPED.getExitCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit code mapper containing mapping logic expected by the tests. 0 means
|
||||
* finished successfully, other value means failure.
|
||||
|
||||
Reference in New Issue
Block a user