1

Grails 1.0.4 アプリケーションを 1.1.1 にアップグレードしました。アップグレード後、Quartz ジョブを実行すると例外が繰り返し発生します (Quartz プラグイン 0.4.1 を使用)。プラグインは、サービスを介して Simple および Cron Triggers を使用してジョブを手動でスケジュールするために使用されます (以下の言い換えコード)。

class SchedulerService implements InitializingBean
{
    static scope = 'singleton'
    ...
    def schedule(def batch) {
        JobDetail job = new JobDetail(uniqueId, groupName, BatchJob.class, false, false, true)
        job.jobDataMap.put("batchId", batch.id)

        SimpleTrigger trigger = new SimpleTrigger(triggerId, triggerGroup, 0)

        SchedulerFactory factory = new SchedulerFactory()
        factory.initialize(properties)
        Scheduler scheduler = factory.getScheduler()

        scheduler.scheduleJob(job, trigger)
    }
    ...
}

私の BatchJob ジョブは次のように設定されています。

class BatchJob implements Job, InterruptableJob
{
    static triggers = {}
    void execute(JobExecutionContext context) {
        def batch = Batch.get(context.jobDetail.jobDataMap.getLongValue("batchId"))
        // the next line is "line 49" from the stack trace below
        def foo = batch.batchStatus.description
    }
}

Batch.groovy (ドメイン) の簡略化された定義は次のとおりです。

class Batch
{
    BatchStatus batchStatus // relationship
}

ただし、schedulerService.schedule()既存の保存されたバッチで呼び出されると、次の例外が発生します。

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
        at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
        at org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil.unwrapProxy(GrailsHibernateUtil.java:311)
        at org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil$unwrapProxy.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
        ...
        <b>at BatchJob.execute(BatchJob.groovy:49)</b>
        ...

これを修正するために次のアクションを試みましたが、どれもうまくいきませんでした:

  • static fetchMode = [batchStatus: 'eager']Batch ドメイン クラスで指定しました
  • static mapping = { columns { batchStatus lazy:false }}Batchドメインクラスで使用しました
  • ジョブbatch.attach()を呼び出した後に使用してみましたBatch.get()

BatchJob.triggerNow()これはいくつかの例の 1 つにすぎないため、このインスタンスでは使用できません。他のものはサービスによってスケジュールされていますが、cron ジョブまたはその他の方法でスケジュールされている可能性があります。Grails をアップグレードするときに、Quartz プラグインもアップグレードしたことは言及しておく必要があります。以前の Quartz バージョンは 0.4.1-SNAPSHOT でした (アップグレードされたバージョンでは 0.4.1 だけでした)。

これらの手動でトリガーされた Quartz ジョブで Hibernate セッションを正しく動作させるにはどうすればよいですか?

私はこの質問を grails-user メーリング リストにも送信しました。このようなよりニッチな問題については、メーリング リストがもう少し多くの反応を引き出しているようです。そこから出てきた場合は、この質問を回答で更新します。ここにリンクがあります。

4

3 に答える 3

1

最新の grails バージョン (Grails 2.0.0) およびおそらくそれ以前のバージョンでは、次のヘルパー メソッドで呼び出しをラップすることができます。

class BatchJob implements Job, InterruptableJob
{
  static triggers = {}

  void execute(JobExecutionContext context) {
    Batch.withSession { sess ->
      def batch = Batch.get(context.jobDetail.jobDataMap.getLongValue("batchId"))
      def foo = batch.batchStatus.description
    }
  }
}
于 2012-04-16T01:44:09.200 に答える
0

jira issue 165 をチェックしてください ( http://jira.codehaus.org/browse/GRAILSPLUGINS-165 ) Quartz プラグインにも手がかりがあります (チェックアウトしたい場合があります)。うまくできた。

試す

    import org.hibernate.FlushMode
    import org.hibernate.Session
    import org.springframework.orm.hibernate3.SessionFactoryUtils
    import org.springframework.orm.hibernate3.SessionHolder

    class BatchJob implements Job, InterruptableJob
    {
        static triggers = {}
        void execute(JobExecutionContext context) {
           Session session = null;   
           try { 
              session = SessionFactoryUtils.getSession(sessionFactory, false); 
           }
           // If not already bound the Create and Bind it! 
           catch (java.lang.IllegalStateException ex) { 
              session = SessionFactoryUtils.getSession(sessionFactory, true);  
              TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); 
           }
          session.setFlushMode(FlushMode.AUTO);
          if( log.isDebugEnabled()) log.debug("Hibernate Session is bounded to Job thread");

        // Your Code!
        def batch = Batch.get(context.jobDetail.jobDataMap.getLongValue("batchId"))
        // the next line is "line 49" from the stack trace below
        def foo = batch.batchStatus.description



        try {
         SessionHolder sessionHolder = (SessionHolder) 
         TransactionSynchronizationManager.unbindResource(sessionFactory);
         if(!FlushMode.MANUAL.equals(sessionHolder.getSession().getFlushMode())) {
           sessionHolder.getSession().flush(); 
         }
         SessionFactoryUtils.closeSession(sessionHolder.getSession());
         if( log.isDebugEnabled()) log.debug("Hibernate Session is unbounded from Job thread and closed");
       }
       catch (Exception ex) { 
         ex.printStackTrace(); 
       }
   }
}

お役に立てれば。それは私のために働いた。

于 2009-12-07T21:42:15.137 に答える