3

My goal is to use Spring Batch with different instances of DataSource for my ItemWriter and the JobRepository respectively which should work like this.

Unfortunately the Spring container injects the primary datasource at a later stage which I can confirm via debugger. Here's my configuration:

@RunWith(SpringJUnit4ClassRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@SpringBootTest(classes = { BatchTest.DatabaseConfig.class, BatchTest.BatchTestConfig.class })
public class BatchTest {

    @Configuration
    static class DatabaseConfig {

        @Bean
        @Primary
        @ConfigurationProperties("spring.datasource")
        public DataSource primaryDataSource() {
            return DataSourceBuilder.create()
                    .build();
        }

        @Bean
        @ConfigurationProperties("spring.secondaryDatasource")
        public DataSource secondaryDataSource() {
            return DataSourceBuilder.create()
                    .build();
        }
    }

    @Configuration
    @EnableBatchProcessing
    static class BatchTestConfig {

        @Bean()
        BatchConfigurer configurer(@Qualifier("secondaryDataSource") DataSource dataSource) {
            return new DefaultBatchConfigurer(dataSource);
        }
    }
}

I reckon this is due to the setter-injection defined in

package org.springframework.batch.core.configuration.annotation;

@Component
public class DefaultBatchConfigurer implements BatchConfigurer {

    @Autowired(required = false)
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        this.transactionManager = new DataSourceTransactionManager(dataSource);
    }
}

So now I'm wondering how above mentioned SO response works or rather doesn't work in my case. Can I somehow disable the additional setter-injection on the provided bean?

Community
  • 1
  • 1
oschlueter
  • 2,596
  • 1
  • 23
  • 46
  • You could add `@Primary` annotation to `@Bean BatchConfigurer configurer(...){}` defines in `BatchTestConfig` – Nicolas Labrot Apr 25 '17 at 19:41
  • Thank you for the suggestion, unfortunately it yields the same result, i.e. the bean being created with the secondary datasource and an injection of the primary datasource later on. – oschlueter Apr 26 '17 at 08:53
  • Then try to override `DefaultBatchConfigurer#setDataSource` and add the qualifier. I would say too, with this configuration, you may have two beans of type `DefaultBatchConfigurer`. One by your configuration, the other by the `@Component` but only if component scan is configured with this package – Nicolas Labrot Apr 26 '17 at 08:57
  • Thank you, this worked although it feels rather odd. Feel free to post it as answer for me to accept. Regarding two beans, I'm confident that it is just one bean because I can confirm with the debugger that the setter-injection overwrites the previously specified `DataSource`. – oschlueter Apr 26 '17 at 09:34
  • does the setter injection method is called only once? – Nicolas Labrot Apr 26 '17 at 09:37
  • `DefaultBatchConfigurer#setDataSource` is called twice. The first call through the constructor caused by my config: ```public DefaultBatchConfigurer(DataSource dataSource) { setDataSource(dataSource); }``` and then a second call with the setter-injected bean. – oschlueter Apr 26 '17 at 09:41
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/142708/discussion-between-oschlueter-and-nicolas-labrot). – oschlueter Apr 26 '17 at 09:41

1 Answers1

4

Ttry to override DefaultBatchConfigurer#setDataSource and add the qualifier to the setDataSource method:

    @Bean()
    BatchConfigurer configurer(@Qualifier("secondaryDataSource") DataSource dataSource) {
        return new DefaultBatchConfigurer(dataSource) {

            @Autowired(required = false)
            public void setDataSource(@Qualifier("secondaryDataSource") DataSource dataSource) {
                super.setDataSource(dataSource);
            }
        };
    }

I agree it's a bit odd, but it's odd too that spring batch has such a constraint.

You could even try to override without any annotation at all. I don't remember if Spring searches annotation too in the class hiearchy.

Nicolas Labrot
  • 4,017
  • 25
  • 40