RESOLVED - issue BATCH-1171: Interrupted step does not fail job.
Added check for STOPPED status in AbstractJob.
This commit is contained in:
@@ -254,7 +254,7 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
|
||||
|
||||
// The job was already stopped before we even got this far. Deal
|
||||
// with it in the same way as any other interruption.
|
||||
execution.setStatus(BatchStatus.FAILED);
|
||||
execution.setStatus(BatchStatus.STOPPED);
|
||||
execution.setExitStatus(ExitStatus.COMPLETED);
|
||||
|
||||
}
|
||||
@@ -346,7 +346,7 @@ public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, In
|
||||
|
||||
jobRepository.updateExecutionContext(execution);
|
||||
|
||||
if (currentStepExecution.getStatus() == BatchStatus.STOPPING) {
|
||||
if (currentStepExecution.getStatus() == BatchStatus.STOPPING || currentStepExecution.getStatus() == BatchStatus.STOPPED) {
|
||||
throw new JobInterruptedException("Job interrupted by step execution");
|
||||
}
|
||||
|
||||
|
||||
@@ -341,26 +341,13 @@ public class SimpleJobTests {
|
||||
"no steps configured") >= 0);
|
||||
}
|
||||
|
||||
// public void testNoStepsExecuted() throws Exception {
|
||||
// StepExecution completedExecution = new
|
||||
// StepExecution("completedExecution", jobExecution);
|
||||
// completedExecution.setStatus(BatchStatus.COMPLETED);
|
||||
//
|
||||
// job.execute(jobExecution);
|
||||
// ExitStatus exitStatus = jobExecution.getExitStatus();
|
||||
// assertEquals(ExitStatus.NOOP.getExitCode(), exitStatus.getExitCode());
|
||||
// assertTrue("Wrong message in execution: " + exitStatus,
|
||||
// exitStatus.getExitDescription().contains(
|
||||
// "steps already completed"));
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testNotExecutedIfAlreadyStopped() throws Exception {
|
||||
jobExecution.stop();
|
||||
job.execute(jobExecution);
|
||||
|
||||
assertEquals(0, list.size());
|
||||
checkRepository(BatchStatus.FAILED, ExitStatus.NOOP);
|
||||
checkRepository(BatchStatus.STOPPED, ExitStatus.NOOP);
|
||||
ExitStatus exitStatus = jobExecution.getExitStatus();
|
||||
assertEquals(ExitStatus.NOOP.getExitCode(), exitStatus.getExitCode());
|
||||
}
|
||||
@@ -454,7 +441,7 @@ public class SimpleJobTests {
|
||||
|
||||
assertNull("Second step was not supposed to be executed", step2.passedInStepContext);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetStepExists() {
|
||||
step1 = new StubStep("step1", jobRepository);
|
||||
@@ -546,7 +533,7 @@ public class SimpleJobTests {
|
||||
stepExecution.setExitStatus(ExitStatus.FAILED);
|
||||
stepExecution.setStatus(BatchStatus.FAILED);
|
||||
stepExecution.addFailureException(exception);
|
||||
throw (JobInterruptedException)exception;
|
||||
throw (JobInterruptedException) exception;
|
||||
}
|
||||
if (exception instanceof RuntimeException) {
|
||||
stepExecution.setExitStatus(ExitStatus.FAILED);
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.junit.Test;
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobInterruptedException;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.Step;
|
||||
@@ -38,7 +39,13 @@ import org.springframework.batch.core.job.flow.support.state.DecisionState;
|
||||
import org.springframework.batch.core.job.flow.support.state.EndState;
|
||||
import org.springframework.batch.core.job.flow.support.state.StepState;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.repository.dao.JobExecutionDao;
|
||||
import org.springframework.batch.core.repository.dao.MapExecutionContextDao;
|
||||
import org.springframework.batch.core.repository.dao.MapJobExecutionDao;
|
||||
import org.springframework.batch.core.repository.dao.MapJobInstanceDao;
|
||||
import org.springframework.batch.core.repository.dao.MapStepExecutionDao;
|
||||
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
|
||||
import org.springframework.batch.core.repository.support.SimpleJobRepository;
|
||||
import org.springframework.batch.core.step.StepSupport;
|
||||
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
|
||||
|
||||
@@ -53,15 +60,19 @@ public class FlowJobTests {
|
||||
private JobExecution jobExecution;
|
||||
|
||||
private JobRepository jobRepository;
|
||||
|
||||
|
||||
private boolean fail = false;
|
||||
|
||||
private JobExecutionDao jobExecutionDao;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MapJobRepositoryFactoryBean.clear();
|
||||
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
|
||||
factory.setTransactionManager(new ResourcelessTransactionManager());
|
||||
factory.afterPropertiesSet();
|
||||
jobExecutionDao = new MapJobExecutionDao();
|
||||
jobRepository = new SimpleJobRepository(new MapJobInstanceDao(), jobExecutionDao, new MapStepExecutionDao(), new MapExecutionContextDao());
|
||||
jobRepository = (JobRepository) factory.getObject();
|
||||
job.setJobRepository(jobRepository);
|
||||
jobExecution = jobRepository.createJobExecution("job", new JobParameters());
|
||||
@@ -181,6 +192,29 @@ public class FlowJobTests {
|
||||
assertEquals(BatchStatus.STOPPED, jobExecution.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterrupted() throws Exception {
|
||||
SimpleFlow flow = new SimpleFlow("job");
|
||||
List<StateTransition> transitions = new ArrayList<StateTransition>();
|
||||
transitions.add(StateTransition.createStateTransition(new StepState(new StubStep("step1") {
|
||||
@Override
|
||||
public void execute(StepExecution stepExecution) throws JobInterruptedException {
|
||||
stepExecution.setStatus(BatchStatus.STOPPING);
|
||||
jobRepository.update(stepExecution);
|
||||
}
|
||||
}), "end0"));
|
||||
transitions.add(StateTransition.createEndStateTransition(new EndState(FlowExecutionStatus.COMPLETED, "end0")));
|
||||
flow.setStateTransitions(transitions);
|
||||
flow.afterPropertiesSet();
|
||||
job.setFlow(flow);
|
||||
job.afterPropertiesSet();
|
||||
job.execute(jobExecution);
|
||||
assertEquals(BatchStatus.STOPPED, jobExecution.getStatus());
|
||||
checkRepository(BatchStatus.STOPPED, ExitStatus.STOPPED);
|
||||
assertEquals(1, jobExecution.getAllFailureExceptions().size());
|
||||
assertEquals(JobInterruptedException.class, jobExecution.getFailureExceptions().get(0).getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndStateStopped() throws Exception {
|
||||
SimpleFlow flow = new SimpleFlow("job");
|
||||
@@ -418,4 +452,15 @@ public class FlowJobTests {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void checkRepository(BatchStatus status, ExitStatus exitStatus) {
|
||||
// because map dao stores in memory, it can be checked directly
|
||||
JobInstance jobInstance = jobExecution.getJobInstance();
|
||||
JobExecution other = (JobExecution) jobExecutionDao.findJobExecutions(jobInstance).get(0);
|
||||
assertEquals(jobInstance.getId(), other.getJobId());
|
||||
assertEquals(status, other.getStatus());
|
||||
if (exitStatus != null) {
|
||||
assertEquals(exitStatus.getExitCode(), other.getExitStatus().getExitCode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -115,4 +115,3 @@ Export-Package: org.springframework.batch.item;version="0",org.springf
|
||||
support",org.springframework.batch.support.transaction;version="0";us
|
||||
es:="org.aopalliance.intercept,org.springframework.transaction,org.sp
|
||||
ringframework.transaction.support"
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<property name="dataSource" ref="dataSource"/>
|
||||
<property name="initScripts">
|
||||
<list>
|
||||
<value>${batch.drop.script}</value>
|
||||
<value>${batch.schema.script}</value>
|
||||
<value>${batch.business.schema.script}</value>
|
||||
</list>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.batch.sample.launch;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@@ -83,7 +84,7 @@ public class RemoteLauncherTests {
|
||||
assertTrue(launcher.getJobNames().contains("loopJob"));
|
||||
}
|
||||
|
||||
//@Test
|
||||
@Test
|
||||
public void testPauseJob() throws Exception {
|
||||
final int SLEEP_INTERVAL = 600;
|
||||
assertTrue(isConnected());
|
||||
@@ -100,18 +101,19 @@ public class RemoteLauncherTests {
|
||||
// assertEquals(0, launcher.getRunningExecutions("loopJob").size());
|
||||
logger.debug(launcher.getSummary(executionId));
|
||||
long resumedId = launcher.restart(executionId);
|
||||
assertEquals("Picked up the same execution after pause and resume", executionId, resumedId);
|
||||
assertNotSame("Picked up the same execution after pause and resume", executionId, resumedId);
|
||||
|
||||
Thread.sleep(SLEEP_INTERVAL);
|
||||
launcher.stop(executionId);
|
||||
launcher.stop(resumedId);
|
||||
Thread.sleep(SLEEP_INTERVAL);
|
||||
|
||||
// assertEquals(0, launcher.getRunningExecutions("loopJob").size());
|
||||
logger.debug(launcher.getSummary(executionId));
|
||||
long resumeId2 = launcher.restart(executionId);
|
||||
assertEquals("Picked up the same execution after pause and resume", executionId, resumeId2);
|
||||
logger.debug(launcher.getSummary(resumedId));
|
||||
long resumeId2 = launcher.restart(resumedId);
|
||||
assertNotSame("Picked up the same execution after pause and resume", executionId, resumeId2);
|
||||
|
||||
launcher.stop(executionId);
|
||||
Thread.sleep(SLEEP_INTERVAL);
|
||||
launcher.stop(resumeId2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
152
src/site/apt/migration/2.0-rc1-rc2.apt
Normal file
152
src/site/apt/migration/2.0-rc1-rc2.apt
Normal file
@@ -0,0 +1,152 @@
|
||||
Spring Batch 2.0.0.RC2 Release Notes
|
||||
|
||||
* Issues
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1165}BATCH-1165}} - Allow 'id' and 'ref' to exist together on <*-listener/>
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1164}BATCH-1164}} - Putting scope="step" on a listener causes failure
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1163}BATCH-1163}} - In Batch xsd, elements in <job/> should be unordered
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1162}BATCH-1162}} - In Batch xsd, elements in <split/> should be unordered
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1161}BATCH-1161}} - Throw error if a flow has no steps
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1160}BATCH-1160}} - In Batch xsd, stepType and flowStepType should be unordered
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1159}BATCH-1159}} - PROCESS_SKIP_COUNT seems not to ever get written to database
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1157}BATCH-1157}} - Add max count parameter to counting item readers
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1154}BATCH-1154}} - TaskletElementParser can't predict which StepFactoryBean to use
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1153}BATCH-1153}} - listener element should only have an "id" when defined at the top level
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1152}BATCH-1152}} - Allow comma and newline as delimiters in exception lists in namespace
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1151}BATCH-1151}} - Add IDE support to <retry-listeners/> in xsd
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1147}BATCH-1147}} - StepExecution getFilterCount always return 0
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1145}BATCH-1145}} - Conflicts if both <step/> and <tasklet/> have a "parent" attribute
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1144}BATCH-1144}} - Create top-level element <job-listener/>
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1143}BATCH-1143}} - Standalone <step/> should not be allowed to have "tasklet" attribute and <tasklet/> together
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1142}BATCH-1142}} - In the xsd, <listeners/> should be moved from "flowType" to "job"
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1141}BATCH-1141}} - Rename CompositeExecutionJobListener to CompositeJobExecutionListener
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1139}BATCH-1139}} - Add "parent" attribute to <tasklet/>
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1138}BATCH-1138}} - Add "parent" attribute to <job/>
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1136}BATCH-1136}} - Add setListeners(StepExecutionListener[]) to TaskletStep
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1135}BATCH-1135}} - Create top-level element <step-listener/>
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1134}BATCH-1134}} - Create a superclass for StepListenerParser and JobExecutionListenerParser
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1132}BATCH-1132}} - Add "parent" attribute to <step/>
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1131}BATCH-1131}} - It is not possible to set transaction-attributes for a tasklet step
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1130}BATCH-1130}} - Ensure Ordered is respected by generated listeners
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1129}BATCH-1129}} - Problems with exception classifications
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1128}BATCH-1128}} - Make sure WRITE_COUNT and ROLLBACK_COUNT are being updated correctly
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1127}BATCH-1127}} - Add contextual line number information for exceptions thrown by FlatFileItemReader
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1126}BATCH-1126}} - StepScope does not apply to twice nested inner beans
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1125}BATCH-1125}} - NoWorkFoundStepExecutionListener doesn't fail the step
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1124}BATCH-1124}} - Fix error message that occurs when the same annotation is used twice on one method
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1123}BATCH-1123}} - ExecutionContextPromotionListener may perform promotion multiple times
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1122}BATCH-1122}} - StaxEventWriter.startDocument() needs to be protected
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1121}BATCH-1121}} - Documentation should cover the 'no work found' scenario
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1120}BATCH-1120}} - Allow completion policy to be set on step
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1119}BATCH-1119}} - afterWrite() will only be called if an exception is raised during throttling
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1118}BATCH-1118}} - Listener annotation with wrong signature fails too late and too quietly
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1117}BATCH-1117}} - onWriteError should be called with only the bad item
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1116}BATCH-1116}} - Create section on MetaDataInstanceFactory in testing chapter
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1113}BATCH-1113}} - query for JdbcJobExecutionDao.findRunningJobExecutions is broken
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1112}BATCH-1112}} - Remove cycle in infrastructure database/support
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1111}BATCH-1111}} - ChunkListener called before WriteListener
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1110}BATCH-1110}} - Defer EntityManager flushing and clearing in JpaPagingItemReader
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1109}BATCH-1109}} - Generalise PrefixMatching* to PatternMatching*
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1108}BATCH-1108}} - Add composite ItemWriter/Processor based on Classifier
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1107}BATCH-1107}} - Fix Date conversion in PlaceholderTargetSource
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1106}BATCH-1106}} - SqlPagingQueryProviderFactoryBean ascending should default to true
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1105}BATCH-1105}} - Namespace error in documentation
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1104}BATCH-1104}} - Wrong stax version in spring-batch-parent-2.0.0.RC1.pom, is 1.2 should be 1.2.0
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1103}BATCH-1103}} - Add partioning sample
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1102}BATCH-1102}} - Classes with "listener" annotations should be auto-registered
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1101}BATCH-1101}} - Remove StepScope bean definition from samples that don't need it
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1099}BATCH-1099}} - Make writer in skip sample stateful
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1098}BATCH-1098}} - Check @AfterWrite is only called once per item
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1097}BATCH-1097}} - Add late binding to some io samples
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1096}BATCH-1096}} - Add late binding to some io samples
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1093}BATCH-1093}} - Make AbstractJobTests.makeUniqueJobParameters() public
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1092}BATCH-1092}} - Fix naming conventions for exit status in <end/>
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1091}BATCH-1091}} - Add strict flag to file readers (flat and XML).
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1072}BATCH-1072}} - Update docs to reflect attribute change in step element
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-1065}BATCH-1065}} - "BATCH-1011
|
||||
|
||||
* {{{http://jira.springframework.org/browse/Update documentation to explain end/fail/pause transitions"
|
||||
* {{{http://jira.springframework.org/browse/BATCH-976}BATCH-976}} - Provide automatic batch database schema installation utility
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-937}BATCH-937}} - Make sure JobRepository can be proxied
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-935}BATCH-935}} - Use NumberFormat when parsing real numbers
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-918}BATCH-918}} - Duplicate jar files in *-with-dependencies.zip
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-902}BATCH-902}} - Revise FAQ on web site
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-794}BATCH-794}} - Align with SpringSource Enterprise Repository
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-632}BATCH-632}} - Move Tasklet interface from core to infrastructure
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-573}BATCH-573}} - Delegating streams and listeners (e.g. HibernateAwareItemWriter) should delegate those interfaces to their delegates.
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-501}BATCH-501}} - Core and Infrastructure still have circular dependency
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-470}BATCH-470}} - RFC: Can all ExceptionHandlers be replaced by a combination of making Repeat/RetryListeners more robust and rewriting as Listeners?
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-394}BATCH-394}} - If FieldSet is an interface it needs a factory, otherwise existing clients are tied to specific implementations
|
||||
|
||||
* {{{http://jira.springframework.org/browse/BATCH-22}BATCH-22}} - Find alternative to ThreadLocal for RepeatSynchronizationManager
|
||||
Reference in New Issue
Block a user