Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: 0.3
-
Fix Version/s: 0.3.3
-
Component/s: None
-
Labels:None
-
Testcase included:yes
Description
In using the new 'jdbcStore' feature, I discovered that I cannot create a persistent trigger.
I am trying to persist both the jobs and triggers, since they must survive a server restart. Here I run into a problem. You make your jobs volatile and simply re-register them when the plugin loads, but Quartz will not allow me to create a non-volatile trigger if the job is volatile. So I have to somehow reregister my triggers when my application starts. I can do this in the short term, but going forward I would like to be able to register non-volatile triggers, as some trigger state can be difficult for me to reproduce.
Here is my example Trigger code:
Trigger trigger = new SimpleTrigger(generateRunOnceTriggerId(planId), PLAN_GROUP, startTime, null, 0, 0L)
trigger.setJobName("QueuePlanJob")
trigger.setJobGroup(PLAN_GROUP)
trigger.setVolatility(false)
trigger.jobDataMap.planId = planId
quartzScheduler.scheduleJob(trigger)
And here is the Job artifact that is referenced by the (plugin-generated) JobDetail object:
import org.quartz.JobDataMap
class QueuePlanJob
{
def concurrent = false
def group = "RTTE_PLAN_MGR"
// triggers are created dynamically on a per Plan basis
static triggers = {}
def planRunnerService
public void execute(def jobExecutionContext)
{
JobDataMap data = jobExecutionContext.mergedJobDataMap
log.info "Queued plan ${data.planId} for execution"
}
}
And here is the stack trace that I get when I try to register a non-volatile trigger against a volatile job:
Caused by: org.quartz.JobPersistenceException: Couldn't store trigger: It does not make sense to associate a non-volatile Trigger with a volatile Job! [See nested exception: org.quartz.JobPersistenceException: It does not make sense to associate a non-volatile Trigger with a volatile Job!]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1182)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$5.execute(JobStoreSupport.java:1088)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$39.execute(JobStoreSupport.java:3590)
at org.quartz.impl.jdbcjobstore.JobStoreCMT.executeInLock(JobStoreCMT.java:244)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInLock(JobStoreSupport.java:3586)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1084)
at org.quartz.core.QuartzScheduler.scheduleJob(QuartzScheduler.java:750)
at org.quartz.impl.StdScheduler.scheduleJob(StdScheduler.java:266)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:226)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:899)
at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:946)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:740)
at org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:765)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:753)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:167)
at PlanRunnerService.scheduleCronPlanJob(PlanRunnerService.groovy:74)
at PlanRunnerService$$FastClassByCGLIB$$eecd189c.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:700)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
... 281 more
In the latest 0.3.3-SNAPSHOT there are 'volatility' and 'durability' parameters for a Job and 'volatility' parameter for a Trigger (all are true by default). Please, test and confirm if this issue could be closed.
Sample code:
class TestJob { def volatility = false static triggers = { simpleTrigger timeout: 5000l, volatility: false simpleTrigger startDelay: 30000l, timeout: 15000l } def execute(context) { println context } }class TestJob { def volatility = false static triggers = { simpleTrigger timeout: 5000l, volatility: false simpleTrigger startDelay: 30000l, timeout: 15000l } def execute(context) { println context } }