1

I have a situation where I have to invoke the batch process and update the status of the job in my service layer. Here the JobRepositoryFactoryBean already consists of transaction manager so I should not annotate my service method with @Transactional, If I annotated I will get exception at runtime saying that "Existing transaction detected in job repository please fix and try again by removing @Transactional" If not annotated with @Transactional I am getting runtime exception saying that "no session found for current thread". Please help me in this to resolve it.

  • The use case sound wired to me. The job status should be managed by your flow and not by some service. Can you explain the Use case. Can you add your bean definition xml/Class – Haim Raman Jul 15 '14 at 10:53
  • I am sending email notification to a set of users using batch process, here before and after invoking batch job I have to update the status of job in DB where I had created separate table to maintain the status which contains some more info about job. Here the batch process is transactional but not the DB operation. – user2710786 Jul 15 '14 at 11:33

1 Answers1

0

Services should not interact directly with JobRepositoryFactoryBean or the Job Repository itself. It’s not recommend to use the JobRepository API outside the Spring Batch infrastructure.

The Database tables let you follow the execution of batch jobs and see what happens at both the job and step levels for more information see here. In case you think you need an additional data persisted about the job add your own table.

To update the status of the Job itself use the jobExecution.setExitStatus or jobExecution.setStatus API. Read about the difference bewteeb ExitStatus and BatchStatus here.

I suggest using a a job listener in your case. Job Listener are unlike tasklet or step listener are executed outside of the chunk’s transaction. See the following blog post here

@Component
public class JobMonitorListener {
    private static Log LOGGER = LogFactory.getLog(JobMonitorListener.class);
    
    @Autowired
    JobMonitorService monitorService;
    @BeforeJob
    public void beforeJob(JobExecution jobExecution){
        LOGGER.info("Before Job");
        monitorService.persistAddtionalData(date);
    }

    
    @AfterJob
    public void afterJob(JobExecution jobExecution){
        LOGGER.info("Afetr Job");
        monitorService.persistAddtionalData(date);
        jobExecution.setExitStatus(new ExitStatus("Failed by Monitor"));
        jobExecution.setStatus(BatchStatus.FAILED);
    }
}

The service:

@Component
public class JobMonitorServiceImpl implements JobMonitorService {
    
    @Transactional("transactionManager")
    public void persistAddtionalData(Object) {
    }
}

your job xml

<batch:job id="job">
        <batch:listeners >
        <batch:listener ref="jobMonitorListener"/>
        </batch:listeners>
...
</batch:job>

Make sure you are using a transaction manager different then the one used by the JobRepostory. See my answer here for more Transaction Issue with Spring Batch JobRepository in Unit Test

Anyway using @Transactional with Spring batch is tricky (see the comment Spring Batch. Call methods with rollbackFor by Michael Minella the project lead of Spring Batch).

Community
  • 1
  • 1
Haim Raman
  • 11,508
  • 6
  • 44
  • 70