首页 > 解决方案 > Spring 5.2.x 到 5.3.x 升级导致 Wildlfy 20 下 Quartz Jobs 出现 ClassNotFoundException

问题描述

我们正在使用:

JDK 8

春季 5.2.16.RELEASE

石英 - 2.3.2

野蝇 20

除了 web 应用程序(.war),我们还有插件(.jar),它们的类在 web 应用程序中使用以下代码加载:

    Thread.currentThread().setContextClassLoader(pluginsClassLoader);

PluginsClassLoader extends URLClassLoader

我们 org.springframework.scheduling.quartz.QuartzBean用于在插件(.jar)的战争中定义我们自己的石英作业,例如FSSendMessagesWorker extends QuartzBean

在@Configuration 类中,我们有

    @Bean
    public JobDetailFactoryBean fsPluginSendMessagesWorkerJob() {
        JobDetailFactoryBean obj = new JobDetailFactoryBean();
        obj.setJobClass(FSSendMessagesWorker.class);
        obj.setDurability(true);
        return obj;
    }


    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public SimpleTriggerFactoryBean fsPluginSendMessagesWorkerTrigger()

        SimpleTriggerFactoryBean obj = new SimpleTriggerFactoryBean();
        obj.setJobDetail(fsPluginSendMessagesWorkerJob().getObject());
        obj.setRepeatInterval("* * * 0 1");
        obj.setStartDelay(20000);
        return obj;
    }

升级到 Spring 5.3.x 后,看起来扩展 QuartzBean 并存在于 .jar 文件中的所有类都无法加载,而在 Spring 5.2.x 之前这是可能的(工作)主应用程序中存在的类(.war ) 工作正常 - 已加载。除了 Spring 没有升级其他库。

021-10-05 14:03:25,055 [] [] [] [EE-ManagedExecutorService-quartzExecutorService-Thread-1] 错误 ossqLocalDataSourceJobStore:2867 - 检索作业时出错,将触发状态设置为 ERROR。org.quartz.JobPersistenceException:无法检索作业,因为找不到所需的类:com.company.plugin.fs.worker.FSSendMessagesWorker from [Module "deployment.mycompany.war" from Service Module Loader] 在deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1393) 在deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java: 2864) 在 deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport$41.execute(JobStoreSupport.java:2805) 在 deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport$41.execute( JobStoreSupport.java:2803) 在 deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3864) 在 deployment.mycompany.war//org.quartz.impl.jdbcjobstore.JobStoreSupport。在 org.jboss.as.ee@20.0.1.Final//org 的 deployment.mycompany.war//org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:287) 处获取 NextTriggers(JobStoreSupport.java:2802)。 jboss.as.ee.concurrent.ControlPointUtils$ControlledRunnable.run(ControlPointUtils.java:105) 在 java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) 在 java.base/java.util.concurrent.FutureTask。在 org.glassfish.javax.enterprise.concurrent//org.glassfish.enterprise.concurrent.internal.ManagedFutureTask.run(ManagedFutureTask.java:117) 在 java.base/java.util.concurrent 运行(FutureTask.java:264) .ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) 在 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) 在 java.base/java.lang.Thread.run(Thread.java :834) 在 org.glassfish.javax.enterprise.concurrent//org.glassfish.enterprise.concurrent.ManagedThreadFactoryImpl$ManagedThread.run(ManagedThreadFactoryImpl.java:227) 引起:java.lang.ClassNotFoundException: com.company.plugin。 fs.worker。FSSendMessagesWorker from [Module "deployment.mycompany.war" from Service Module Loader] at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255) at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)在 org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398) 在 org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116) 在 java.base/java.lang.Class.forName0(Native Method)在 java.base/java.lang.Class.forName(Class.java:398) 在 deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.springframework.util.ClassUtils.forName(ClassUtils.java:284 ) 在部署时的 deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.springframework.scheduling.quartz.ResourceLoaderClassLoadHelper.loadClass(ResourceLoaderClassLoadHelper.java:81)。domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.springframework.scheduling.quartz.ResourceLoaderClassLoadHelper.loadClass(ResourceLoaderClassLoadHelper.java:87) 在 deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.quartz .impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852) 在 deployment.domibus-MSH-wildfly-5.0-SNAPSHOT.war//org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1390)

标签: springwildflyclassloaderquartz

解决方案


石英可以选择通过属性注册类加载器:

 org.quartz.scheduler.classLoadHelper.class

如果设置 TCCL Transaction Context ClassLoader,请确保 cron 线程具有与加载“类”的类加载器相同的类加载器。在 WildFly 新线程中,获取 ModuleClassLoader,它可以具有与初始阶段设置回线程范围的类范围不同的类范围。尝试: org.quartz.scheduler.classLoadHelper.class = org.quartz.simpl.InitThreadContextClassLoadHelper 或编写自定义 ClassHelperLoader 类。 https://www.quartz-scheduler.org/api/2.0.2/org/quartz/spi/ClassLoadHelper.html


推荐阅读