Quartz JDBCJobStore with RoutingDataSource

时间:2017-01-03 07:06:37

标签: spring quartz-scheduler

对于我的应用,我们正在使用弹簧 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource

根据请求的域URL配置和选择目标dataSource。

    Eg: 

    qa.example.com ==> target datasource = DB1
    qa-test.example.com ==> target datasource = DB2

以下是相同

的配置
@Bean(name = "dataSource")
    public DataSource dataSource() throws PropertyVetoException, ConfigurationException {
        EERoutingDatabase routingDB = new EERoutingDatabase();

        Map<Object, Object> targetDataSources = datasourceList();
        routingDB.setTargetDataSources(targetDataSources);

        return routingDB;
    }

public class EERoutingDatabase extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        // This is derived from the request's URL/Domain
        return SessionUtil.getDataSourceHolder();
    }
}

该任务现在使用Quartz JDBCJobStore存储quartz jobs / triggers。

首选选项是使用JobStoreCMT。

我们使用了以下配置

@Configuration
public class QuartzConfig {
    private static final Logger LOG = LoggerFactory.getLogger(QuartzConfig.class);
    private static final String QUARTZ_CONFIG_FILE = "ee-quartz.properties";


    @Autowired
    private DataSource dataSource;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
   private ApplicationContext applicationContext;

    /**
     * Spring wrapper over Quartz Scheduler bean
     */
    @Bean(name="quartzRealTimeScheduler")
    SchedulerFactoryBean schedulerFactoryBean() {
        LOG.info("Creating QUARTZ Scheduler for real time Job invocation");
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setConfigLocation(new ClassPathResource(QUARTZ_CONFIG_FILE));
        factory.setDataSource(dataSource);
        factory.setTransactionManager(transactionManager);
        factory.setJobFactory(springBeanJobFactory());
        factory.setWaitForJobsToCompleteOnShutdown(true);
        factory.setApplicationContextSchedulerContextKey("applicationContext");
        return factory;
    }

    @Bean
    public SpringBeanJobFactory springBeanJobFactory() {
        AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        jobFactory.setIgnoredUnknownProperties("applicationContext");
        return jobFactory;
    }
}

以下是quartz属性文件(ee-quartz.properties)中的配置

org.quartz.scheduler.instanceId=AUTO
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate

启动应用程序时,发生以下异常

Caused by: java.lang.IllegalStateException: Cannot determine target DataSource for lookup key [null]
    at org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.determineTargetDataSource(AbstractRoutingDataSource.java:202) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at com.expertly.config.EERoutingDatabase.determineTargetDataSource(EERoutingDatabase.java:60) ~[EERoutingDatabase.class:na]
    at org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:164) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:289) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:329) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.scheduling.quartz.LocalDataSourceJobStore.initialize(LocalDataSourceJobStore.java:149) ~[spring-context-support-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:1321) ~[quartz-2.2.2.jar:na]
    at org.quartz.impl.StdSchedulerFactory.getScheduler(StdSchedulerFactory.java:1525) ~[quartz-2.2.2.jar:na]
    at org.springframework.scheduling.quartz.SchedulerFactoryBean.createScheduler(SchedulerFactoryBean.java:599) ~[spring-context-support-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:482) ~[spring-context-support-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612) ~[spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549) ~[spring-

豆-4.0.1.RELEASE.jar:4.0.1.RELEASE]

似乎

  1. Quartz正在尝试预先与我的数据源建立连接。 由于我的dataSource不是具体的(它的路由数据源),而且还不知道要连接哪个目标Db(在配置时),它失败

  2. 我们是否有任何规定,其中quartz可与RoutingDataSource一起使用?如果不是,那么下一个最好的东西是什么?

1 个答案:

答案 0 :(得分:0)

理想情况下,您可以尝试将SchedulerFactoryBean设为@Lazy。

但似乎懒惰的初始化不起作用bug,评论中也列出了一个解决方法。

  

之后动态创建schedulerFactory bean   根据上下文收到ContextRefreshedEvent

请告诉我们,如果有效。