4

У меня проблема с кварцем (плагин: quartz2: 2.1.6.2, но у меня есть тест даже с плагином: кварц: 1.0-RC7, но проблема не меняется) в моем проекте Grails (grails 2.2.1).Кварцевое задание перестает выполняться на исключении StaleObjectStateException

У меня есть работа, как этот

class MyJob { 

def concurrent = false 

def execute(context){ 

     try { 

      //.... 
      // works with domains ..... 
      myDomain.save(flush: true) 
      // works with domains ..... 
      //.... 

      sessionFactory.currentSession.flush() 

     } catch (org.springframework.dao.OptimisticLockingFailureException olfe) { 
      println "Job failed by database exception " 
     } catch (org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException ole){ 
      println "Job failed by database exception " 
     } catch (org.hibernate.HibernateException hibe){ 
      println "Job failed by database exception " 
     } 
    } 

} 

} 

Иногда StaleObjectStateException в происходить подавление метода выполнения. Это нормально для моей логики, я использую оптимистичную блокировку Грайла, и это исключение происходит только раз в неделю.

Проблема заключается в том, что это исключение происходит после того, как Job перестает стрелять снова.

Я попытался co обернуть код метода в попытке уловить и сфотографировать сессию спящего режима внутри, чтобы захватить исключение, но без фортуны. Исключением не является захват ни одним из моих улов.

В поисках онлайн Я нашел это old grails quartz bug, но он исправлен, и в любом случае использование try {} catch должно обойти ошибку.

P.S. Работа запланирована на bootstrab вызовом этого типа

MyJob.schedule(10000L) 

Исключение, которое останавливает планирование является

[194949896] core.ErrorLogger Unable to notify JobListener(s) of Job that was executed: (error will be ignored). trigger= DEFAULT.MT_3tbn6lewgiqa3 job= DEFAULT.MyJob 
org.quartz.SchedulerException: JobListener 'persistenceContextJobListener' threw exception: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyDomain#42] [See nested exception: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyDomain#42]] 
    at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1939) 
    at org.quartz.core.JobRunShell.notifyJobListenersComplete(JobRunShell.java:361) 
    at org.quartz.core.JobRunShell.run(JobRunShell.java:235) 
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) 
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyDomain#42] 
    at grails.plugin.quartz2.PersistenceContextJobListener.jobWasExecuted(PersistenceContextJobListener.groovy:46) 
    at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1937) 
    ... 3 more 

..... 

events.PatchedDefaultFlushEventListener Could not synchronize database state with session 
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyJob#42] 
    at MyJob.execute(MyJob.groovy:354) 
    at grails.plugin.quartz2.GrailsArtefactJob.execute(GrailsArtefactJob.java:57) 
    at org.quartz.core.JobRunShell.run(JobRunShell.java:213) 
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557) 
+0

в вашем примере кода вы не поймать «org.hibernate.StaleObjectStateException», так что я думаю, что это нормально работа провал ... – moskiteau

+0

@moskiteau org.hibernate.StaleObjectStateException является org.hibernate.HibernateException –

ответ

1

Я прошу прощения за восстановление старого сообщения, но мы столкнулись с этой проблемой с устаревшим приложением Grails (Grails 2.2.3), и очистка сеанса в методе выполнения не всегда решила проблему, поэтому я опишу, что мы чтобы устранить проблему.

В нашем случае иногда исключение может происходить вне контекста метода execute, даже если мы явно сбросили сеанс в методе выполнения. Более конкретно, исключение выбрано в коде PersistenceContextJobListener плагина Quartz2, который очищает сеанс ПОСЛЕ завершения выполнения метода выполнения. Поэтому после просмотра кода плагина Quartz2 мы поняли, что нам нужно переопределить значение PersistenceContextJobListener по умолчанию, которое завершает метод выполнения задания и очищает сеанс.

Во-первых, обратите внимание, что в методе обратного вызова jobWasExecuted объекта PersistenceContextJobListener нет обработки исключений.

https://github.com/9ci/grails-quartz2/blob/master/src/groovy/grails/plugin/quartz2/PersistenceContextJobListener.groovy#L44

Все, что вам действительно нужно сделать, это реализовать свой собственный слушатель работы и перенесите код jobWasExecuted в Try/улове. См. Следующие фрагменты кода для примера того, как это сделать.

https://gist.github.com/jmiranda/45084eb32f07f6e3d1934547cd4fbb9f https://gist.github.com/jmiranda/5148f0a67afc8950bad950793e9c2303

Мы использовали SessionBinderJobListener оригинального Quartz плагина в качестве примера (эээ, мы более или менее скопировал его).

https://github.com/grails-plugins/grails-quartz/blob/master/src/main/groovy/grails/plugins/quartz/listeners/SessionBinderJobListener.java

Во всяком случае, это должны вас к точке, где вы предотвращающая запускаемым рабочие места от остановки в целом из-за неперехваченный StaleObjectStateException.

+0

Отличная работа Justin. Я больше не работаю над этим проектом, и я не могу проверить это решение, но, похоже, хорошо для меня. –

0

Не знаю, насколько точны ваш пример, но вы должны знать, что заводной является исключением. Это означает, что даже когда код запускает StaleObjectStateException, вы можете получить его в простое исключение RuntimeException, которое не выхвачено выше. Насколько глубоко это myDomain.save(flush: true) метод (прямо в работе или выполнен из другой службы)?

0

Я столкнулся с аналогичной проблемой, задание кварца работает на потоке, который не связан с ним сессией спящего режима, я смог обойти его, захватив новый сеанс, а затем вытеснить флеш() и Чисто(). Если вы не очистите &, очистите задание, в конце концов повторно используйте один из предыдущих потоков заданий и попытайтесь выписать тот же самый объект (не можете вспомнить, должен ли он быть тем же или любым объектом того же класса) , но будет не-совершенные копии в сессии, связанной с этой нити, которые в свою очередь вызывают StaleObjectException:

Вот что мой код выглядит следующим образом:

def sessionFactory 

def execute() { 
    def session = SessionFactoryUtils.getSession(sessionFactory,true) 

    myDomain.save(flush: true) 

    session.flush() 
    session.clear() 
} 

Вы можете просто нужно сделайте flush() и clear() в вашем примере кода, чтобы добиться того же результата.

+0

Thanl вы miedzial. Пробовал с флешем и ясным. Проблема заключается не в исключении StaleObjectException, которое предполагается моим проектом. Проблема в том, что когда StaleObjectException occour я не смог его поймать, а кварц прекратил выполнение других вызовов –

Смежные вопросы