在 JobController.java
@RequestMapping(path = "/testjob", method = RequestMethod.POST)
這個主要是呼叫 HelloJob.java
去執行每 5秒取 DB 資料印出來這樣的功能
[========]
但是丟 POST/testjob 過去,都會出現 NullPointerException
的錯誤。找了一下發現是 UserImpl.java
內的 jdbcTemplate
沒有被自動注入 ↓↓↓
(如果把@Autowired
private JdbcTemplate jdbcTemplate
放到 controller 內好像就找的到了)
**寫法上如何更好或者哪邊機制沒弄熟丟文章給我都可以,麻煩各位指導方向了!! 謝謝!
Hi,
我簡單試了一下 不過錯誤並不是顯示JDBCTemplate的注入失敗, 可能跟我有修改DB的部份有關? 但我看了一下JDBCTemplate應該是沒啥問題的 如果對注入有疑問可以試著加入actuator對注入的bean做檢查
我測試時報錯的是找不到UserRepository, 會這樣主因是因為排程是單獨被拉出來的 他看不到spring的相關設定, 如果在已經是spring的環境, 應該試著使用spring處理會比較簡單(包括對DB的操作, e.g. spring data)
如果使用spring scheduler的話, 基本上程式應該不太需要做太多調整
如果不想透過spring的元件來處理的話, 可以找看看比較古老的spring的版本是怎麼被quartz取得bean的, 或換句話說, 是怎麼取得applicationcontext
附上這邊測試的code
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
JobController
package com.demo.controller;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JobController {
@Autowired
private Scheduler scheduler;
public CronTrigger trigger;
public JobDetail jobDetail;
@RequestMapping(path = "/testjob", method = RequestMethod.GET)
public String testjob() {
try {
jobDetail = JobBuilder.newJob(com.demo.controller.jobs.HelloJob.class).withIdentity("myJob", "group1").build();
trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0/5 0-59 0-23 * * ?"))
.build();
scheduler.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
e.printStackTrace();
}
return "testjob!";
}
}
感謝分享,原來一直以為 @Autowired
不管在哪個 class 都可以取得 spring 底下的 bean。
後來又一直測試的結論是 JobBuilder.newJob(c)
給定class&後來呼叫runJob()
時就不受 spring 管理了
jobDetail = JobBuilder.newJob(c)
解法是後來到 stackoverflow 詢問後的結果~ 順便分享一下。
@Component
public class SpringBeanUtils implements ApplicationContextAware{
private static ApplicationContext context;
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
public static ApplicationContext getApplicationContext() {
Assert.notNull(context, "applicationContext must be not null");
return context;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringBeanUtils.context = applicationContext;
}
}
public class HelloJob extends BaseJob {
private UserRepository userRepository;
public HelloJob() {
this.userRepository = SpringBeanUtils.getBean(UserRepository.class);
}
...
如果是透過Spring的quartz就不需要做這些處理了, 他會幫你全部弄好. 這種寫法在舊的spring版本上才比較會看到
autowired的話 其實有個更簡單的判斷方法, 你可以試著改用setter或constructor的方式注入, 就會發現他拿不到了