Skip to content

Inaccurate exception message when attempting to start a running job #5280

@fmbenhassine

Description

@fmbenhassine

Currently, when a JobExecutionAlreadyRunningException happens, the message of the exception is inaccurate. It shows the job instance details instead of the job execution details.

package org.springframework.batch.samples.helloworld;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.job.Job;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.job.parameters.JobParameters;
import org.springframework.batch.core.job.parameters.JobParametersBuilder;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.Step;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.infrastructure.repeat.RepeatStatus;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;

@Configuration
@EnableBatchProcessing
public class HelloWorldJobConfiguration {

	public static void main(String[] args) throws Exception {
		ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldJobConfiguration.class);
		JobOperator jobOperator = context.getBean(JobOperator.class);
		Job job = context.getBean(Job.class);
		JobParameters parameters = new JobParametersBuilder().addString("name", "foo").toJobParameters();
		jobOperator.start(job, parameters);

		// attempt to start the same job instance, which should fail with JobExecutionAlreadyRunningException
		jobOperator.start(job, parameters);
	}

	@Bean
	public Step step(JobRepository jobRepository) {
		return new StepBuilder(jobRepository).tasklet((contribution, chunkContext) -> {
			Thread.sleep(5000);
			System.out.println("Hello world!");
			return RepeatStatus.FINISHED;
		}).build();
	}

	@Bean
	public Job job(JobRepository jobRepository, Step step) {
		return new JobBuilder(jobRepository).start(step).build();
	}

	@Bean
	public TaskExecutor taskExecutor() {
		return new SimpleAsyncTaskExecutor("batch-worker-");
	}

}

prints:

08:17:24.110 [batch-worker-1] INFO  o.s.b.c.l.s.TaskExecutorJobLauncher - Job: [SimpleJob: [name=job]] launched with the following parameters: [{JobParameter{name='name', value=foo, type=class java.lang.String, identifying=true}}]
08:17:24.115 [batch-worker-1] INFO  o.s.batch.core.job.SimpleStepHandler - Executing step: [step]
Exception in thread "main" org.springframework.batch.core.launch.JobExecutionAlreadyRunningException: A job execution for this job is already running: JobExecution: id=1, version=null, startTime=2026-02-12T08:17:24.115279, endTime=null, lastUpdated=2026-02-12T08:17:24.115295, status=STARTED, exitStatus=exitCode=UNKNOWN;exitDescription=, job=[JobInstance: id=1, version=null, Job=[job]], jobParameters=[{JobParameter{name='name', value=foo, type=class java.lang.String, identifying=true}}]
	at org.springframework.batch.core.launch.support.TaskExecutorJobLauncher.createJobExecution(TaskExecutorJobLauncher.java:136)
	at org.springframework.batch.core.launch.support.TaskExecutorJobLauncher.run(TaskExecutorJobLauncher.java:108)
	at org.springframework.batch.core.launch.support.SimpleJobOperator.start(SimpleJobOperator.java:201)
	at org.springframework.batch.core.launch.support.TaskExecutorJobOperator.start(TaskExecutorJobOperator.java:117)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:158)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:133)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:371)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:130)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:222)
	at jdk.proxy2/jdk.proxy2.$Proxy16.start(Unknown Source)
	at org.springframework.batch.samples.helloworld.HelloWorldJobConfiguration.main(HelloWorldJobConfiguration.java:46)
Hello world!
08:17:29.127 [batch-worker-1] INFO  o.s.batch.core.step.AbstractStep - Step: [step] executed in 5s10ms
08:17:29.129 [batch-worker-1] INFO  o.s.b.c.l.s.TaskExecutorJobLauncher - Job: [SimpleJob: [name=job]] completed with the following parameters: [{JobParameter{name='name', value=foo, type=class java.lang.String, identifying=true}}] and the following status: [COMPLETED] in 5s12ms

This code should be updated to pass the running job execution instead of the job instance.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions