无法在Spring cron中执行Quartz作业

时间:2018-10-31 02:01:40

标签: java spring-mvc jobs stateful quartz

类似的问题似乎已经被问过很多次了,但是我仍然找不到确切的答案。我使用org.quartz.StatefulJob来设置一个排定的作业,通过模拟Exception和Spring cron来重试5次。触发它,但发生了一些异常,详细信息如下:

@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:20 AM触发一次,结果是:

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$1.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$1.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的耐心和努力,但是代码本身似乎存在问题。我尝试运行这些代码,但是在发生模拟异常时无法再次执行该作业:

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

日志显示了一个异常,没有更多线索。我如何实现我的目标?

1 个答案:

答案 0 :(得分:0)

Spring Quartz BeanCreationException问题

从Spring xml

<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>

未指定MethodInvokerMethodInvokingJobDetailFactoryBean扩展)的参数,因此它假定没有参数。结果是例外

  

由以下原因引起:org.springframework.beans.factory.BeanCreationException:在类路径资源[applicationContext-job.xml]中定义名称为'cronJobRetryImplTask​​'的bean创建时出错:调用init方法失败;嵌套的异常是java.lang.NoSuchMethodException:tv.huan.cms.services.rest.DuMiSynchronizationRetryRest。 execute()

抛出

,因为在execute类中没有方法DuMiSynchronizationRetryRest没有参数。

要解决此问题,请使用JobDetailFactoryBean代替Java Doc of MethodInvokingJobDetailFactoryBean

中所说的MethodInvokingJobDetailFactoryBean
  

避免了实现仅在Spring管理的目标bean上调用现有服务方法的单行Quartz Job

但是,DuMiSynchronizationRetryRest被实现为Quartz Job,并使用execute的Job方法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注释后不需要@Service bean 也可以删除。

最后,由于Java Doc of StatefulJob中的建议,StatefulJob已过时,

  

使用DisallowConcurrentExecution和/或PersistJobDataAfterExecution   注释。

作业不立即重试问题

对于作业不能立即重试的问题,这是由于使用 e2.refireImmediately();,这只是一个吸气剂。要设置重发射标志:

对于版本1.5.2或之前的石英, 我们可以使用new JobExecutionException(e, true),其中第二个参数会将refireImmediately设置为true。

在1.7.2版之后,提供了setter方法setRefireImmediately(boolean refireImmediately);