You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring升级至5.3.27、Quartz-scheduler升级至2.3.1后出现SchedulerConfigException错误求助

Spring升级至5.3.27、Quartz-scheduler升级至2.3.1后出现SchedulerConfigException错误求助

问题背景

刚完成Spring从5.1.20到5.3.27、Quartz-scheduler从2.2.1到2.3.1的版本升级,启动应用时直接抛出了如下异常栈,查了官方文档确认Quartz 2.3.1是兼容Spring 5.3.x版本的,但实在搞不清问题出在哪,求大佬帮忙分析!

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jobManager' defined in URL [jar:file:DefaultJobManager.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactory' defined in ServletContext resource [/WEB-INF/spring/app-standard-config.xml]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Non-ManagedTX DataSource name not set! If your 'org.quartz.jobStore.dataSource' is XA, then set 'org.quartz.jobStore.nonManagedTXDataSource' to a non-XA datasource (for the same DB). Otherwise, you can set them to be the same.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactory' defined in ServletContext resource [/WEB-INF/spring/app-standard-config.xml]: Invocation of init method failed; nested exception is org.quartz.SchedulerConfigException: Non-ManagedTX DataSource name not set! If your 'org.quartz.jobStore.dataSource' is XA, then set 'org.quartz.jobStore.nonManagedTXDataSource' to a non-XA datasource (for the same DB). Otherwise, you can set them to be the same.

Caused by: org.quartz.SchedulerConfigException: Non-ManagedTX DataSource name not set! If your 'org.quartz.jobStore.dataSource' is XA, then set 'org.quartz.jobStore.nonManagedTXDataSource' to a non-XA datasource (for the same DB). Otherwise, you can set them to be the same.

问题根源

这个错误是Quartz 2.3.x版本对JDBC作业存储的配置规则做了强制变更:
在Quartz 2.2.x及更早版本中,只要配置了org.quartz.jobStore.dataSource,框架会默认复用该数据源处理非容器托管的事务操作;但从2.3.x开始,Quartz要求必须显式指定org.quartz.jobStore.nonManagedTXDataSource——这个参数对应的数据源是用来处理Quartz内部不需要容器事务管理的元数据操作(比如触发器状态更新、作业记录维护等),以此明确区分托管事务和非托管事务的数据源使用场景。

解决方案

根据你使用的数据源类型,分两种场景处理:

场景1:使用普通非XA数据源

如果你的org.quartz.jobStore.dataSource是普通的非XA数据源(比如Spring自带的DriverManagerDataSource或第三方连接池数据源),直接把nonManagedTXDataSource设置成和dataSource同名即可。

修改app-standard-config.xml中的SchedulerFactoryBean配置:

<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <!-- 保留你已有的其他配置,比如触发器、数据源引用等 -->
    <property name="quartzProperties">
        <props>
            <!-- 你原来配置的数据源名称 -->
            <prop key="org.quartz.jobStore.dataSource">myAppDataSource</prop>
            <!-- 添加该行,和上面的数据源名称保持一致 -->
            <prop key="org.quartz.jobStore.nonManagedTXDataSource">myAppDataSource</prop>
            <!-- 其他Quartz基础配置,比如作业存储类型 -->
            <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
        </props>
    </property>
    <!-- 数据源映射,确保你的数据源Bean已提前定义 -->
    <property name="dataSources">
        <map>
            <entry key="myAppDataSource" value-ref="yourExistingDataSourceBean"/>
        </map>
    </property>
</bean>

场景2:使用XA分布式事务数据源

如果你的org.quartz.jobStore.dataSource是XA类型的数据源(用于分布式事务场景),则需要额外配置一个非XA数据源(必须连接同一个数据库),然后把nonManagedTXDataSource指向这个新的非XA数据源:

  1. 先在Spring配置中定义非XA数据源Bean:
<bean id="nonManagedXADataSource" class="com.zaxxer.hikari.HikariDataSource">
    <property name="jdbcUrl" value="${db.url}"/>
    <property name="username" value="${db.username}"/>
    <property name="password" value="${db.password}"/>
    <!-- 其他连接池配置,比如最大连接数、超时时间等 -->
</bean>
  1. 再修改SchedulerFactoryBean的Quartz属性配置:
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <!-- 保留你已有的其他配置 -->
    <property name="quartzProperties">
        <props>
            <!-- 原有的XA数据源 -->
            <prop key="org.quartz.jobStore.dataSource">myXADataSource</prop>
            <!-- 指向新配置的非XA数据源 -->
            <prop key="org.quartz.jobStore.nonManagedTXDataSource">nonManagedXADataSource</prop>
            <!-- 分布式事务场景下的作业存储类型 -->
            <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreCMT</prop>
            <!-- 其他XA相关配置 -->
        </props>
    </property>
    <!-- 映射两个数据源 -->
    <property name="dataSources">
        <map>
            <entry key="myXADataSource" value-ref="yourXADataSourceBean"/>
            <entry key="nonManagedXADataSource" value-ref="nonManagedXADataSource"/>
        </map>
    </property>
</bean>

验证说明

配置完成后重启应用,这个SchedulerConfigException应该就能解决了。本质上就是Quartz新版本对事务边界的处理更严谨,强制区分了不同事务场景下的数据源使用规则。

备注:内容来源于stack exchange,提问作者hamza moslah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 15:05:30