Skip to content

EmptyResultDataAccessException in JobRepository.findRunningJobExecutions for a completed job executionΒ #5104

@A1exL

Description

@A1exL

Bug description
JobRepository.findRunningJobExecutions throws an EmptyResultDataAccessException if there are no running job executions for a given job name and BATCH_JOB_EXECUTION table contains only COMPLETED or FAILED records (BATCH_JOB_EXECUTION.STATUS column value).

Environment

  • Spring Boot 4.0.0
  • Spring Batch 6.0.0
  • Java 25
  • Embedded H2 database (reproduces on any database)

Steps to reproduce
Preconditions:
JdbcJobExecutionDao is used. BATCH_JOB_EXECUTION and BATCH_JOB_INSTANCE tables are empty.
Have Spring Batch Job with name "SuccessfulJob".

  1. Run this job, wait until it completes successfully.
    After execution one record in BATCH_JOB_INSTANCE table will be created.
    Also one record with STATUS=COMPLETED will be created in BATCH_JOB_EXECUTION table.
  2. call org.springframework.batch.core.repository.JobRepository.findRunningJobExecutions("SuccessfulJob")

Expected behavior
An empty set is returned.

Actual behavior
An EmptyResultDataAccessException is thrown.

Cause of the issue
Root cause of the issue is the code in JdbcJobExecutionDao.findRunningJobExecutions method:
This code fragment
getJdbcTemplate().queryForObject(getQuery(GET_RUNNING_EXECUTION_FOR_INSTANCE), Long.class, jobInstanceId)
fails if there are only COMPLETED (or FAILED) records in BATCH_JOB_EXECUTION table for a given jobInstanceId
Code in org.springframework.batch.core.repository.dao.jdbc.JdbcJobExecutionDao

private static final String GET_RUNNING_EXECUTION_FOR_INSTANCE = """
		SELECT E.JOB_EXECUTION_ID
		FROM %PREFIX%JOB_EXECUTION E, %PREFIX%JOB_INSTANCE I
		WHERE E.JOB_INSTANCE_ID=I.JOB_INSTANCE_ID AND I.JOB_INSTANCE_ID=? AND E.STATUS IN ('STARTING', 'STARTED', 'STOPPING')
		""";
		

public Set<JobExecution> findRunningJobExecutions(String jobName) {
	final Set<JobExecution> result = new HashSet<>();
	List<Long> jobInstanceIds = this.jobInstanceDao.getJobInstanceIds(jobName);
	for (long jobInstanceId : jobInstanceIds) {

		// throws EmptyResultDataAccessException if nothing is found
		long runningJobExecutionId = getJdbcTemplate().queryForObject(getQuery(GET_RUNNING_EXECUTION_FOR_INSTANCE),
				Long.class, jobInstanceId);

		JobExecution runningJobExecution = getJobExecution(runningJobExecutionId);
		result.add(runningJobExecution);
	}
	return result;
}

Minimal Complete Reproducible example
https://github.com/A1exL/spring-batch6-bugs
Please launch JobRepositoryTests and see the results

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions