spring - 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)
解决方案
石英可以选择通过属性注册类加载器:
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
推荐阅读
- php - 将函数或字符串注册到 Symfony 依赖注入容器中
- javascript - 具有 Web 用户控件的 ASP.NET 母版页丢失 css 和 javascript
- javascript - Vue重置变量竞争条件
- php - 为什么 mysqli prepare 语句没有清理数据
- c++ - 模板类中的 typedef 语句
- javascript - 箭头函数不起作用。普通人会。为什么?
- html - CSS 和 Boostrap:在 div 中拟合图像或轮播
- mongodb - 为什么我需要指定 $switch 默认语句,而它是可选的?
- angular - filter() 仅返回所选产品的第一个字母
- javascript - 仅在对象未定义时才将属性添加到对象