繁体   English   中英

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

[英]Spring Boot : Use @Autowired within a Quartz Job

我设法在 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();
      }
}

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

其次,为了在 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();
        }
      }
}

然后:

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

</bean>

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

友情链接

我在做什么有什么问题?

更新 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);
      }
}

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

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

My job is running with null 0

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

更新 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();
        }       
    }  
}

服务实现:

@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();
            }
    }
}

我的工作:

public class MyJob extends QuartzJobBean{

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

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>

石英属性:

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

控制台:

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

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

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

从链接粘贴相关信息:

更新:extends QuartzJobBean替换implements Job

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);
    }
}

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

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

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

我解决了在工作中实施“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 {
        }
    }

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

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

我们可以使用 JobDataMap 来传递对象。

例如:这里 restTemplate 是自动装配的。

JobDataMap newJobDataMap = new JobDataMap();
newJobDataMap.put("restTemplate", restTemplate);

JobDetail someJobDetail = JobBuilder
.newJob(QuartzJob.class)
.withIdentity(jobName, GROUP)
.usingJobData(newJobDataMap)
.build();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM