java Spring Boot:在 Quartz 作业中使用 @Autowired

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37623430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 02:39:25  来源:igfitidea点击:

Spring Boot : Use @Autowired within a Quartz Job

javaspringquartz-schedulerinject

提问by Daniel

I managed to configure and schedule a Quartz job using JobStoreTX persistent store in Spring Boot ( version 4.2.5 ). Here is how I schedule the job. First :

我设法在 Spring Boot(版本 4.2.5)中使用 JobStoreTX 持久存储配置和安排 Quartz 作业。这是我安排工作的方式。第一的 :

public class MyJob implements Job{
    @Autowired
    IService service;

    @Override
      public void execute(JobExecutionContext context) throws JobExecutionException {
        service.doSomething();
      }
}

@Autowiredseems like it wont work in a Quartz job implementation because it wont be instantiated by Spring. Hence, im facing the famous JavaNullPointerException.

@Autowired似乎它不会在 Quartz 作业实现中工作,因为它不会被 Spring 实例化。因此,我面临着著名的 JavaNullPointerException。

Second, in order to get hold of Spring-managed beans in a Quartz job, I used org.springframework.scheduling.quartz.SchedulerFactoryBeanto manage the Quartz lifecycle :

其次,为了在 Quartz 作业中获取 Spring 管理的 bean,我曾经org.springframework.scheduling.quartz.SchedulerFactoryBean管理 Quartz 生命周期:

public class MyJob implements Job{

    @Override
      public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            ApplicationContext applicationContext = (ApplicationContext) context.getScheduler().getContext().get("applicationContext");
            IService service= applicationContext.getBean(IService.class);
            service.getManualMaxConfig();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
      }
}

And then :

接着 :

<bean id="scheduler"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="applicationContextSchedulerContextKey" value="applicationContext" />

</bean>

The sad news is that im also facing JavaNPE. I also try these suggestions, in vain ..

可悲的消息是我也面临 JavaNPE。我也尝试了这些建议,但徒劳..

LINK

关联

Whats wrong with what im doing?

我在做什么有什么问题?

Update 1 :Before trying to inject service, i tried to pass some Params as @ritesh.garg suggests.

更新 1:在尝试注入服务之前,我尝试按照 @ritesh.garg 的建议传递一些参数。

public class MyJob implements Job{

    private String someParam;
    private int someParam2;

    public void setSomeParam(String someParam) {
        this.someParam = someParam;
    }


    public void setSomeParam2(int someParam2) {
        this.someParam2 = someParam2;
    }

    @Override
      public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("My job is running with "+someParam+' '+someParam2);
      }
}

And my jobBean.xml looks like :

我的 jobBean.xml 看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean id="scheduler"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="applicationContextSchedulerContextKey" value="applicationContext" />

</bean> 


<bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.quartz.service.MyJob"/>
    <property name="jobDataAsMap">
        <map>
            <entry key="someParam" value="some value"/>
            <entry key="someParam2" value="1"/>
        </map>
    </property>
</bean>

</beans>

I dont know why, but the parameters arent passed and it prints :

我不知道为什么,但没有传递参数并打印:

My job is running with null 0

My job is running with null 0

Ps : I imported the jobBean.xml into Application.java . So i dont know what am i missing ?

Ps:我将 jobBean.xml 导入到 Application.java 中。所以我不知道我错过了什么?

Update 2 :Here is my detailed code :

更新 2:这是我的详细代码:

@Component
public class JobScheduler{
    Timer timer = new Timer();    
   @PostConstruct
    public void distributeAutomaticConf(){
        try {
            timer.schedule(new ServiceImpl(), 10000);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
    }  
}

Service Impl :

服务实现:

@Transactional
@Component
public class ServiceImpl extends TimerTask implements IService{

@Override
    public void run() {
         final SchedulerFactory factory = new StdSchedulerFactory();
            Scheduler scheduler = null;

            try {
              scheduler = factory.getScheduler();


                  final JobDetailImpl jobDetail = new JobDetailImpl();
                  jobDetail.setName("My job executed only once.. ");
                  jobDetail.setJobClass(MyJob.class);

              SimpleTrigger trigger = (SimpleTrigger) newTrigger()
                        .withIdentity("trigger_", "group_")
                        .build(); 
              scheduler.start();
              scheduler.scheduleJob(jobDetail, trigger);

              System.in.read();
              if (scheduler != null) {
                scheduler.shutdown();
              }
            } catch (final SchedulerException e) {
              e.printStackTrace();
            } catch (final IOException e) {
              e.printStackTrace();
            }
    }
}

MyJob :

我的工作 :

public class MyJob extends QuartzJobBean{

