0

I am trying to send an email from a class that implements Quartz Job, in order to do that I have to @Autowire the IEmailService inside the class.

Here is the method I use to create a Quartz Job:

@Override
    public Boolean sendInfoEmail(ManifestationProp manifProp, ServletRequest request) throws SchedulerException {             
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String token = httpRequest.getHeader("jwt_token");  
        if(token == null) {
            System.out.println("(ManifestationPropDaoImp) - TOKEN NULL");
            return false;
        }           
        String email = tokenUtils.getUsernameFromToken(token);      
        User user = userDao.findUserByEmail(email);         
        if(update(manifProp) != null) {             
            Scheduler sc = StdSchedulerFactory.getDefaultScheduler();
            sc.start();
            JobKey jobKey = new JobKey("Job_"+manifProp.getId(),"group1");
            if(!sc.checkExists(jobKey)) {                                   System.out.println("-----------------------------------------------");
                System.out.println("Scheduling a Job for Manifestation Prop with ID - "+ manifProp.getId());
                System.out.println("Current time - " + new Date());
                System.out.println("Scheduled time - NOW" );
                System.out.println("User - "+ user.getEmail());
                System.out.println("Manifestation Prop - "+manifProp.getName());    
                JobDataMap jdm = new JobDataMap();
                jdm.put("manifProp",manifProp);
                jdm.put("user", user);
                JobDetail jobDetail = JobBuilder.newJob(QuartzInformUser.class)
                                                .withIdentity(jobKey)
                                                .usingJobData(jdm)
                                                .build();
                Trigger t = TriggerBuilder.newTrigger().withIdentity("SimpleTrigger_"+manifProp.getId()).startNow().build();
                sc.scheduleJob(jobDetail, t);
                System.out.println("-----------------------------------------------");
            }else {
                System.out.println(" *** Job_"+manifProp.getId()+" already exists! *** ");
            }
            return true;
        }else {
            System.out.println("Could not update manifestation prop!");
        }
        return false;
    }

Here is the code of the class which implements Job interface:

@Service
public class QuartzInformUser implements Job{

    @Autowired
    IEmailService emailService;

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {   
        try {
            JobDataMap dataMap = arg0.getJobDetail().getJobDataMap();  
            User user = (User)dataMap.get("user");
            ManifestationProp manifProp = (ManifestationProp)dataMap.get("manifProp"); 
            System.out.println("USER: "+user);
            System.out.println("MANIFESTATION PROP: "+manifProp);
            emailService.informUser(user,manifProp);            
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

Quartz Job gets created perfectly fine, the problem is in the class QuartzInformUser. Spring does not inject IEmailService into the class, therefore the field emailService is null and i get the following exception:

enter image description here

If anyone has any idea how can i fix this issue I would really appreciate the help! Thank you in advance!

TwiN
  • 3,554
  • 1
  • 20
  • 31
Stefan Radonjic
  • 1,449
  • 4
  • 19
  • 38
  • What about using the brand-new [Spring Boot Quartz starter](https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-quartz/2.0.1.RELEASE)? Unfortunately I haven't had enough time to learn how to use it. – joninx Apr 16 '18 at 14:48

2 Answers2

1

You will want to use the spring helpers/implementations of the various Quartz components, so that the jobs you create will be managed by spring.

... are two good starting points (although you'll want to make sure the documentation you look at is appropriate for the version of spring you're using; spring-boot for example has a starter for scheduling/quartz)

mrusinak
  • 1,002
  • 1
  • 12
  • 22
0

Did you add AutowiringSpringBeanJobFactory in your project? This will add the support of autowiring to quartz jobs.

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

    private transient AutowireCapableBeanFactory beanFactory;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        beanFactory = applicationContext.getAutowireCapableBeanFactory();        
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        return job;
    }
}

You also need to create a jobFactory and set the application context to your quartz jobs. This should be in a @Configuration class

 @Bean
 public JobFactory jobFactory(ApplicationContext applicationContext)
 {
     AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
     jobFactory.setApplicationContext(applicationContext);
     return jobFactory;
 }

(Just copy and paste this class in your project)

Patrick
  • 12,336
  • 15
  • 73
  • 115
  • I have just created this class. Would you please be kind enough to let me know how does this class fit into my code? – Stefan Radonjic Apr 16 '18 at 14:54
  • I added some more code. You will need the configuration to enable the support of autowiring to your quartz jobs – Patrick Apr 16 '18 at 15:57