BATCH-2242: Stopping a job in STARTING state throws OptimisticLockingFailureException
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -23,4 +23,5 @@ s3.properties
|
||||
build
|
||||
.gradle
|
||||
pom.xml
|
||||
out
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2013 the original author or authors.
|
||||
* Copyright 2006-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -157,6 +157,8 @@ public class SimpleJobRepository implements JobRepository {
|
||||
Assert.notNull(jobExecution.getId(), "JobExecution must be already saved (have an id assigned).");
|
||||
|
||||
jobExecution.setLastUpdated(new Date(System.currentTimeMillis()));
|
||||
|
||||
jobExecutionDao.synchronizeStatus(jobExecution);
|
||||
jobExecutionDao.updateJobExecution(jobExecution);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.batch.core.repository.dao;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.launch.JobOperator;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class OptimisticLockingFailureTests {
|
||||
@Autowired
|
||||
private Job job;
|
||||
|
||||
@Autowired
|
||||
private JobLauncher jobLauncher;
|
||||
|
||||
@Autowired
|
||||
private JobOperator jobOperator;
|
||||
|
||||
@Test
|
||||
public void testAsyncStopOfStartingJob() throws Exception {
|
||||
JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder()
|
||||
.addLong("test", 1L)
|
||||
.toJobParameters());
|
||||
|
||||
jobOperator.stop(jobExecution.getId());
|
||||
|
||||
while(jobExecution.isRunning()) {
|
||||
// wait for async launched job to complete execution
|
||||
}
|
||||
|
||||
int numStepExecutions = jobExecution.getStepExecutions().size();
|
||||
StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next();
|
||||
String stepName = stepExecution.getStepName();
|
||||
BatchStatus stepExecutionStatus = stepExecution.getStatus();
|
||||
BatchStatus jobExecutionStatus = jobExecution.getStatus();
|
||||
|
||||
assertTrue("Should only be one StepExecution but got: " + numStepExecutions, numStepExecutions == 1);
|
||||
assertTrue("Step name for execution should be step1 but got: " + stepName, "step1".equals(stepName));
|
||||
assertTrue("Step execution status should be STOPPED but got: " + stepExecutionStatus, stepExecutionStatus.equals(BatchStatus.STOPPED));
|
||||
assertTrue("Job execution status should be STOPPED but got:" + jobExecutionStatus, jobExecutionStatus.equals(BatchStatus.STOPPED));
|
||||
|
||||
JobExecution restartJobExecution = jobLauncher.run(job, new JobParametersBuilder()
|
||||
.addLong("test", 1L)
|
||||
.toJobParameters());
|
||||
|
||||
while(restartJobExecution.isRunning()) {
|
||||
// wait for async launched job to complete execution
|
||||
}
|
||||
|
||||
int restartNumStepExecutions = restartJobExecution.getStepExecutions().size();
|
||||
assertTrue("Should be two StepExecution's on restart but got: " + restartNumStepExecutions, restartNumStepExecutions == 2);
|
||||
|
||||
for(StepExecution restartStepExecution : restartJobExecution.getStepExecutions()) {
|
||||
BatchStatus restartStepExecutionStatus = restartStepExecution.getStatus();
|
||||
|
||||
assertTrue("Step execution status should be COMPLETED but got: " + restartStepExecutionStatus,
|
||||
restartStepExecutionStatus.equals(BatchStatus.COMPLETED));
|
||||
}
|
||||
|
||||
BatchStatus restartJobExecutionStatus = restartJobExecution.getStatus();
|
||||
assertTrue("Job execution status should be COMPLETED but got:" + restartJobExecutionStatus,
|
||||
restartJobExecutionStatus.equals(BatchStatus.COMPLETED));
|
||||
}
|
||||
|
||||
public static class Writer implements ItemWriter<String> {
|
||||
@Override
|
||||
public void write(List<? extends String> items) throws Exception {
|
||||
for(String item : items) {
|
||||
System.out.println(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:batch="http://www.springframework.org/schema/batch"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/batch
|
||||
http://www.springframework.org/schema/batch/spring-batch.xsd">
|
||||
|
||||
<import resource="classpath:/org/springframework/batch/core/repository/dao/data-source-context.xml" />
|
||||
|
||||
<batch:job id="locking">
|
||||
<batch:step id="step1" next="step2">
|
||||
<batch:tasklet ref="tasklet"/>
|
||||
</batch:step>
|
||||
<batch:step id="step2">
|
||||
<batch:tasklet>
|
||||
<batch:chunk reader="itemReader" writer="itemWriter" commit-interval="5"/>
|
||||
</batch:tasklet>
|
||||
</batch:step>
|
||||
</batch:job>
|
||||
|
||||
<batch:job-repository/>
|
||||
|
||||
<bean id="tasklet" class="org.springframework.batch.core.configuration.xml.NoopTasklet"/>
|
||||
|
||||
<bean id="itemReader" class="org.springframework.batch.item.support.ListItemReader">
|
||||
<constructor-arg>
|
||||
<list>
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
<value>3</value>
|
||||
<value>4</value>
|
||||
<value>5</value>
|
||||
</list>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="itemWriter" class="org.springframework.batch.core.repository.dao.OptimisticLockingFailureTests$Writer"/>
|
||||
|
||||
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
|
||||
<property name="jobRepository" ref="jobRepository"/>
|
||||
<property name="taskExecutor">
|
||||
<bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
</bean>
|
||||
|
||||
<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry"/>
|
||||
|
||||
<bean id="jobOperator" class="org.springframework.batch.core.launch.support.SimpleJobOperator">
|
||||
<property name="jobLauncher" ref="jobLauncher"/>
|
||||
<property name="jobRepository" ref="jobRepository"/>
|
||||
<property name="jobExplorer" ref="jobExplorer"/>
|
||||
<property name="jobRegistry" ref="jobRegistry"/>
|
||||
</bean>
|
||||
</beans>
|
||||
Reference in New Issue
Block a user