QuartzAutoConfiguration.JdbcStoreTypeConfiguration will use the transaction manager of the primary data source when an application has multiple data sources and a non-primary data source is annotated with @QuartzDataSource.

Consider this configuration of beans:

@Primary
@Bean
public HikariDataSource primaryDataSource() {
    HikariConfig config = new HikariConfig();
    config.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres");
    config.setDriverClassName("org.postgresql.Driver");
    config.setUsername("postgres");
    config.setPassword("mysecretpassword");
    config.setAutoCommit(false);
    config.setIdleTimeout(10000);
    config.setPoolName("Primary pool");
    return new HikariDataSource(config);
}

@Primary
@Bean
public DataSourceTransactionManager primaryDataSourceTransactionManager() {
    return new DataSourceTransactionManager(primaryDataSource());
}

@QuartzDataSource
@Bean
public HikariDataSource quartzDataSource() {
    HikariConfig config = new HikariConfig();
    config.setJdbcUrl("jdbc:postgresql://localhost:5432/quartzexample");
    config.setDriverClassName("org.postgresql.Driver");
    config.setUsername("quartzexample");
    config.setPassword("quartzexamplepw");
    config.setAutoCommit(false);
    config.setIdleTimeout(10000);
    config.setPoolName("Quartz pool");
    return new HikariDataSource(config);
}

@Bean
public DataSourceTransactionManager quartzDataSourceTransactionManager() {
    return new DataSourceTransactionManager(quartzDataSource());
}

In org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration.JdbcStoreTypeConfiguration#dataSourceCustomizer you will see the transaction manager for the primary datasource gets set on the SchedulerFactoryBean.

In this scenario actually the transaction manager of the datasource annotated with @QuartzDataSource should be set on the SchedulerFactoryBean. As a workaround this can be accomplished by adding a SchedulerFactoryBeanCustomizer like this:

@Order(Ordered.HIGHEST_PRECEDENCE)
@Bean
public SchedulerFactoryBeanCustomizer schedulerFactoryBeanCustomizer() {
    return schedulerFactoryBean -> schedulerFactoryBean.setTransactionManager(quartzDatasourceTransactionManager());
}

But ideally auto-configuration would take of this automatically of course.

This is using Spring Boot 2.2.4.RELEASE.

Comment From: snicoll

Thanks for the report.

But ideally auto-configuration would take of this automatically of course.

For that to be possible we would need a way to tie the transaction manager (implementation) to its DataSource. Looping over the available TransactionManager to introspect them would be a possibility but that makes me a bit nervous. A better approach would be to use a qualifier on the TransactionManager bean.

Comment From: breun

My current workaround is annotating the transaction manager with my own @QuartzTransactionManager annotation and an extra SchedulerFactoryBeanCustomizer bean that looks for a transaction manager with this annotation and sets this on the SchedulerFactoryBean as the transaction manager.