我希望你們中的一個可愛的人將能夠幫助我,因爲我已經花了許多沒有結果的時間已經試圖讓一切都很好玩!石英JobStore:JobPersistenceException:無法檢索觸發器:ClassNotFoundException
我追蹤的問題到類加載,並且能夠看到,當石英試圖從一個作業存儲(jobStoreCMT),使用不含有任何我的應用程序類的類加載器去連載的JobDetail的,只有在EAR的lib文件夾中定義的庫。
所以...我明明使用應用程序服務器,在這種情況下試圖對Glassfish的3.1.1/3.1.2
使用Spring 3.1對石英1.8.6/2.1.5 嘗試。 0.RELEASE
彈簧/石英配置:
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="overwriteExistingJobs" value="true" />
<property name="triggers">
<list>
<ref bean="notificationEmailsSimpleTrigger" />
</list>
</property>
<property name="quartzProperties">
<props>
<prop key="org.quartz.scheduler.instanceName">QuartzScheduler</prop>
<prop key="org.quartz.scheduler.instanceId">AUTO</prop>
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">25</prop>
<prop key="org.quartz.threadPool.threadPriority">5</prop>
<prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreCMT</prop>
<prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
<prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
<!-- <prop key="org.quartz.jobStore.isClustered">true</prop> -->
<!-- <prop key="org.quartz.jobStore.clusterCheckinInterval">20000</prop> -->
<prop key="org.quartz.scheduler.classLoadHelper.class">org.quartz.simpl.CascadingClassLoadHelper</prop>
<prop key="org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer">true</prop>
<prop key="org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread">true</prop>
<prop key="org.quartz.scheduler.skipUpdateCheck">true</prop>
</props>
</property>
</bean>
和相應的觸發參考:
<bean id="notificationEmailsSimpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="notificationJobDetail" />
<property name="repeatInterval" value="60000" />
</bean>
<bean id="notificationJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.mcboom.social.notifications.NotificationQuartzJobBean" />
</bean>
所以我遇到的問題是這樣的:下面的任何組合似乎並沒有影響正在使用的類加載器。
<prop key="org.quartz.scheduler.classLoadHelper.class">org.quartz.simpl.CascadingClassLoadHelper</prop>
<prop key="org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer">true</prop>
<prop key="org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread">true</prop>
或者試圖檢索以前堅持觸發器時更具體地說不幫助,從而產生以下stracktrace:
INFO: ERROR - ErrorLogger.schedulerError(schedulerFactoryBean_QuartzSchedulerThread)(2358) | An error occured while scanning for the next trigger to fire.
org.quartz.JobPersistenceException: Couldn't acquire next trigger: Couldn't retrieve trigger: com.mcboom.social.notifications.NotificationQuartzJobBean [See nested exception: org.quartz.JobPersistenceException: Couldn't retrieve trigger: com.mcboom.social.notifications.NotificationQuartzJobBean [See nested exception: java.lang.ClassNotFoundException: com.mcboom.social.notifications.NotificationQuartzJobBean]]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2814)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$36.execute(JobStoreSupport.java:2757)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3788)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2753)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:263)
Caused by: org.quartz.JobPersistenceException: Couldn't retrieve trigger: com.mcboom.social.notifications.NotificationQuartzJobBean [See nested exception: java.lang.ClassNotFoundException: com.mcboom.social.notifications.NotificationQuartzJobBean]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveTrigger(JobStoreSupport.java:1596)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveTrigger(JobStoreSupport.java:1572)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2792)
... 4 more
我可以看到org.quartz.simpl.CascadingClassLoadHelper使用上負載,並正確選擇正確的類加載器。
問題是,當QuartzSchedulerThread嘗試檢索一個觸發器,它使用JobStoreSupport.retrieveTrigger(),這反過來又下降回至ObjectInputsStream.resolveClass(),和下面的代碼行:
Class.forName(name, false, latestUserDefinedLoader())
凡latestUserDefinedLoader()總是返回錯誤的類加載器......導致ClassNotFoundException的和留下我非常狼狽!
我應該指出latestUserDefinedLoader()是ObjectInputsStream的本地方法,並且我在OSX上使用jdk 1.6。
任何來自Quartz/Spring或更有可能的Glassfish社區的人都會對此有所瞭解,此刻我正在拉我的頭髮。
謝謝Steve。
更優雅的解決方案是重新打包我的EAR,將所有非EJB類打包到core.jar lib中,並將其放在EAR的lib文件夾中,以便與所有其他應用程序共享相同的類加載器。解決了這個問題,但卻帶來了大量重構的不必要開銷。 –