title: Spring Boot 2.0 Quartz - Use non-primary datasource
body: <p>I used Quartz as scheduler in my application. Trying to use Spring boot 2.0 features. I have 2 different data sources in the configuration. One for application and another one for scheduler. How can I use non-primary data source (schedulerDataSource in this case) as data source for Quartz? Please help.</p>
  
  <p><strong><em>pom.xml</em></strong></p>
  
  <pre><code>    &lt;parent&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
          &lt;version&gt;2.0.0.RELEASE&lt;/version&gt;
      &lt;/parent&gt;
  
      &lt;dependencies&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter&lt;/artifactId&gt;
          &lt;/dependency&gt;       
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-jdbc&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-quartz&lt;/artifactId&gt;
          &lt;/dependency&gt;       
          &lt;dependency&gt;
              &lt;groupId&gt;com.oracle&lt;/groupId&gt;
              &lt;artifactId&gt;wlthint3client&lt;/artifactId&gt;
              &lt;version&gt;12.2.1.2&lt;/version&gt;
              &lt;scope&gt;system&lt;/scope&gt;
              &lt;systemPath&gt;C:/Oracle/products/mw_home/wlserver/server/lib/wlthint3client.jar&lt;/systemPath&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;com.oracle&lt;/groupId&gt;
              &lt;artifactId&gt;ojdbc&lt;/artifactId&gt;
              &lt;version&gt;7&lt;/version&gt;
              &lt;scope&gt;system&lt;/scope&gt;
              &lt;systemPath&gt;C:/Oracle/products/mw_home/oracle_common/modules/oracle.jdbc/ojdbc7.jar&lt;/systemPath&gt;
          &lt;/dependency&gt;       
      &lt;/dependencies&gt;
  </code></pre>
  
  <p><strong><em>application.yml</em></strong></p>
  
  <pre><code>spring:
    quartz:
      job-store-type: jdbc
      jdbc:
        initialize-schema: never
      properties:
        org:
          quartz:
            scheduler:
              instanceName: ETL
            threadPool:
              threadCount: 50
            jobStore:
              class: org.quartz.impl.jdbcjobstore.JobStoreTX
              driverDelegateClass: org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
              tablePrefix: QRTZ_ 
              useProperties: true
  
  scheduler:
    datasource:
      url: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXXXX)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XXXX)))
      username: scheduler
      password: XXXXXX
      driver-class-name: oracle.jdbc.OracleDriver
  
  t3:
    datasource:
      url: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXXXX)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XXXXXX)))
      username: app
      password: XXXXXX
      driver-class-name: oracle.jdbc.OracleDriver
  </code></pre>
  
  <p><strong><em>AppDataSource.java</em></strong></p>
  
  <pre><code>@Configuration
  public class AppDataSource 
  {
      @Bean
      @Primary
      @ConfigurationProperties("t3.datasource")
      public DataSourceProperties t3DataSourceProperties() 
      {
          return new DataSourceProperties();
      }
  
      @Bean
      @Primary
      @ConfigurationProperties("t3.datasource")
      public HikariDataSource t3DataSource() 
      {
          return t3DataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
      }
  
      @Bean
      @ConfigurationProperties("scheduler.datasource")
      public DataSourceProperties schedulerDataSourceProperties() 
      {
          return new DataSourceProperties();
      }
  
      @Bean
      @ConfigurationProperties("scheduler.datasource")
      public HikariDataSource schedulerDataSource() 
      {
          return schedulerDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
      }
  
      @Bean
      public PlatformTransactionManager schedulerTransactionManager()
      {
          final DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
          transactionManager.setDataSource(schedulerDataSource());
  
          return transactionManager;
      }
  }
  </code></pre>
  
  <p><strong><em>Application.java</em></strong></p>
  
  <pre><code>package com.aaa.t3.starter;
  
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
  import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
  import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
  import org.springframework.context.ApplicationContext;
  import org.springframework.context.annotation.ComponentScan;
  
  import com.spdji.aaa.jms.JmsService;
  
  @ComponentScan("com.aaa.t3")
  @SpringBootApplication(exclude = { ActiveMQAutoConfiguration.class, JmxAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
  public class Application
  {
      public static void main(String[] args) 
      {
          ApplicationContext context = SpringApplication.run(Application.class, args);
          JmsService jmsService = (JmsService) context.getBean("jmsService");
          jmsService.sendMessage();
  
          /*String[] beans = context.getBeanDefinitionNames();
          Arrays.stream(beans).sorted().forEach(System.out::println);*/
      }
  }
  </code></pre>
  
  <p>Tried to modify data source using SchedulerFactoryBeanCustomizer, but still it refers primary data source.</p>
  
  <pre><code>@Configuration
  public class SchedulerConfig 
  {
      private DataSource dataSource;
  
      @Autowired
      public SchedulerConfig(@Qualifier("schedulerDataSource") DataSource dataSource) 
      {
          this.dataSource = dataSource;
      }
  
      @Bean
      public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer() 
      {
          return bean -&gt; bean.setDataSource(dataSource);
      }
  }
  </code></pre>
  
  <p>Verified using debugger. Autowired data source in SchedulerConfig is scheduler data source, but it has been overridden after that. Added break point in QuartzAutoConfiguration.quartzDataSourceInitializer and checked the data source. This is not scheduler data source. This has been overridden by primary data source. Quartz auto configuration overrides SchedulerFactoryBeanCustomizer customization. I have opened <a href="https://github.com/spring-projects/spring-boot/issues/12780" rel="noreferrer">github.com/spring-projects/spring-boot/issues/12780</a> to fix it.</p>
  
  <p>This is a bug in spring-boot. As a workaround, I removed spring.quartz.job-store-type property and then configured DataSource and PlatformTransactionManager in customizer. Refer below updated code:</p>
  
  <pre><code>@Configuration
  public class SchedulerConfig 
  {
      private DataSource dataSource;
  
      private PlatformTransactionManager transactionManager;
  
      @Autowired
      public SchedulerConfig(@Qualifier("schedulerDataSource") DataSource dataSource, @Qualifier("schedulerTransactionManager") PlatformTransactionManager transactionManager) 
      {
          this.dataSource = dataSource;
          this.transactionManager = transactionManager;
      }
  
      @Bean
      public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer() 
      {
          return bean -&gt; 
          {
              bean.setDataSource(dataSource);
              bean.setTransactionManager(transactionManager);
          };
      }
  }
  </code></pre>