javaspringspring-bootquartz-schedulerjdbctemplate

JdbcTemplate is not automatically injected (&quartz)


JobController.java (POST/testjob)-> to start quartz Scheduler

(POST/testjob => start Scheduler => QuartzJob.java => run execute => HelloJob do runJob())

BUT When userRepository.printData(), I got error NullPointerException from

@Autowired
    private JdbcTemplate jdbcTemplate;

JobController :

@RestController
public class JobController {
    
    public static SchedulerFactory sf;
    public static Scheduler sched;
    public static CronTrigger trigger;
    public static JobDetail jobDetail;
    
    @RequestMapping(path = "/testjob", method = RequestMethod.POST)
    public String testjob() {
        Class c;
        
        try {
            c = Class.forName("com.demo.jobs.HelloJob");
            sf = new org.quartz.impl.StdSchedulerFactory();
            sched = sf.getScheduler();

            jobDetail = JobBuilder.newJob(c).withIdentity("myJob", "group1").build();
            trigger = (CronTrigger) TriggerBuilder.newTrigger()
                    .withIdentity("myTrigger", "group1")
                    .withSchedule(CronScheduleBuilder.cronSchedule("0/5 0-59 0-23 * * ?"))
                    .build();

            sched.scheduleJob(jobDetail, trigger);
            sched.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return "testjob!";
    }
}

QuartzJob.java

@DisallowConcurrentExecution
public abstract class QuartzJob implements Job {
    
    public abstract void runJob() throws Exception;
    
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            runJob();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

HelloJob.java:

public class HelloJob extends QuartzJob {
    
    @Autowired
    private UserRepository userRepository;

    @Override
    public void runJob() throws Exception{
        try {
            userRepository.printData();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

UserImpl.java:

@Repository
public class UserImpl implements UserRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public void printData() {
        List<User> result = jdbcTemplate.query(" SELECT * FROM USER ",
                new BeanPropertyRowMapper<User>(User.class), new Object[] {});
        for (User u : result) {
            System.out.println("name: " + u.getName() + " ~ " + "phone: " + u.getPhone());
        }
    }
}

Does anybody have some experience with it? How to do it better? THANKS~

github_demo:https://github.com/qxgnbryoo81014/demo


Solution

  • The HelloJob is not manage by spring.you can use util acquire UserRepository obj like this:

    private UserRepository userRepository;
    
    public HelloJob() {
        this.userRepository = SpringBeanUtils.getBean(UserRepository.class);
    }
    

    The SpringBeanUtils :

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