无法在 Spring cron 中执行 Quartz 作业
Quartz job can not be executed in Spring cron
类似的问题好像被问过很多次了,但是我还是找不到确切的问题 answer.I 使用 org.quartz.StatefulJob 设置一个定时作业通过模拟异常重试5次和 Spring cron 来触发它,但发生了一些异常,详情如下:
@Service(value = "cronJobRetryImpl")
public class DuMiSynchronizationRetryRest implements StatefulJob {
private Logger logger = Logger.getLogger(getClass());
@Override
public void execute(JobExecutionContext context) throws
JobExecutionException {
logger.info("enter execute ...");
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
long count =
NumberUtils.toLong(String.valueOf(dataMap.get("count")));
if (count >= 5) {
logger.info("Retries exceeded...");
JobExecutionException e = new JobExecutionException("Retries
exceeded");
e.setUnscheduleAllTriggers(true);
throw e;
}
try {
logger.info("business begin...");
dataMap.put("count", 0);
int n = 10 / 0;
} catch (Exception e) {
count++;
dataMap.putAsString("count", count);
JobExecutionException e2 = new JobExecutionException(e);
try {
logger.info("Thread begin to sleep for 3 seconds...");
Thread.sleep(3000);
} catch (InterruptedException e1) {
logger.info("interrupted exception",e1);
}
e2.refireImmediately();
logger.info("job refired ...");
throw e2;
}
}
}
这是 Spring xml:
<!-- retry test start -->
<bean id="cronJobRetryImplTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" lazy-init="true">
<property name="targetObject">
<ref bean="cronJobRetryImpl" />
</property>
<property name="targetMethod">
<value>execute</value>
</property>
<property name="concurrent" value="false" />
</bean>
<bean id="cronJobRetryTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="cronJobRetryImplTask" />
</property>
<property name="cronExpression">
<value>20 30 9 * * ?</value>
</property>
</bean>
<!-- retry test end -->
<bean id="startQuertz" lazy-init="false" autowire="no"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronJobRetryTime" />
</list>
</property>
我计划在每个 9:30:20AM 触发它,结果:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryTime' defined in class path resource [applicationContext-job.xml]: Cannot resolve reference to bean 'cronJobRetryImplTask' while setting bean property 'jobDetail'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryImplTask' defined in class path resource [applicationContext-job.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5157)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5680)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1702)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1692)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryImplTask' defined in class path resource [applicationContext-job.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
... 24 more
Caused by: java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
at java.lang.Class.getMethod(Unknown Source)
at org.springframework.util.MethodInvoker.prepare(MethodInvoker.java:178)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.afterPropertiesSet(MethodInvokingJobDetailFactoryBean.java:198)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 31 more
--------------------第一次编辑-------------------- ------
是的,是的,samabcde 的回放是有效的,感谢 samabcde 的耐心和努力,但问题似乎在代码中 itself.I 尝试 运行 这些代码,但工作不能模拟异常发生时再次执行:
INFO 2018-11-02 14:43:00,022 [DuMiSynchronizationRetryRest.java,16] - enter
execute ...
INFO 2018-11-02 14:43:00,027 [DuMiSynchronizationRetryRest.java,28] -
business begin...
INFO 2018-11-02 14:43:00,027 [DuMiSynchronizationRetryRest.java,36] -
Thread begin to sleep for 3 seconds...
INFO 2018-11-02 14:43:03,028 [DuMiSynchronizationRetryRest.java,42] - job
refired ...
INFO 2018-11-02 14:43:03,031 [JobRunShell.java,221] - Job
DEFAULT.cronJobRetryImplTask threw a JobExecutionException:
org.quartz.JobExecutionException: java.lang.ArithmeticException: / by zero
[See nested exception: java.lang.ArithmeticException: / by zero]
at tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute(DuMiSynchronizati onRetryRest.java:34)
at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: java.lang.ArithmeticException: / by zero
at tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute(DuMiSynchronizat
ionRetryRest.java:30)
... 2 more
日志显示异常,没有了clue.How我可以实现我的目标吗?
Spring Quartz BeanCreationException 问题
来自Springxml
<bean id="cronJobRetryImplTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" lazy-init="true">
<property name="targetObject">
<ref bean="cronJobRetryImpl" />
</property>
<property name="targetMethod">
<value>execute</value>
</property>
<property name="concurrent" value="false" />
</bean>
未指定 MethodInvoker(MethodInvokingJobDetailFactoryBean
extend) 的参数,因此假定没有参数。结果异常
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryImplTask' defined in class path resource [applicationContext-job.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
被抛出,因为在 DuMiSynchronizationRetryRest
class.
中没有没有参数的方法 execute
要解决此问题,应使用 JobDetailFactoryBean
而不是 Java Doc of MethodInvokingJobDetailFactoryBean
中所述的 MethodInvokingJobDetailFactoryBean
Avoids the need for implementing a one-line Quartz Job that just invokes an existing service method on a Spring-managed target bean.
然而,DuMiSynchronizationRetryRest
是作为 Quartz 作业实现的,并且使用作业的 execute
方法,这需要 JobExecutionContext
。在这种情况下,JobDetailFactoryBean
应该是合适的工厂 bean。要更改工厂 bean,只需将 cronJobRetryImplTask 的 bean 定义更新为
<bean id="cronJobRetryImplTask"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean"
lazy-init="true">
<property name="jobClass">
<value>gov.housingauthority.pass.app.DuMiSynchronizationRetryRest
</value>
</property>
</bean>
因为cronJobRetryImpl
bean在改变@Service
注解后不需要
也可以删除。
最后,由于 StatefulJob
已弃用,如 Java Doc of StatefulJob、
中所建议
use DisallowConcurrentExecution and/or PersistJobDataAfterExecution
annotations instead.
作业不立即重试问题
作业没有立即重试的问题,这是由于使用
e2.refireImmediately();
,这是一个getter only.To 设置重新启动标志:
对于 quartz 1.5.2 或之前的版本,
我们可以使用 new JobExecutionException(e, true)
,其中第二个参数会将 refireImmediately
设置为 true。
1.7.2版本后,提供setter方法setRefireImmediately(boolean refireImmediately);
类似的问题好像被问过很多次了,但是我还是找不到确切的问题 answer.I 使用 org.quartz.StatefulJob 设置一个定时作业通过模拟异常重试5次和 Spring cron 来触发它,但发生了一些异常,详情如下:
@Service(value = "cronJobRetryImpl")
public class DuMiSynchronizationRetryRest implements StatefulJob {
private Logger logger = Logger.getLogger(getClass());
@Override
public void execute(JobExecutionContext context) throws
JobExecutionException {
logger.info("enter execute ...");
JobDataMap dataMap = context.getJobDetail().getJobDataMap();
long count =
NumberUtils.toLong(String.valueOf(dataMap.get("count")));
if (count >= 5) {
logger.info("Retries exceeded...");
JobExecutionException e = new JobExecutionException("Retries
exceeded");
e.setUnscheduleAllTriggers(true);
throw e;
}
try {
logger.info("business begin...");
dataMap.put("count", 0);
int n = 10 / 0;
} catch (Exception e) {
count++;
dataMap.putAsString("count", count);
JobExecutionException e2 = new JobExecutionException(e);
try {
logger.info("Thread begin to sleep for 3 seconds...");
Thread.sleep(3000);
} catch (InterruptedException e1) {
logger.info("interrupted exception",e1);
}
e2.refireImmediately();
logger.info("job refired ...");
throw e2;
}
}
}
这是 Spring xml:
<!-- retry test start -->
<bean id="cronJobRetryImplTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" lazy-init="true">
<property name="targetObject">
<ref bean="cronJobRetryImpl" />
</property>
<property name="targetMethod">
<value>execute</value>
</property>
<property name="concurrent" value="false" />
</bean>
<bean id="cronJobRetryTime" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref bean="cronJobRetryImplTask" />
</property>
<property name="cronExpression">
<value>20 30 9 * * ?</value>
</property>
</bean>
<!-- retry test end -->
<bean id="startQuertz" lazy-init="false" autowire="no"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronJobRetryTime" />
</list>
</property>
我计划在每个 9:30:20AM 触发它,结果:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryTime' defined in class path resource [applicationContext-job.xml]: Cannot resolve reference to bean 'cronJobRetryImplTask' while setting bean property 'jobDetail'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryImplTask' defined in class path resource [applicationContext-job.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:5157)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5680)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1702)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1692)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryImplTask' defined in class path resource [applicationContext-job.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:323)
... 24 more
Caused by: java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
at java.lang.Class.getMethod(Unknown Source)
at org.springframework.util.MethodInvoker.prepare(MethodInvoker.java:178)
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean.afterPropertiesSet(MethodInvokingJobDetailFactoryBean.java:198)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 31 more
--------------------第一次编辑-------------------- ------
是的,是的,samabcde 的回放是有效的,感谢 samabcde 的耐心和努力,但问题似乎在代码中 itself.I 尝试 运行 这些代码,但工作不能模拟异常发生时再次执行:
INFO 2018-11-02 14:43:00,022 [DuMiSynchronizationRetryRest.java,16] - enter
execute ...
INFO 2018-11-02 14:43:00,027 [DuMiSynchronizationRetryRest.java,28] -
business begin...
INFO 2018-11-02 14:43:00,027 [DuMiSynchronizationRetryRest.java,36] -
Thread begin to sleep for 3 seconds...
INFO 2018-11-02 14:43:03,028 [DuMiSynchronizationRetryRest.java,42] - job
refired ...
INFO 2018-11-02 14:43:03,031 [JobRunShell.java,221] - Job
DEFAULT.cronJobRetryImplTask threw a JobExecutionException:
org.quartz.JobExecutionException: java.lang.ArithmeticException: / by zero
[See nested exception: java.lang.ArithmeticException: / by zero]
at tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute(DuMiSynchronizati onRetryRest.java:34)
at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: java.lang.ArithmeticException: / by zero
at tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute(DuMiSynchronizat
ionRetryRest.java:30)
... 2 more
日志显示异常,没有了clue.How我可以实现我的目标吗?
Spring Quartz BeanCreationException 问题
来自Springxml
<bean id="cronJobRetryImplTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean" lazy-init="true">
<property name="targetObject">
<ref bean="cronJobRetryImpl" />
</property>
<property name="targetMethod">
<value>execute</value>
</property>
<property name="concurrent" value="false" />
</bean>
未指定 MethodInvoker(MethodInvokingJobDetailFactoryBean
extend) 的参数,因此假定没有参数。结果异常
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cronJobRetryImplTask' defined in class path resource [applicationContext-job.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodException: tv.huan.cms.services.rest.DuMiSynchronizationRetryRest.execute()
被抛出,因为在 DuMiSynchronizationRetryRest
class.
execute
要解决此问题,应使用 JobDetailFactoryBean
而不是 Java Doc of MethodInvokingJobDetailFactoryBean
MethodInvokingJobDetailFactoryBean
Avoids the need for implementing a one-line Quartz Job that just invokes an existing service method on a Spring-managed target bean.
然而,DuMiSynchronizationRetryRest
是作为 Quartz 作业实现的,并且使用作业的 execute
方法,这需要 JobExecutionContext
。在这种情况下,JobDetailFactoryBean
应该是合适的工厂 bean。要更改工厂 bean,只需将 cronJobRetryImplTask 的 bean 定义更新为
<bean id="cronJobRetryImplTask"
class="org.springframework.scheduling.quartz.JobDetailFactoryBean"
lazy-init="true">
<property name="jobClass">
<value>gov.housingauthority.pass.app.DuMiSynchronizationRetryRest
</value>
</property>
</bean>
因为cronJobRetryImpl
bean在改变@Service
注解后不需要
也可以删除。
最后,由于 StatefulJob
已弃用,如 Java Doc of StatefulJob、
use DisallowConcurrentExecution and/or PersistJobDataAfterExecution annotations instead.
作业不立即重试问题
作业没有立即重试的问题,这是由于使用
e2.refireImmediately();
,这是一个getter only.To 设置重新启动标志:
对于 quartz 1.5.2 或之前的版本,
我们可以使用 new JobExecutionException(e, true)
,其中第二个参数会将 refireImmediately
设置为 true。
1.7.2版本后,提供setter方法setRefireImmediately(boolean refireImmediately);