用户填写一些表单,在其中设置报表生成的参数。他提交表单,服务器验证参数,向用户返回一切正常的消息,并生成报告。报告生成完成后,用户将收到带有报告链接的电子邮件。
在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中,做这件事的正确方法是什么?
这里的问题是您正在创建一个新线程,并且它没有绑定到Hibernate会话。创建一个已经足够容易了。使用哪个域类并不重要。例如:
def buildExportAndSendMail() {
executor.execute {
SomeDomainClass.withNewSession { session ->
//GENERATE REPORT AND SEND MAIL. USES GORM.
}
}
}
您可以在文档中阅读有关withNewSession
的更多信息。
我可能会添加一个带有grails石英插件的作业:
class ReportJob {
def execute () {
// create report
// mail report
}
}
然后用触发作业
ReportJob.triggerNow (Map params)
优点是,您不需要显式地处理线程或会话内容。