Skip to content

Commit e5fbc2a

Browse files
committed
Fix job execution interruption process
Before this commit, stopping a job execution left its status in a STARTED status and its end time unset. This commit fixes that by making sure the job and step executions are marked as STOPPED and have a non-null end time value before updating their status in the job repository. Resolves #4023
1 parent bce9b19 commit e5fbc2a

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobOperator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.jspecify.annotations.NullUnmarked;
3131

3232
import org.springframework.batch.core.BatchStatus;
33+
import org.springframework.batch.core.ExitStatus;
3334
import org.springframework.batch.core.job.Job;
3435
import org.springframework.batch.core.job.JobExecution;
3536
import org.springframework.batch.core.job.JobInstance;
@@ -341,8 +342,12 @@ public boolean stop(JobExecution jobExecution) throws JobExecutionNotRunningExce
341342
if (logger.isInfoEnabled()) {
342343
logger.info("Stopping job execution: " + jobExecution);
343344
}
344-
jobExecution.setStatus(BatchStatus.STOPPING);
345+
jobExecution.setStatus(BatchStatus.STOPPING); // will be upgraded to STOPPED in
346+
// JobRepository.update
347+
jobExecution.setExitStatus(ExitStatus.STOPPED);
348+
jobExecution.setEndTime(LocalDateTime.now());
345349
jobRepository.update(jobExecution);
350+
jobRepository.updateExecutionContext(jobExecution);
346351

347352
Job job = jobRegistry.getJob(jobExecution.getJobInstance().getJobName());
348353
if (job != null) {
@@ -359,12 +364,16 @@ public boolean stop(JobExecution jobExecution) throws JobExecutionNotRunningExce
359364
if (tasklet instanceof StoppableTasklet stoppableTasklet) {
360365
StepSynchronizationManager.register(stepExecution);
361366
stoppableTasklet.stop(stepExecution);
367+
jobRepository.update(stepExecution);
368+
jobRepository.updateExecutionContext(stepExecution);
362369
StepSynchronizationManager.release();
363370
}
364371
}
365372
if (step instanceof StoppableStep stoppableStep) {
366373
StepSynchronizationManager.register(stepExecution);
367374
stoppableStep.stop(stepExecution);
375+
jobRepository.update(stepExecution);
376+
jobRepository.updateExecutionContext(stepExecution);
368377
StepSynchronizationManager.release();
369378
}
370379
}

spring-batch-core/src/main/java/org/springframework/batch/core/step/StoppableStep.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
*/
1616
package org.springframework.batch.core.step;
1717

18+
import java.time.LocalDateTime;
19+
20+
import org.springframework.batch.core.BatchStatus;
21+
import org.springframework.batch.core.ExitStatus;
22+
1823
/**
1924
* Extension of the {@link Step} interface to be implemented by steps that support being
2025
* stopped.
@@ -25,13 +30,17 @@
2530
public interface StoppableStep extends Step {
2631

2732
/**
28-
* Callback to signal the step to stop. The default implementation sets the
29-
* {@link StepExecution} to terminate only. Concrete implementations can override this
30-
* method to add custom stop logic.
33+
* Callback to signal the step to stop. The default implementation marks the
34+
* {@link StepExecution} as terminate only and set its status to stopped and its end
35+
* time to the current time. Concrete implementations can override this method to add
36+
* custom stop logic.
3137
* @param stepExecution the current step execution
3238
*/
3339
default void stop(StepExecution stepExecution) {
3440
stepExecution.setTerminateOnly();
41+
stepExecution.setStatus(BatchStatus.STOPPED);
42+
stepExecution.setExitStatus(ExitStatus.STOPPED);
43+
stepExecution.setEndTime(LocalDateTime.now());
3544
}
3645

3746
}

0 commit comments

Comments
 (0)