Grails和后台任务

时间:2014-09-14 17:01:42

标签: hibernate grails gorm executorservice

用户填写表格,为报告生成设置参数。他提交表单,服务器验证参数,向用户返回一切正常的消息并生成报告。报告生成完成后,用户会收到包含报告链接的电子邮件。

在grails中实现这一目标的正确方法是什么? 目前我有一个生成报告的服务,它看起来像这样:

@Transactional
class AnalyticsService {

    ExecutorService executor = Executors.newSingleThreadExecutor()

    def buildExportAndSendMail() {
        executor.execute {
            //GENERATE REPORT AND SEND MAIL. USES GORM.
        }
    }

    @PreDestroy
    void shutdown() {
        executor.shutdownNow()
    }
}

我的控制器操作如下所示:

def generateReport(ReportParams command) {
    if(!command.hasErrors()) {
        analyticsService.buildExportAndSendMail()
        render([success:true, html:"Your report is being generated."] as JSON)
    } else {
        ...
    }
}

但是,在尝试访问域对象字段时,服务会抛出错误:

Exception in thread "pool-8-thread-1" 
Error |
org.hibernate.LazyInitializationException: could not initialize proxy - no Session

在grails中这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

这里的问题是你正在创建一个新线程并且它没有绑定到Hibernate会话。创建一个很容易。使用哪个域类并不重要。例如:

def buildExportAndSendMail() {
  executor.execute {
    SomeDomainClass.withNewSession { session ->
      //GENERATE REPORT AND SEND MAIL. USES GORM.
    }
  }
}

您可以在documentation中详细了解withNewSession

答案 1 :(得分:1)

我可能会用grails quartz plugin添加一份工作:

class ReportJob {
    def execute () {
        // create report
        // mail report
    }
}

然后使用

触发作业
ReportJob.triggerNow (Map params)

优点是,您不需要显式处理线程或会话内容。