Class not found exception with persistent stores

瀏覽次數:651 次
跳到第一則未讀訊息

Daniel Woelfel

未讀,
2012年10月14日 晚上9:11:462012/10/14
收件者:clojure...@googlegroups.com
Hello,

I've been using quartzite with the RAM store successfully for a while, but I'm having trouble using a persistent store.

Whenever a job executes, I get:

org.quartz.JobPersistenceException: Could not load job class java.lang.ClassNotFoundException: chki.background.sample.job-test

I've tried both the quartz-mongodb and a mysql store, but I get the same error in both cases.

I set up a sample file that exhibits this behavior. I am able to initialize and start the scheduler without any errors. Setting up the job works, and it is stored in the database. It only throws errors when it executes the job.

(ns chki.background.sample
  (:require [clojurewerkz.quartzite.scheduler :as sched]
            [clojurewerkz.quartzite.triggers :as t]
            [clojurewerkz.quartzite.jobs :as j]
            [clojurewerkz.quartzite.schedule.simple :as s]
            [clojurewerkz.quartzite.matchers  :as m])
  (:use [clojurewerkz.quartzite.jobs :only [defjob]]
        [clojurewerkz.quartzite.schedule.simple :only
         [schedule repeat-forever with-repeat-count
          with-interval-in-minutes with-interval-in-milliseconds]]
        [clojure.tools.logging :only [info error]]
        [clojure.java.io])
  (:import org.quartz.simpl.SimpleClassLoadHelper
           org.quartz.impl.triggers.SimpleTriggerImpl
           org.quartz.impl.JobDetailImpl
           org.quartz.impl.matchers.GroupMatcher
           com.novemberain.quartz.mongodb.MongoDBJobStore
           com.mysql.jdbc.Driver
           ))

(defjob job-test [ctx]
  (info "in job"))

(defn setup-test-job []
  (let [job (j/build
             (j/of-type job-test))
        trigger (t/build
                 (t/start-now)
                 (t/with-schedule (schedule
                                   (with-repeat-count 3)
                                   (with-interval-in-milliseconds 1))))]
    (sched/schedule job trigger)))

(defn -main []
  (sched/initialize)
  (sched/start)
  (setup-test-job))

Here is the full backtrace:


10-14@17:45:05 ERROR (org.quartz.core.ErrorLogger) - An error occurred while firing triggers '[Trigger 'DEFAULT.6da64b5bd2ee-9afb2493-0b79-4a2b-8398-179a12cbeb61':  triggerClass: 'org.quartz.impl.triggers.SimpleTriggerImpl calendar: 'null' misfireInstruction: 0 nextFireTime: null]'
org.quartz.JobPersistenceException: Could not load job class chki.background.sample.job-test [See nested exception: java.lang.ClassNotFoundException: chki.background.sample.job-test]
        at com.novemberain.quartz.mongodb.MongoDBJobStore.retrieveJob(MongoDBJobStore.java:174)
        at com.novemberain.quartz.mongodb.MongoDBJobStore.retrieveJob(MongoDBJobStore.java:908)
        at com.novemberain.quartz.mongodb.MongoDBJobStore.triggersFired(MongoDBJobStore.java:538)
        at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:326)
Caused by: java.lang.ClassNotFoundException: chki.background.sample.job-test
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
        at com.novemberain.quartz.mongodb.MongoDBJobStore.retrieveJob(MongoDBJobStore.java:155)


Michael Klishin

未讀,
2012年10月14日 晚上10:44:412012/10/14
收件者:clojure...@googlegroups.com


2012/10/15 Daniel Woelfel <dwwo...@gmail.com>

Whenever a job executes, I get:

org.quartz.JobPersistenceException: Could not load job class java.lang.ClassNotFoundException: chki.background.sample.job-test

I've tried both the quartz-mongodb and a mysql store, but I get the same error in both cases.

Clojure and Quartz use different class loaders so code that Clojure compiler loads using an instance
of clojure.lang.DynamicClassLoader is not visible (because of the JVM security model) to Quartz.

The solution is to add a tiny subclass of whatever base store you need and override the method
that determines what classloader to use, like here:

and then tell Quartz to use it via quartz.properties:

Lein 2 documentation on mixed Clojure/Java projects:

I may be a good idea to ship such class with Quartzite, unfortunately, the whole
thing still will not be obvious or "turn key" without looking at the docs.
--
MK

http://github.com/michaelklishin
http://twitter.com/michaelklishin

Ashish Negi

未讀,
2016年2月18日 上午11:00:592016/2/18
收件者:clojure-quartz
Thanks for the quartzite..

I am having the same problem with jdbc.

I have read http://www.clojurequartz.info/articles/durable_quartz_stores.html

My project.clj has :
   :source-paths ["src/clj"]
   :java-source-paths ["src/java"]

I have DynamicClassLoadHelper.java file in src/java/theophrastus directory.

I use lein to run :
              lein run server


my quartz.properties file is :
    org.quartz.scheduler.classLoadHelper.class=theophrastus.DynamicClassLoadHelper
    org.quartz.threadPool.threadCount=3

    ## To use the JobStoreTX with Postgresql include the following:
    ## (Documentation for other database backends is below)
    org.quartz.dataSource.db.driver=org.postgresql.Driver
    org.quartz.dataSource.db.URL=<replaced by my jdbc conn>
    org.quartz.dataSource.db.user=<replaced by my user>
    org.quartz.dataSource.db.password=<replaced by my password>

In repl on executing :

   (.getMetaData @scheduler)
   #object[org.quartz.SchedulerMetaData 0x4ca70439 "Quartz Scheduler (v2.1.7) 'QuartzScheduler' with instanceId 'NON_CLUSTERED'\n  Scheduler class: 'org.quartz.impl.StdScheduler' - running locally.\n  Running since: Thu Feb 18 21:24:28 IST 2016\n  Not currently in standby mode.\n  Number of jobs executed: 11\n  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.\n  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.\n"]

Please find "3 threads" in above output same as my config file.

My job using defjob runs fine when it is defined in same file as scheduler initialize is called.
However defjob referenced from another file does not work and throws

Exception in thread "main" java.lang.RuntimeException: No such var: ttasks/NoOpJob, compiling:(theophrastus/utils.clj:19:14)

How can i solve the problem ?

Ashish Negi

未讀,
2016年2月18日 下午1:37:032016/2/18
收件者:clojure-quartz
Finally able to do :

Since defjob creates a defrecord.. to use these jobs i need to use "import" for getting these records in another file :

(ns mynamespace.utils
      (:import [mynamesapce.jobfilename JobName]))
回覆所有人
回覆作者
轉寄
0 則新訊息