Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start a spring batch job when already within a transaction

I have simple Spring-Service that (among other tasks) starts a spring batch job with the following code:

@Autowired
private JobRegistry jobRegistry;

@Autowired
private JobLauncher jobLauncher;

public void startMyJob() {
    Job job = jobRegistry.getJob("myJobName");
    JobParameters jobParameters = new JobParametersBuilder().toJobParameters();
    jobLauncher.run(job, jobParameters);
}

This works fine, as long as there is no transaction active when the Serivce-Method is called. However, with an active transaction, I get this exception:

Caused by: java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).

I cannot easily remove the existing transaction, since it is implied due to some framework code that is not within my reach.

So, how can I start the job anyway within this context? The new job just should not use the existing transaction. It could just start its own transaction - but how to configure it to make it work?

like image 515
Jack Avatar asked Aug 08 '13 11:08

Jack


People also ask

Is it possible to restart a completed job in Spring Batch?

By default, it does not allow completed jobs to be restarted. When a job is restarted, Spring Batch will create a new job execution for the particular job instance that failed, and it will restart at the failed step, executing from that point forward.

Can a Spring Batch have multiple jobs?

Multiple jobs can be run simultaneously. There are two main types of Spring Batch Parallel Processing: Single Process, Multi-threaded, or Multi-process. These are also divided into subcategories, as follows: Multi-threaded Step (Step with many threads, single process)

How does Spring Batch handle transactions?

Spring Batch handles transactions at the step level. This means that Spring Batch will never use only one transaction for a whole job (unless the job has a single step). Remember that you're likely to implement a Spring Batch job in one of two ways: using a tasklet or using a chunk-oriented step.


1 Answers

I had a similar problem. In particular, I was starting my jobs from within a class that was annotated with @Transactional(propagation = Propagation.REQUIRES_NEW). To work around this, I started my jobs from a somewhere, where I had no active transaction. Then I ran into your problem as described above - and here is how I solved it:

set validateTransactionStateto false on the JobRepository - it now ignored the transactions that were automatically created in the class my ItemProcessor called (because said class was annotated with @Transcational, as explained above).

This made my jobs run just fine. However, I wasn't sure if I was now dealing with 2 open transactions and wanted to be sure I was not. So I also removed the transcational annnotation on the class level and moved it to all public methods, except the ones called by my Itemprocessor. Thus I solved the issue.

like image 194
Schaka Avatar answered Sep 25 '22 12:09

Schaka