    @Autowired
    IService service;
    @Override
    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {         SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);    
        service.doSomething();  
    }
}

jobBean.xml :

jobBean.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean id="scheduler"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="applicationContextSchedulerContextKey" value="applicationContext" />

</bean> 


<bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.quartz.service.MyJob"/>
    <property name="jobDataAsMap">
        <map>
            <entry key="someParam" value="some value"/>
            <entry key="someParam2" value="1"/>
        </map>
    </property>
</bean>

</beans>

quartz.properties :

石英属性:

org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 60000

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_

org.quartz.dataSource.myDS.driver = org.postgresql.Driver
org.quartz.dataSource.myDS.URL = jdbc:postgresql://localhost:5432/myDB
org.quartz.dataSource.myDS.user = admin
org.quartz.dataSource.myDS.password = admin
org.quartz.dataSource.myDS.maxConnections = 10

org.quartz.scheduler.skipUpdateCheck=true

console :

安慰 :

java.lang.NullPointerException: null
    at com.quartz.service.MyJob.executeInternal(MyJob.java:27) ~[classes/:na]
    at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113) ~[spring-context-support-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.2.1.jar:na]
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.2.1.jar:na]

2016-06-05 11:35:16.839 ERROR 25452 --- [eduler_Worker-1] org.quartz.core.ErrorLogger              : Job (DEFAULT.My job executed only once..  threw an exception.

org.quartz.SchedulerException: Job threw an unhandled exception.
    at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-2.2.1.jar:na]
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.2.1.jar:na]
Caused by: java.lang.NullPointerException: null
    at com.quartz.service.MyJob.executeInternal(MyJob.java:27) ~[classes/:na]
    at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113) ~[spring-context-support-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.2.1.jar:na]
    ... 1 common frames omitted

回答by ritesh.garg

I have experienced the same problem in past. My understanding on this issue is that beans instantiated in spring context cannot be injected in quartz context simply by using @Autowiredannotation.

我过去遇到过同样的问题。我对这个问题的理解是,在 spring 上下文中实例化的 bean 不能简单地通过使用@Autowired注释注入到quartz 上下文中。

I managed to solve it by using setter based dependency injection. But the same is mentioned in the "LINK" you have added in the original post.

我设法通过使用基于 setter 的依赖注入来解决它。但是您在原始帖子中添加的“链接”中也提到了同样的内容。

Pasting the relevant information from the link:

从链接粘贴相关信息:

Update:Replaced implements Jobwith extends QuartzJobBean

更新:替换implements Jobextends QuartzJobBean

public class MyJob extends QuartzJobBean {
    private String someParam;
    private int someParam2;

    public void setSomeParam(String someParam) {
        this.someParam = someParam;
    }

    public void setSomeParam2(String someParam2) {
        this.someParam2 = someParam2;
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("My job is running with "+someParam+' '+someParam2);
    }
}

Here, someParam and someParam2 are being injected via setter dependency injection. Now the other part that makes this complete is to pass someParam and someParam2 in jobDataAsMap

在这里, someParam 和 someParam2 是通过 setter 依赖注入注入的。现在使这个完整的另一部分是传递 someParam 和 someParam2jobDataAsMap

<bean id="myJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.my.MyJob"/>
    <property name="jobDataAsMap">
        <map>
            <entry key="someParam" value="some value"/>
            <entry key="someParam2" value="1"/>
        </map>
    </property>
</bean>

In your case, it would be a value-ref="IserviceBeanId", instead of 'value' in entry. I would be surprised as well as curious, if this did not/does not work for you.

在您的情况下,它将是 value-ref="IserviceBeanId",而不是条目中的 'value'。如果这对您不起作用/不起作用,我会感到惊讶和好奇。

回答by Marcos Vinícius

I fix my problem implementing "InitializingBean" in my job;

我解决了在工作中实施“InitializingBean”的问题;

    public class MyJob extends QuartzJobBean implements InitializingBean {

        private String someParam;
        private int someParam2;

        public void setSomeParam(String someParam) {
            this.someParam = someParam;
        }

        public void setSomeParam2(String someParam2) {
            this.someParam2 = someParam2;
        }

        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            System.out.println("My job is running with "+someParam+' '+someParam2);
        }
        @Override
        public void afterPropertiesSet() throws Exception {
        }
    }

回答by Nikolay Hristov

The correct way from the most of the examples I've seen is to make your Job interface implementation a @Component

从我见过的大多数例子中,正确的方法是让你的 Job 接口实现成为 @Component

@Component
public class MyJob implements Job{ 
     @Autowired IService service; 
     @Override 
     public void execute(JobExecutionContext context) throws JobExecutionException{ 
          service.doSomething();
     } 
}