Le redémarrage de quartz planificateur sans avoir une erreur

Contexte

Je suis en train d'utiliser le planificateur quartz de mode de cluster à l'aide de jdbc.

Problème

Avant j'ai commencé avec jdbc en mode cluster je viens de tester le planificateur en général avec la RAM magasin. Qui a fonctionné sans problème et j'ai pu redémarrer le planificateur (classe principale), sans erreurs. Le problème que j'ai maintenant c'est que quand j'ai arrêter l'exécution (ctrl+c) puis de le redémarrer, je reçois toujours le message d'erreur:

org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'MyTestJob', because one already exists with this identification.

Je ne comprends pas ce qui se passe ici. Ne quartz de ne pas soutenir le redémarrage de l'ordonnanceur? Je veux dire, qu'advient-il si il y a un crash, et le planificateur redémarre après la reprise? Est la seule option pour ensuite supprimer les travaux du quartz de la base de données? Peut-être il ya une autre méthode ou quelque chose que j'ai manqué. Je ne me sens pas très à l'aise à l'aide d'une bibliothèque qui n'a pas à composer avec redémarre.

Une autre chose étrange est, que lors de la modification de jdbc mon travail, ne pas se déclencher plus et je viens de voir l'état d'ATTENTE dans la DB. Ce pourrait-il être? Le travail (cron-horaire) a fonctionné sans problème en mode RAM.

Je suis un peu surpris par le niveau de la documentation et les problèmes que je rencontre avec cette simple tâche parce que j'ai entendu le planificateur quartz pour de nombreuses années maintenant, mais jamais trouvé le temps de l'utiliser. Goodle penser que je ne suis pas le seul avec ce problème. J'espère que c'est juste moi et qu'il existe une solution simple à mon problème, sinon, il serait très décevant pour essayer cette bibliothèque pour la première fois dans le 2.2.x version et déjà d'avoir à chercher quelque chose d'autre.

Voici ma configuration:

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.skipUpdateCheck = true
org.quartz.scheduler.instanceName = Test-Scheduler
org.quartz.scheduler.instanceId = AUTO

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = true
org.quartz.jobStore.dataSource = quartzDS
org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000

Voici mon code:

    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler scheduler = sf.getScheduler();

    scheduler.start();

                JobDetail jobDetail = newJob(job.getClass())
                    .withIdentity("test-name", "test-group")
                    .build();

                CronTrigger trigger = newTrigger()
                    .withIdentity("test-name-trigger", "test-group")
                    .withSchedule(cronSchedule("0 0/1 * * * ?"))
                    .build();

                scheduler.scheduleJob(jobDetail, trigger);

                System.out.println(trigger.getNextFireTime());

MODIFIER

Ce qui est intéressant.

1) en mode RAM fonctionne.

2) jdbc avec le cluster de permettre de ne pas travailler et ne parvient pas (ou presque), silencieusement, même si la journalisation est activée. À la sortie du journal, je vois les suivantes:

19:57:29,913  INFO StdSchedulerFactory:1184 - Using default implementation for ThreadExecutor
19:57:29,936  INFO SchedulerSignalerImpl:61 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
19:57:29,936  INFO QuartzScheduler:240 - Quartz Scheduler v.2.2.1 created.
19:57:29,938  INFO JobStoreTX:667 - Using db table-based data access locking (synchronization).
19:57:29,940  INFO JobStoreTX:59 - JobStoreTX initialized.
19:57:29,941  INFO QuartzScheduler:305 - Scheduler meta-data: Quartz Scheduler (v2.2.1) 'Test-Scheduler' with instanceId 'Michael-PC1405447049916'
Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 25 threads.
Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is clustered.
19:57:29,941  INFO StdSchedulerFactory:1339 - Quartz scheduler 'Test-Scheduler' initialized from default resource file in Quartz package: 'quartz.properties'
19:57:29,941  INFO StdSchedulerFactory:1343 - Quartz scheduler version: 2.2.1
19:57:29,995  INFO AbstractPoolBackedDataSource:462 - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1hgeby993gf1xpdmdc44s|7ec4d0, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1hgeby993gf1xpdmdc44s|7ec4d0, idleConnectionTestPeriod -> 50, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost:3306/scheduler, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> SELECT 1 FROM QRTZ_JOB_DETAILS, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
19:57:30,243 DEBUG StdRowLockSemaphore:107 - Lock 'TRIGGER_ACCESS' is desired by: main
19:57:30,262 DEBUG StdRowLockSemaphore:92 - Lock 'TRIGGER_ACCESS' is being obtained: main
19:58:21,328 DEBUG StdRowLockSemaphore:141 - Lock 'TRIGGER_ACCESS' was not obtained by: main - will try again.
19:58:22,329 DEBUG StdRowLockSemaphore:92 - Lock 'TRIGGER_ACCESS' is being obtained: main
19:59:13,389 DEBUG StdRowLockSemaphore:141 - Lock 'TRIGGER_ACCESS' was not obtained by: main - will try again.
19:59:14,389 DEBUG StdRowLockSemaphore:92 - Lock 'TRIGGER_ACCESS' is being obtained: main

