1
votes

Whenever I'm trying to run the job asynchronously, I'm getting this error

A job instance already exists and is complete for parameters={fileName=D:\experiment\31employeeCSVFile.csv}. If you want to run this job again, change the parameters.

Here is what I'm trying to do:

@Autowired
JobLauncher jobLauncher;

@Autowired
@Qualifier("importEmployeeJob")
Job job;

@RequestMapping("/jobLauncher")
    public ResponseEntity<String> handle() throws Exception {
        log.info("Rest request to handle()");

        Thread async = new Thread(new Runnable() {

            @Override
            public void run() {

                String fileLocation = "D:\\experiment\\31employeeCSVFile.csv";
                Map<String, JobParameter> JobParameters = new HashMap<String, JobParameter>();
                JobParameters.put("fileName", new JobParameter(fileLocation));
                try {
                    jobLauncher.run(job, new JobParameters(JobParameters));
                } catch (JobExecutionAlreadyRunningException | JobRestartException | JobInstanceAlreadyCompleteException
                        | JobParametersInvalidException e) {
                    e.printStackTrace();
                }
                log.info("success");
            }
        });
        log.info("Starting job...");
        async.start();
        return ResponseEntity.ok("Job started");
    }

Complete exception trace:

org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={fileName=D:\experiment\31employeeCSVFile.csv}. If you want to run this job again, change the parameters. at org.springframework.batch.core.repository.support.SimpleJobRepository.createJobExecution(SimpleJobRepository.java:131) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:181) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy63.createJobExecution(Unknown Source) at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:137) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy68.run(Unknown Source) at com.diatoz.demo.rest.EmployeeResource$1.run(EmployeeResource.java:61) at java.lang.Thread.run(Unknown Source)

At least for the first time it should run. What am I doing wrong?
One more thing to add that if I don't use runnable then everything works perfectly fine.

Update:
Following the error message, I tried by setting one more unique job parameter (i.e. Timestamp), and it ran. But It's still mystery to me that why it is denying to run even for the first time.

1
Hi, I just ran the same code as you and the first time it is working successfully for me. Can you add the full log here? Since started and the call to the API? maybe something helpful thereBrother
just off-topic now, maybe it is better as well to have an Async Launcher if that is what you want, instead of creating new threads manually each time. Either this: docs.spring.io/spring-batch/docs/current/reference/html/….Brother
@Brother, I have to set a unique job parameter (Timestamp) to run it asynchronously.Prajjwal Gupta
could you please share the full log, starting the service and from the API call as well. Maybe we find a clue in there. Like I mentioned, your example as it is worked the first call with success message. Maybe even run logs as debug to try to find tooBrother

1 Answers

1
votes

You should already have a job instance with that parameter in your db (probably created in your previous tests?). With a fresh db, you should not have this error in the first run, unless two requests come at the same time and try to create a job instance with the same parameter and one of them completes before the other tries to create a job instance.. (which is very unlikely to happen).

Apart from that, you should not be manually creating threads to start jobs asynchronously. What you need to do instead is configure your job launcher with an asynchronous TaskExecutor implementation instead. For more details about that, please refer to the Running Jobs from within a Web Container section.