web-dev-qa-db-ja.com

Spring Boot 2.0 Quartz-非プライマリデータソースを使用する

私のアプリケーションでは、Quartzをスケジューラーとして使用しました。 Spring boot 2.0機能を使用しようとしています。構成に2つの異なるデータソースがあります。 1つはアプリケーション用、もう1つはスケジューラ用です。 Quartzのデータソースとしてプライマリ以外のデータソース(この場合はschedulerDataSource)を使用するにはどうすればよいですか?助けてください。

pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>       
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>       
        <dependency>
            <groupId>com.Oracle</groupId>
            <artifactId>wlthint3client</artifactId>
            <version>12.2.1.2</version>
            <scope>system</scope>
            <systemPath>C:/Oracle/products/mw_home/wlserver/server/lib/wlthint3client.jar</systemPath>
        </dependency>
        <dependency>
            <groupId>com.Oracle</groupId>
            <artifactId>ojdbc</artifactId>
            <version>7</version>
            <scope>system</scope>
            <systemPath>C:/Oracle/products/mw_home/Oracle_common/modules/Oracle.jdbc/ojdbc7.jar</systemPath>
        </dependency>       
    </dependencies>

application.yml

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

AppDataSource.Java

@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;
    }
}

Application.Java

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);*/
    }
}

SchedulerFactoryBeanCustomizerを使用してデータソースを変更しようとしましたが、それでもプライマリデータソースを参照しています。

@Configuration
public class SchedulerConfig 
{
    private DataSource dataSource;

    @Autowired
    public SchedulerConfig(@Qualifier("schedulerDataSource") DataSource dataSource) 
    {
        this.dataSource = dataSource;
    }

    @Bean
    public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer() 
    {
        return bean -> bean.setDataSource(dataSource);
    }
}

デバッガーを使用して確認済み。 SchedulerConfigの自動配線データソースはスケジューラデータソースですが、その後オーバーライドされました。 QuartzAutoConfiguration.quartzDataSourceInitializerにブレークポイントを追加し、データソースを確認しました。これはスケジューラデータソースではありません。これは、プライマリデータソースによってオーバーライドされました。 Quartz自動構成は、SchedulerFactoryBeanCustomizerのカスタマイズをオーバーライドします。 github.com/spring-projects/spring-boot/issues/1278 を開いて修正しました。

これはスプリングブートのバグです。回避策として、spring.quartz.job-store-typeプロパティを削除し、カスタマイザでDataSourceおよびPlatformTransactionManagerを構成しました。以下の更新されたコードを参照してください:

@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 -> 
        {
            bean.setDataSource(dataSource);
            bean.setTransactionManager(transactionManager);
        };
    }
}
8
user1020455

これはスプリングブートのバグです。回避策として、spring.quartz.job-store-typeプロパティを削除し、カスタマイザでDataSourceおよびPlatformTransactionManagerを構成しました。以下の更新されたコードを参照してください。

@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 -> 
        {
            bean.setDataSource(dataSource);
            bean.setTransactionManager(transactionManager);
        };
    }
}
3
user1020455

SchedulerFactoryBeanを自分でビルドして、データソースをカスタマイズできます。

@Bean
public SchedulerFactoryBean schedulerFactory() {
    SchedulerFactoryBean bean = new SchedulerFactoryBean();
    bean.setDataSource(schedulerDataSource());
    return bean;
}

または、Spring Boot 2ではSchedulerFactoryBeanCustomizerを使用できます。これにより、自動構成機能によってインスタンス化されたBeanをカスタマイズできます。

@Configuration
public class SchedulerConfig {
    DataSource dataSource;

    @Autowired
    public SchedulerConfig(@Qualifier("scheduler.datasource") DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Bean
    public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer()
    {
        return bean -> bean.setDataSource(dataSource);
    }
}
2
teppic