Bien, juste que comme j'étais sur le point d'activer le mode cluster encore une fois, j'ai vu de l'exception:

Exception in thread "main" org.quartz.impl.jdbcjobstore.LockException: Failure obtaining db row lock: Lock wait timeout exceeded; try restarting transaction [See nested exception: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction]
at org.quartz.impl.jdbcjobstore.StdRowLockSemaphore.executeSQL(StdRowLockSemaphore.java:157)
at org.quartz.impl.jdbcjobstore.DBSemaphore.obtainLock(DBSemaphore.java:113)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3780)
at org.quartz.impl.jdbcjobstore.JobStoreTX.executeInLock(JobStoreTX.java:93)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.clearAllSchedulingData(JobStoreSupport.java:1956)
at org.quartz.core.QuartzScheduler.clear(QuartzScheduler.java:1572)
at org.quartz.impl.StdScheduler.clear(StdScheduler.java:239)
at com.scs.core.cron.TaskRunner.main(TaskRunner.java:52)

3) Dans jdbc mode avec le regroupement désactivé il ne fonctionne pas non plus, mais j'obtiens une exception:

  20:04:15,993 DEBUG SimpleSemaphore:132 - Lock 'TRIGGER_ACCESS' retuned by: main
20:04:15,993 DEBUG JobStoreTX:703 - JobStore background threads started (as scheduler was started).
20:04:15,994  INFO QuartzScheduler:575 - Scheduler Test-Scheduler_$_NON_CLUSTERED started.
20:04:15,994 DEBUG JobStoreTX:3933 - MisfireHandler: scanning for misfires...
20:04:16,000 DEBUG JobStoreTX:3182 - Found 0 triggers that missed their scheduled fire-time.
20:04:16,004 DEBUG QuartzSchedulerThread:276 - batch acquisition of 0 triggers
20:04:16,008 DEBUG SimpleSemaphore:81 - Lock 'TRIGGER_ACCESS' is desired by: main
20:04:16,008 DEBUG SimpleSemaphore:88 - Lock 'TRIGGER_ACCESS' is being obtained: main
20:04:16,008 DEBUG SimpleSemaphore:105 - Lock 'TRIGGER_ACCESS' given to: main
20:04:16,052 DEBUG SimpleSemaphore:132 - Lock 'TRIGGER_ACCESS' retuned by: main
Found job: class to.test.cron.ImportProducts
Tue Jul 15 20:05:00 CEST 2014
isStarted=true
isShutdown=false
isInStandbyMode=false
20:04:16,058 DEBUG QuartzSchedulerThread:276 - batch acquisition of 0 triggers
20:04:42,961 ERROR ErrorLogger:2425 - An error occurred while scanning for the next triggers to fire.
org.quartz.JobPersistenceException: Couldn't acquire next trigger: to.test.cron.ImportProducts [See nested exception: java.lang.ClassNotFoundException: to.test.cron.ImportProducts]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2848)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2759)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:2757)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3787)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTriggers(JobStoreSupport.java:2756)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:272)
Caused by: java.lang.ClassNotFoundException: to.test.cron.ImportProducts
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.quartz.simpl.InitThreadContextClassLoadHelper.loadClass(InitThreadContextClassLoadHelper.java:72)
at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:114)
at org.quartz.simpl.CascadingClassLoadHelper.loadClass(CascadingClassLoadHelper.java:138)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.acquireNextTrigger(JobStoreSupport.java:2816)
... 5 more

Je n'arrive pas à comprendre pourquoi je reçois 3 complètement différents comportements dans les 3 nationalités différentes modes. Surley si la classe peut être trouvé dans la RAM-mode, pourquoi ne devrait-on pas trouver dans jdbc mode? Et pourquoi n'est-il pas d'être connecté en mode cluster? La classe est en fait dans un osgi-module de type. Peut que provoquer un problème (jdbc-mode)? Est-ce que je peux faire, alors que la classe peut être trouvé, comme un passage du chargeur de classe etc à quartz?

Je suis assez perdu maintenant et vraiment reconnaissant de toute aide. Il serait dommage d'avoir à revenir à la norme des tâches cron, surtout que le quartz a tellement plus à offrir.

Merci d'avance pour toute aide,

Michael

OriginalL'auteur michaeldd | 2014-07-14