Skip to content

Commit 13ca0e0

Browse files
dimitrislifmbenhassine
authored andcommitted
Explicitly considering Start Time not being null for running Job Executions
This is to exclude from capturing erroneous Job Executions. An example is whenever a TaskRejectedException is thrown after submitting to the taskExecutor in SimpleJobLauncher#run(), the JobExecution is left without a Start or End Time. Also related tests are fixed. Resolves BATCH-2675
1 parent 1ebb8c3 commit 13ca0e0

File tree

11 files changed

+76
-21
lines changed

11 files changed

+76
-21
lines changed

spring-batch-core-tests/src/test/java/org/springframework/batch/core/test/repository/JdbcJobRepositoryTests.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2013 the original author or authors.
2+
* Copyright 2006-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
import java.io.Serializable;
1919
import java.sql.Timestamp;
2020
import java.util.ArrayList;
21+
import java.util.Date;
2122
import java.util.HashSet;
2223
import java.util.List;
2324
import java.util.Set;
@@ -204,6 +205,11 @@ public void run() {
204205

205206
try {
206207
JobExecution execution = repository.createJobExecution(job.getName(), new JobParameters());
208+
209+
//simulate running execution
210+
execution.setStartTime(new Date());
211+
repository.update(execution);
212+
207213
cacheJobIds(execution);
208214
list.add(execution);
209215
Thread.sleep(1000);

spring-batch-core/src/main/java/org/springframework/batch/core/JobExecution.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2017 the original author or authors.
2+
* Copyright 2006-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,6 +35,8 @@
3535
*
3636
* @author Lucas Ward
3737
* @author Michael Minella
38+
* @author Mahmoud Ben Hassine
39+
* @author Dimitrios Liapis
3840
*
3941
*/
4042
@SuppressWarnings("serial")
@@ -232,10 +234,10 @@ public StepExecution createStepExecution(String stepName) {
232234
* be noted that this does not necessarily mean that it has been persisted
233235
* as such yet.
234236
*
235-
* @return true if the end time is null
237+
* @return true if the end time is null and the start time is not null
236238
*/
237239
public boolean isRunning() {
238-
return endTime == null;
240+
return startTime != null && endTime == null;
239241
}
240242

241243
/**

spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2013 the original author or authors.
2+
* Copyright 2006-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,6 +58,8 @@
5858
* @author Dave Syer
5959
* @author Robert Kasanicky
6060
* @author Michael Minella
61+
* @author Mahmoud Ben Hassine
62+
* @author Dimitrios Liapis
6163
*/
6264
public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements JobExecutionDao, InitializingBean {
6365

@@ -83,7 +85,7 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements
8385
+ " from %PREFIX%JOB_EXECUTION where JOB_EXECUTION_ID = ?";
8486

8587
private static final String GET_RUNNING_EXECUTIONS = "SELECT E.JOB_EXECUTION_ID, E.START_TIME, E.END_TIME, E.STATUS, E.EXIT_CODE, E.EXIT_MESSAGE, E.CREATE_TIME, E.LAST_UPDATED, E.VERSION, "
86-
+ "E.JOB_INSTANCE_ID, E.JOB_CONFIGURATION_LOCATION from %PREFIX%JOB_EXECUTION E, %PREFIX%JOB_INSTANCE I where E.JOB_INSTANCE_ID=I.JOB_INSTANCE_ID and I.JOB_NAME=? and E.END_TIME is NULL order by E.JOB_EXECUTION_ID desc";
88+
+ "E.JOB_INSTANCE_ID, E.JOB_CONFIGURATION_LOCATION from %PREFIX%JOB_EXECUTION E, %PREFIX%JOB_INSTANCE I where E.JOB_INSTANCE_ID=I.JOB_INSTANCE_ID and I.JOB_NAME=? and E.START_TIME is not NULL and E.END_TIME is NULL order by E.JOB_EXECUTION_ID desc";
8789

8890
private static final String CURRENT_VERSION_JOB_EXECUTION = "SELECT VERSION FROM %PREFIX%JOB_EXECUTION WHERE JOB_EXECUTION_ID=?";
8991

spring-batch-core/src/test/java/org/springframework/batch/core/JobExecutionTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2014 the original author or authors.
2+
* Copyright 2006-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
3030

3131
/**
3232
* @author Dave Syer
33+
* @author Dimitrios Liapis
3334
*
3435
*/
3536
public class JobExecutionTests {
@@ -65,6 +66,7 @@ public void testGetJobConfigurationName() {
6566
*/
6667
@Test
6768
public void testIsRunning() {
69+
execution.setStartTime(new Date());
6870
assertTrue(execution.isRunning());
6971
execution.setEndTime(new Date(100L));
7072
assertFalse(execution.isRunning());
@@ -76,6 +78,7 @@ public void testIsRunning() {
7678
*/
7779
@Test
7880
public void testIsRunningWithStoppedExecution() {
81+
execution.setStartTime(new Date());
7982
assertTrue(execution.isRunning());
8083
execution.stop();
8184
assertTrue(execution.isRunning());

spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/MapJobExplorerFactoryBeanTests.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2014 the original author or authors.
2+
* Copyright 2010-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,11 +18,14 @@
1818
import static org.junit.Assert.assertEquals;
1919

2020
import org.junit.Test;
21+
import org.springframework.batch.core.JobExecution;
2122
import org.springframework.batch.core.JobParameters;
2223
import org.springframework.batch.core.explore.JobExplorer;
23-
import org.springframework.batch.core.explore.support.MapJobExplorerFactoryBean;
24+
import org.springframework.batch.core.repository.JobRepository;
2425
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
2526

27+
import java.util.Date;
28+
2629
/**
2730
* Tests for {@link MapJobExplorerFactoryBean}.
2831
*/
@@ -36,8 +39,13 @@ public class MapJobExplorerFactoryBeanTests {
3639
public void testCreateExplorer() throws Exception {
3740

3841
MapJobRepositoryFactoryBean repositoryFactory = new MapJobRepositoryFactoryBean();
39-
repositoryFactory.getObject().createJobExecution("foo", new JobParameters());
40-
42+
JobRepository jobRepository = repositoryFactory.getObject();
43+
JobExecution jobExecution = jobRepository.createJobExecution("foo", new JobParameters());
44+
45+
//simulating a running job execution
46+
jobExecution.setStartTime(new Date());
47+
jobRepository.update(jobExecution);
48+
4149
MapJobExplorerFactoryBean tested = new MapJobExplorerFactoryBean(repositoryFactory);
4250
tested.afterPropertiesSet();
4351

spring-batch-core/src/test/java/org/springframework/batch/core/jsr/launch/JsrJobOperatorTests.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2017 the original author or authors.
2+
* Copyright 2013-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -74,6 +74,9 @@
7474
import static org.mockito.Mockito.verify;
7575
import static org.mockito.Mockito.when;
7676

77+
/**
78+
* Tests for {@link JsrJobOperator}.
79+
*/
7780
public class JsrJobOperatorTests extends AbstractJsrTestCase {
7881

7982
private JobOperator jsrJobOperator;
@@ -210,6 +213,8 @@ public void testAbandonNoSuchJob() throws Exception {
210213
@Test(expected=JobExecutionIsRunningException.class)
211214
public void testAbandonJobRunning() throws Exception {
212215
JobExecution jobExecution = new JobExecution(5L);
216+
jobExecution.setStartTime(new Date(1L));
217+
213218
when(jobExplorer.getJobExecution(5L)).thenReturn(jobExecution);
214219

215220
jsrJobOperator.abandon(5L);

spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2014 the original author or authors.
2+
* Copyright 2008-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,6 +39,9 @@
3939
import static org.junit.Assert.assertTrue;
4040
import static org.junit.Assert.fail;
4141

42+
/**
43+
* Parent Test Class for {@link JdbcJobExecutionDao} and {@link MapJobExecutionDao}.
44+
*/
4245
public abstract class AbstractJobExecutionDaoTests {
4346

4447
protected JobExecutionDao dao;
@@ -194,14 +197,24 @@ public void testGetMissingLastExecution() {
194197
@Transactional
195198
@Test
196199
public void testFindRunningExecutions() {
197-
200+
//Normally completed JobExecution as EndTime is populated
198201
JobExecution exec = new JobExecution(jobInstance, jobParameters);
199202
exec.setCreateTime(new Date(0));
200-
exec.setEndTime(new Date(1L));
203+
exec.setStartTime(new Date(1L));
204+
exec.setEndTime(new Date(2L));
205+
exec.setLastUpdated(new Date(5L));
206+
dao.saveJobExecution(exec);
207+
208+
//BATCH-2675
209+
//Abnormal JobExecution as both StartTime and EndTime are null
210+
//This can occur when SimpleJobLauncher#run() submission to taskExecutor throws a TaskRejectedException
211+
exec = new JobExecution(jobInstance, jobParameters);
201212
exec.setLastUpdated(new Date(5L));
202213
dao.saveJobExecution(exec);
203214

215+
//Running JobExecution as StartTime is populated but EndTime is null
204216
exec = new JobExecution(jobInstance, jobParameters);
217+
exec.setStartTime(new Date(2L));
205218
exec.setLastUpdated(new Date(5L));
206219
exec.createStepExecution("step");
207220
dao.saveJobExecution(exec);

spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -73,6 +73,8 @@ public void testAsyncStopOfStartingJob() throws Exception {
7373
.addLong("test", 1L)
7474
.toJobParameters());
7575

76+
Thread.sleep(1000);
77+
7678
while(restartJobExecution.isRunning()) {
7779
// wait for async launched job to complete execution
7880
}

spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/MapJobRepositoryFactoryBeanTests.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2014 the original author or authors.
2+
* Copyright 2008-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,11 +17,14 @@
1717

1818
import org.junit.Test;
1919
import org.springframework.batch.core.Job;
20+
import org.springframework.batch.core.JobExecution;
2021
import org.springframework.batch.core.JobParameters;
2122
import org.springframework.batch.core.job.JobSupport;
2223
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
2324
import org.springframework.batch.core.repository.JobRepository;
2425

26+
import java.util.Date;
27+
2528
import static org.junit.Assert.fail;
2629

2730
/**
@@ -42,7 +45,11 @@ public void testCreateRepository() throws Exception {
4245
Job job = new JobSupport("jobName");
4346
JobParameters jobParameters = new JobParameters();
4447

45-
repository.createJobExecution(job.getName(), jobParameters);
48+
JobExecution jobExecution = repository.createJobExecution(job.getName(), jobParameters);
49+
50+
// simulate a running execution
51+
jobExecution.setStartTime(new Date());
52+
repository.update(jobExecution);
4653

4754
try {
4855
repository.createJobExecution(job.getName(), jobParameters);

spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2014 the original author or authors.
2+
* Copyright 2008-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
4343
* Repository tests using JDBC DAOs (rather than mocks).
4444
*
4545
* @author Robert Kasanicky
46+
* @author Dimitrios Liapis
4647
*/
4748
@RunWith(SpringJUnit4ClassRunner.class)
4849
@ContextConfiguration(locations = "/org/springframework/batch/core/repository/dao/sql-dao-test.xml")
@@ -180,7 +181,11 @@ public void testSaveExecutionContext() throws Exception {
180181
@Test
181182
public void testOnlyOneJobExecutionAllowedRunning() throws Exception {
182183
job.setRestartable(true);
183-
jobRepository.createJobExecution(job.getName(), jobParameters);
184+
JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);
185+
186+
//simulating a running job execution
187+
jobExecution.setStartTime(new Date());
188+
jobRepository.update(jobExecution);
184189

185190
try {
186191
jobRepository.createJobExecution(job.getName(), jobParameters);

spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2014 the original author or authors.
2+
* Copyright 2006-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@
5555
*
5656
* @author Lucas Ward
5757
* @author Will Schipp
58+
* @author Dimitrios Liapis
5859
*
5960
*/
6061
public class SimpleJobRepositoryTests {
@@ -240,6 +241,7 @@ public void testIsJobInstanceTrue() throws Exception {
240241
@Test(expected = JobExecutionAlreadyRunningException.class)
241242
public void testCreateJobExecutionAlreadyRunning() throws Exception {
242243
jobExecution.setStatus(BatchStatus.STARTED);
244+
jobExecution.setStartTime(new Date());
243245
jobExecution.setEndTime(null);
244246

245247
when(jobInstanceDao.getJobInstance("foo", new JobParameters())).thenReturn(jobInstance);

0 commit comments

Comments
 (0)