7
votes

I'm testing Spring Batch using Spring boot. My need is to define jobs working on an Oracle Database but I don't want to save jobs and steps states inside this DB. I've read in the documentation I can use a in-memory repository with the MapJobRepositoryFactoryBean.

Then, I've implemented this bean:

@Bean
    public JobRepository jobRepository() {
        MapJobRepositoryFactoryBean factoryBean = new MapJobRepositoryFactoryBean(new ResourcelessTransactionManager());
        try {
            JobRepository jobRepository = factoryBean.getObject();
            return jobRepository;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

But when my job starts, the first thing Spring Batch does is to create the table in the Oracle DB and continues to use the Oracle datasource. It's like my JobRepository definition isn't taken account.

What did I miss ?

EDIT: I'm using Spring Boot 1.5.3 and Spring Batch 3.0.7

4
how does your JobLauncher configuration look like? How are you setting this repository to your jobLauncher - pvpkiran
Thanks! I didn't configure a JobLauncher bean. - ChriX

4 Answers

9
votes

A few things here:

  1. If you have a DataSource configured in your ApplicationContext, by default Spring Batch will try to use it.
  2. In order to not use a DataSource when one is available within the ApplicationContext, you'll need to create your own BatchConfigurer. You can do that by extending the DefaultBatchConfigurer.
  3. Don't use the MapJobRepository except only for testing purposes. I has a number of issues (thread safety, etc) and is not recommended for production use. Use an in memory database like HSQLDB instead (you'll still need to create your own BatchConfigurer to do so).
9
votes

With SpringBoot 2.x, the solution is simpler.

You have to extend the DefaultBatchConfigurer class like this:

@Component
public class NoPersistenceBatchConfigurer extends DefaultBatchConfigurer {
    @Override
    public void setDataSource(DataSource dataSource) {
    }
}

Without datasource, the framework automatically switches to use the MapJobRepository.

3
votes

Thank the comment of pvpkiran I've found my problem. It's necessary to define a JobLauncher bean.

Below an example:

@Bean
public JobRepository jobRepository() {
    MapJobRepositoryFactoryBean factoryBean = new MapJobRepositoryFactoryBean(new ResourcelessTransactionManager());
    try {
        JobRepository jobRepository = factoryBean.getObject();
        return jobRepository;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

@Bean
public JobLauncher jobLauncher(JobRepository jobRepository) {
    SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
    jobLauncher.setJobRepository(jobRepository);

    return jobLauncher;
}
0
votes

If using Spring Boot and @EnableBatchProcessing, you would extend the DefaultBatchConfigurer and override the createJobRepository method. Create a ResourcelessTransactionManager and JobRepository using MapJobRepositoryFactoryBean, the rest of the beans will be auto created by Spring Boot.

@Configuration
public class InMemoryBatchContextConfigurer extends DefaultBatchConfigurer {
    @Bean
    private ResourcelessTransactionManager resoucelessTransactionManager() {
        return new ResourcelessTransactionManager();
    }

    @Override
    protected JobRepository createJobRepository() throws Exception {
        MapJobRepositoryFactoryBean factoryBean = new MapJobRepositoryFactoryBean();
        factoryBean.setTransactionManager(resoucelessTransactionManager());
        return factoryBean.getObject();
    }
}`