我已将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']
static mapping = { columns { batchStatus lazy:false }}
batch.attach()
后尝试使用Batch.get()
我不能在这个实例中使用BatchJob.triggerNow()
,因为这只是几个示例中的一个 - 其他仍由服务调度,但可能被安排为cron作业或其他。我应该提一下,升级Grails时我也升级了Quartz插件;之前的Quartz版本是0.4.1-SNAPSHOT(与升级版本相反,仅为0.4.1)。
如何在这些手动触发的Quartz作业中使Hibernate会话正常工作?
我还将此问题发送到了grails-user邮件列表,至于像这样的更小众问题,该列表似乎引起了更多的响应。如果有人回答,我会用一个答案更新这个问题。 Here's a link 的
答案 0 :(得分: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
}
}
}
答案 1 :(得分:0)
查看jira issue 165(http://jira.codehaus.org/browse/GRAILSPLUGINS-165)Quartz插件中也有线索(您可以查看)这段代码与JMS插件一起使用,似乎运行良好。
试
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();
}
}
}
希望这会有所帮助。它对我有用。
答案 2 :(得分:0)
我认为您可以调用attach()
方法将会话添加到传递给预定作业的对象。
job.attach()