spring-projects / spring-projects/spring-batch
Multiple jobs running with same parameters
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 3k
- Forks
- 2.5k
- Avg merge
- 6d 53m
- Merged PRs (30d)
- 3
Description
Bug description
I have multiple instances of the application running so the job gets triggered multiple times but I want only one job to actually run.
I have provided the same job parameters.
The time param is based on the hour but still I can see that 3 jobs are getting created and running at the time.
Also when the job fails I have a job operator restart logic which also fails with the error that 3 instance are running.
I have added the error log below.
Environment
<spring.boot.version>3.3.3</spring.boot.version>
<spring-core.version>6.1.12</spring-core.version>
<spring.batch.version>5.1.2</spring.batch.version>
Steps to reproduce
Code for launching the job-
lastJobExecution = launcher.run(job, jobParameters);
JobParameters jobParameters = new JobParametersBuilder()
.addLong("run.id", 1L)
.addString("TENANTID", tenantId)
.addString("MODE", mode)
.addString("PARAM_TIME", getCurrentTimeInHour())
.toJobParameters();
return jobParameters;
String getCurrentTimeInHour() {
LocalDateTime currentTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");
return currentTime.format(formatter);
}
@Bean(name = "JobRepository1")
public JobRepository jobRepository1() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(ds);
factory.setTransactionManager(transactionManager); [PlatformTransactionManager]
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean(name = "launcher1")
public JobLauncher jobLauncher() throws Exception {
TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
jobLauncher.setJobRepository(jobRepository1());
jobLauncher.setTaskExecutor(simpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
Errors faced-
{"msg":"Unexpected error running the task "{}"","level":"ERROR","written_ts":"1726852080036217710","logger":".jobs.TriggerFactory","exception_type":"java.lang.IllegalStateException","written_at":"2024-09-20T17:08:00.035Z","thread":"scheduling-1","type":"log","exception_message":"instance count must be 1 but was 3","stacktrace":["java.lang.IllegalStateException: instance count must be 1 but was 3","\tat org.springframework.util.Assert.state(Assert.java:76)","\tat org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.getJobInstance(JdbcJobInstanceDao.java:193)","\tat org.springframework.batch.core.repository.support.SimpleJobRepository.getLastJobExecution(SimpleJobRepository.java:299)","\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)","\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)","\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)","\tat java.base/java.lang.reflect.Method.invoke(Method.java:569)","\tat org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355)","\tat org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)","\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)","\tat org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)","\tat org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)","\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)","\tat org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)","\tat jdk.proxy2/jdk.proxy2.$Proxy140.getLastJobExecution(Unknown Source)","\tat org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:111)","\tat org.springframework.batch.core.launch.support.TaskExecutorJobLauncher.run(TaskExecutorJobLauncher.java:59)","\tat apim.anomaly.scheduling.jobs.TriggerTrainingFactory.buildTraining(TriggerTrainingFactory.java:117)","\tat apim.anomaly.scheduling.jobs.TriggerTrainingFactory.runTrainings(TriggerTrainingFactory.java:56)","\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)","\tat java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)","\tat java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)","\tat java.base/java.lang.reflect.Method.invoke(Method.java:569)","\tat org.springframework.scheduling.support.ScheduledMethodRunnable.runInternal(ScheduledMethodRunnable.java:130)","\tat org.springframework.scheduling.support.ScheduledMethodRunnable.lambda$run$2(ScheduledMethodRunnable.java:124)","\tat io.micrometer.observation.Observation.observe(Observation.java:499)","\tat org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:124)","\tat org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)","\tat org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:96)","\tat java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)","\tat java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)","\tat java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)","\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)","\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)","\tat java.base/java.lang.Thread.run(Thread.java:840)"]}
Images of the batch table-
Job name and tenant id is the same for all 3 jobs.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with JdbcJobInstanceDao.getJobInstance and SimpleJobRepository.getLastJobExecution in the stack trace, then review the custom JobRepository1 and launcher1 configuration and the TriggerTrainingFactory entry points. Reproduce concurrent launches using the shown parameters and verify that duplicate scheduling does not create multiple instances for the same job parameters.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring-boot
- Domain
- backend, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100