Skip to content

Commit e260bfe

Browse files
committed
Add status check in CommandLineJobOperator
Signed-off-by: Cheolhwan Ihn <[email protected]>
1 parent c6d9fa8 commit e260bfe

File tree

2 files changed

+69
-5
lines changed

2 files changed

+69
-5
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.springframework.batch.core.configuration.JobRegistry;
2323
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
2424
import org.springframework.batch.core.converter.JobParametersConverter;
25+
import org.springframework.batch.core.BatchStatus;
2526
import org.springframework.batch.core.job.Job;
2627
import org.springframework.batch.core.job.JobExecution;
2728
import org.springframework.batch.core.job.parameters.JobParameters;
@@ -52,6 +53,7 @@
5253
*
5354
* @author Mahmoud Ben Hassine
5455
* @author Yejeong Ham
56+
* @author Cheolhwan Ihn
5557
* @since 6.0
5658
*/
5759
public class CommandLineJobOperator {
@@ -185,7 +187,12 @@ public int restart(long jobExecutionId) {
185187
logger.error(() -> "No job execution found with ID: " + jobExecutionId);
186188
return JVM_EXITCODE_GENERIC_ERROR;
187189
}
188-
// TODO should check and log error if the job execution did not fail
190+
BatchStatus status = jobExecution.getStatus();
191+
if (status != BatchStatus.FAILED && status != BatchStatus.STOPPED) {
192+
logger.error(() -> "Cannot restart job execution " + jobExecutionId + ": current status is " + status
193+
+ " (must be FAILED or STOPPED).");
194+
return JVM_EXITCODE_GENERIC_ERROR;
195+
}
189196
JobExecution restartedExecution = this.jobOperator.restart(jobExecution);
190197
return this.exitCodeMapper.intValue(restartedExecution.getExitStatus().getExitCode());
191198
}
@@ -208,8 +215,12 @@ public int abandon(long jobExecutionId) {
208215
logger.error(() -> "No job execution found with ID: " + jobExecutionId);
209216
return JVM_EXITCODE_GENERIC_ERROR;
210217
}
211-
// TODO should throw JobExecutionNotStoppedException if the job execution is
212-
// not stopped
218+
BatchStatus status = jobExecution.getStatus();
219+
if (status != BatchStatus.STOPPED) {
220+
logger.error(() -> "Cannot abandon job execution " + jobExecutionId + ": current status is " + status
221+
+ " (must be STOPPED).");
222+
return JVM_EXITCODE_GENERIC_ERROR;
223+
}
213224
JobExecution abandonedExecution = this.jobOperator.abandon(jobExecution);
214225
return this.exitCodeMapper.intValue(abandonedExecution.getExitStatus().getExitCode());
215226
}

spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/CommandLineJobOperatorTests.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717

1818
import java.util.Properties;
1919

20+
import org.junit.jupiter.api.Assertions;
2021
import org.junit.jupiter.api.BeforeEach;
2122
import org.junit.jupiter.api.Test;
2223
import org.mockito.Mockito;
2324

25+
import org.springframework.batch.core.BatchStatus;
2426
import org.springframework.batch.core.configuration.JobRegistry;
2527
import org.springframework.batch.core.converter.JobParametersConverter;
2628
import org.springframework.batch.core.job.Job;
@@ -30,12 +32,14 @@
3032
import org.springframework.batch.core.repository.JobRepository;
3133

3234
import static org.mockito.Mockito.mock;
35+
import static org.springframework.batch.core.launch.support.ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR;
3336

3437
/**
3538
* Tests for {@link CommandLineJobOperator}.
3639
*
3740
* @author Mahmoud Ben Hassine
3841
* @author Yejeong Ham
42+
* @author Cheolhwan Ihn
3943
*/
4044
class CommandLineJobOperatorTests {
4145

@@ -111,6 +115,7 @@ void restart() throws Exception {
111115
// given
112116
long jobExecutionId = 1;
113117
JobExecution jobExecution = mock();
118+
Mockito.when(jobExecution.getStatus()).thenReturn(BatchStatus.FAILED);
114119

115120
// when
116121
Mockito.when(jobRepository.getJobExecution(jobExecutionId)).thenReturn(jobExecution);
@@ -121,19 +126,67 @@ void restart() throws Exception {
121126
}
122127

123128
@Test
124-
void abandon() throws Exception {
129+
void restartJobExecutionStopped() throws Exception {
125130
// given
126131
long jobExecutionId = 1;
127132
JobExecution jobExecution = mock();
133+
Mockito.when(jobExecution.getStatus()).thenReturn(BatchStatus.STOPPED);
134+
Mockito.when(jobRepository.getJobExecution(jobExecutionId)).thenReturn(jobExecution);
128135

129136
// when
137+
this.commandLineJobOperator.restart(jobExecutionId);
138+
139+
// then
140+
Mockito.verify(jobOperator).restart(jobExecution);
141+
}
142+
143+
@Test
144+
void restartJobExecutionNotFailed() throws Exception {
145+
// given
146+
long jobExecutionId = 1;
147+
JobExecution jobExecution = mock();
148+
Mockito.when(jobExecution.getStatus()).thenReturn(BatchStatus.COMPLETED);
130149
Mockito.when(jobRepository.getJobExecution(jobExecutionId)).thenReturn(jobExecution);
150+
151+
// when
152+
int exitCode = this.commandLineJobOperator.restart(jobExecutionId);
153+
154+
// then
155+
Assertions.assertEquals(JVM_EXITCODE_GENERIC_ERROR, exitCode);
156+
Mockito.verify(jobOperator, Mockito.never()).restart(jobExecution);
157+
}
158+
159+
@Test
160+
void abandon() throws Exception {
161+
// given
162+
long jobExecutionId = 1;
163+
JobExecution jobExecution = mock();
164+
Mockito.when(jobExecution.getStatus()).thenReturn(BatchStatus.STOPPED);
165+
Mockito.when(jobRepository.getJobExecution(jobExecutionId)).thenReturn(jobExecution);
166+
167+
// when
131168
this.commandLineJobOperator.abandon(jobExecutionId);
132169

133170
// then
134171
Mockito.verify(jobOperator).abandon(jobExecution);
135172
}
136173

174+
@Test
175+
void abandonJobExecutionNotStopped() throws Exception {
176+
// given
177+
long jobExecutionId = 1;
178+
JobExecution jobExecution = mock();
179+
Mockito.when(jobExecution.getStatus()).thenReturn(BatchStatus.COMPLETED);
180+
Mockito.when(jobRepository.getJobExecution(jobExecutionId)).thenReturn(jobExecution);
181+
182+
// when
183+
int exitCode = this.commandLineJobOperator.abandon(jobExecutionId);
184+
185+
// then
186+
Assertions.assertEquals(ExitCodeMapper.JVM_EXITCODE_GENERIC_ERROR, exitCode); // JVM_EXITCODE_GENERIC_ERROR
187+
Mockito.verify(jobOperator, Mockito.never()).abandon(jobExecution);
188+
}
189+
137190
@Test
138191
void recover() {
139192
// given
@@ -148,4 +201,4 @@ void recover() {
148201
Mockito.verify(jobOperator).recover(jobExecution);
149202
}
150203

151-
}
204+
}

0 commit comments

Comments
 (0)