Spring-boot: Quartz auto-configuration can mutate an existing TaskScheduler via properties config

Created on 10 Apr 2018  路  2Comments  路  Source: spring-projects/spring-boot

See Stack Overflow #49762112.

Since SI wires in a TaskScheduler, Quartz autowiring wires it in and the resulting adapter doesn't expose standard quartz properties.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quartzScheduler' defined in class path resource [org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.class]: Invocation of init method failed; nested exception is org.quartz.SchedulerException: ThreadPool class 'org.springframework.scheduling.quartz.LocalTaskExecutorThreadPool' props could not be configured. [See nested exception: java.lang.NoSuchMethodException: No setter for property 'threadCount']
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1710) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:741) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at com.xxx.t3.starter.Application.main(Application.java:31) [classes/:na]
Caused by: org.quartz.SchedulerException: ThreadPool class 'org.springframework.scheduling.quartz.LocalTaskExecutorThreadPool' props could not be configured.
    at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:849) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.StdSchedulerFactory.getScheduler(StdSchedulerFactory.java:1559) ~[quartz-2.3.0.jar:na]
    at org.springframework.scheduling.quartz.SchedulerFactoryBean.createScheduler(SchedulerFactoryBean.java:636) ~[spring-context-support-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:510) ~[spring-context-support-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    ... 15 common frames omitted
Caused by: java.lang.NoSuchMethodException: No setter for property 'threadCount'
    at org.quartz.impl.StdSchedulerFactory.setBeanProps(StdSchedulerFactory.java:1447) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:847) ~[quartz-2.3.0.jar:na]
    ... 20 common frames omitted

and

spring:
  mail:
    host: XXXXXXXXXX
    port: 25
    protocol: smtp
    defaultEncoding: UTF-8
  quartz:
    jdbc:
      initialize-schema: never
    properties:
      org:
        quartz:
          scheduler:
            instanceId: AUTO
            #instanceName: ETL
            batchTriggerAcquisitionMaxCount: 25
            skipUpdateCheck: true
          threadPool:
            threadCount: 50
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
            tablePrefix: QRTZ_ 
            useProperties: true
            acquireTriggersWithinLock: true
bug

Most helpful comment

I think we should not detect a TaskExecutor at all then since Quartz offers a way to configure it using advanced config. Our documentation does not state we'd look for an existing TaskExecutor so I am tempted to remove that feature as I don't see how it is compatible with the contract above.

Let's see what the rest of the team thinks.

All 2 comments

I think we should not detect a TaskExecutor at all then since Quartz offers a way to configure it using advanced config. Our documentation does not state we'd look for an existing TaskExecutor so I am tempted to remove that feature as I don't see how it is compatible with the contract above.

Let's see what the rest of the team thinks.

And one more argument to remove such an Executor injection into the QuartzAutoConfiguration: https://jira.spring.io/browse/SPR-16189. The WebSocketConfigurationSupport provides this:

@Bean
public TaskScheduler defaultSockJsTaskScheduler() {
    return initTaskScheduler();
}

Where one of the variants is exactly the same what we provide in Spring Integration - ThreadPoolTaskScheduler.

Was this page helpful?
0 / 5 - 0 ratings