Search code examples
springspring-batch

Cannot resolve reference to bean 'dataSource' when upgrading spring batch from 4.3.x to 5.0.x


Currently I a working on migrating Spring Boot 2.7.x (Spring Batch 4.3.x) to Spring Boot 3.0.x (Spring Batch 5.0.x) with Mongo DB based Job repository

Custom Job repository and Transaction manager

@Configuration
public class MainBatchConfigurer  {

    @Autowired
    private ExecutionContextDao mongoExecutionContextDao;

    @Autowired
    private JobExecutionDao mongoJobExecutionDao;

    @Autowired
    private JobInstanceDao mongoJobInstanceDao;

    @Autowired
    private StepExecutionDao mongoStepExecutionDao;

    @Bean
    public JobRepository jobRepo() {
        return new SimpleJobRepository(mongoJobInstanceDao, mongoJobExecutionDao, mongoStepExecutionDao, mongoExecutionContextDao);
    }

    @Bean
    public PlatformTransactionManager getTransactionManager() {
        return new ResourcelessTransactionManager();
    }


    public TaskExecutorJobLauncher getJobLauncher() throws Exception {
        TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
        jobLauncher.setJobRepository(jobRepo());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }

    @Bean
    public JobExplorer getJobExplorer() {
        return new SimpleJobExplorer(mongoJobInstanceDao, mongoJobExecutionDao, mongoStepExecutionDao, mongoExecutionContextDao);
    }

}

Baseconfiguration

@Configuration
public class BaseConfiguration {

    @Autowired
    private JobRepository jobRepo;

    @Autowired
    private PlatformTransactionManager getTransactionManager;

    protected StepBuilder getStep(String stepName) {
        return new StepBuilder(stepName, jobRepo);
    }

    protected JobBuilder getJob(String jobName) {
        return new JobBuilder(jobName,jobRepo);
    }

}

Sample Job class

@Configuration
@EnableBatchProcessing
public class DepartmentJob extends BaseConfiguration {

@Autowired
        
private PlatformTransactionManager getTransactionManager;
// additional configuration
 
@Bean
public Step departmentMigrationStep() throws UnexpectedInputException, ParseException {

    return super.getStep("departmentMigrationStep ")
            .<xxx, yyy>chunk(10000,getTransactionManager)
            .reader(departmentPeekingReader())
            .processor(departmentProcessor())
            .writer(departmentWriter)
            .listener(genericItemReadListener)
            .listener(departmentSkipListener)
            .listener(genericStepExecutionListener)
            .listener(genericChunkListener)
            .build();
}
 
@Bean
public Job processDepartment() {
    return super.getJob("processDepartment")
            .incrementer(new RunIdIncrementer()).listener(deparmentJobListener())
            .start(departmentMigrationStep ())
            .build();
}

Test class

@RunWith(SpringRunner.class)
@SpringBootTest
@EnableBatchProcessing
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)

public class DepartmentTest {
@Autowired
private JobLauncher jobLauncher;

 
@Test
public void department_migration() throws Exception  {
 
JobExecution jobExecution = jobLauncher.run(xxx.processDepartment(), jobParameters);
}
}

When launch my job from test I get the below exception, for custom repository why datasource bean is required am I missing something here ?

    Unsatisfied dependency expressed through field 'jobRepo': Error creating bean with name 'jobRepository': Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:713)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:693)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:133)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:482)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1416)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:597)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:917)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:310)
    at org.springframework.boot.test.context.SpringBootContextLoader.lambda$loadContext$3(SpringBootContextLoader.java:137)
    at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:58)
    at org.springframework.util.function.ThrowingSupplier.get(ThrowingSupplier.java:46)
    at org.springframework.boot.SpringApplication.withHook(SpringApplication.java:1388)
    at org.springframework.boot.test.context.SpringBootContextLoader$ContextLoaderHook.run(SpringBootContextLoader.java:545)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:137)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:108)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:184)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:118)
    ... 25 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobRepository': Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:377)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:135)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1682)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:597)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1417)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1337)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:710)
    ... 50 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'dataSource' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:893)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:275)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:365)

When I start spring boot app, I get the below exception

    onfigReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobRepository': Cannot resolve reference to 



***************************
APPLICATION FAILED TO START
***************************

Description:

A component required a bean named 'dataSource' that could not be found.


Action:

Consider defining a bean named 'dataSource' in your configuration.

Solution

  • I got this issue fixed now. I had to remove @EnableBatchProcessing from all the Job classes and change batchconfigurer to extend DefaultBatchConfiguration like below

    @Configuration
    public class MainBatchConfigurer extends  DefaultBatchConfiguration  {
    
        @Autowired
        private ExecutionContextDao mongoExecutionContextDao;
    
        @Autowired
        private JobExecutionDao mongoJobExecutionDao;
    
        @Autowired
        private JobInstanceDao mongoJobInstanceDao;
    
        @Autowired
        private StepExecutionDao mongoStepExecutionDao;
    
    
        @Override
        public JobRepository jobRepository() {
            return new SimpleJobRepository(mongoJobInstanceDao, mongoJobExecutionDao, mongoStepExecutionDao, mongoExecutionContextDao);
        }
    
        @Override
        public PlatformTransactionManager getTransactionManager() {
            return new ResourcelessTransactionManager();
        }
    
        public TaskExecutorJobLauncher getJobLauncher() throws Exception {
            TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher();
            jobLauncher.setJobRepository(jobRepository());
            jobLauncher.afterPropertiesSet();
            return jobLauncher;
        }
    
        @Override
        public JobExplorer jobExplorer() {
            return new SimpleJobExplorer(mongoJobInstanceDao, mongoJobExecutionDao, mongoStepExecutionDao, mongoExecutionContextDao);
        }
    
    
    }