Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring and Quartz integration with Java Config

I searched a lot, but i couldn't fine any post or comment or any complete code on integrating spring and quartz and store the quartz config in database with java config (XML-LESS) could anyone help me and show me some code or reference ? thanks a lot

like image 498
hadi Avatar asked Jan 07 '23 20:01

hadi


1 Answers

We can implement it like this -
1) Annotations

Class level Annotation :
Only this class will be scan for quartz support-

package com.example.config;  

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface QuartzJob{


}


Method Level Annotation : Annotation holds property of quartz configuration

package com.example.config;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cron {

    String name();

    String group() default "DEFAULT_GROUP";

    String cronExp();

    String timeZone() default "Europe/London";
}

2) create Beans holding methods to run as cron job

package com.example.job;
public class AnotherBean  {
public void print(){
    System.out.println("I am printing in another bean");
}
}
package com.example.job;

import org.springframework.beans.factory.annotation.Autowired;

import com.example.config.Cron;
import com.example.config.QuartzJob;


@QuartzJob
public class MyJobOne {

    @Autowired
    private AnotherBean anotherBean;
    protected void myTask() {
        System.out.println("This is my task");
    }

    protected void myTask1() {
        System.out.println("This is love task");
    }


    @Cron(name="abc", cronExp="* * * * * ? *", timeZone="Asia/Kolkata")
    protected void scheduleMyJob() {
        System.out.println("This is lovely task");
        anotherBean.print();
    }

    @Cron(name="xyz", cronExp="0 35 9 ? * MON-FRI", timeZone="Asia/Kolkata")
    protected void scheduleMyJob1() {
        System.out.println("This is hate task");
    }
}

3) Listener to look into bean and initiate Job

package com.example.config;


import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;

public class QuartJobSchedulingListener implements ApplicationListener<ContextRefreshedEvent>
{ 


 @Override
 public void onApplicationEvent(ContextRefreshedEvent event)
 {
  try 
  {
    ApplicationContext applicationContext = event.getApplicationContext();
    List<CronTrigger> cronTriggerBeans = this.loadCronTriggerBeans(applicationContext);
    if(cronTriggerBeans.size() > 0){
        SchedulerFactoryBean schedulerFactoryBean =  applicationContext.getBean(SchedulerFactoryBean.class, cronTriggerBeans);
        schedulerFactoryBean.start();
    }

  } 
  catch (Exception e) 
  {
    e.printStackTrace();
  }
 }

 private List<CronTrigger> loadCronTriggerBeans(ApplicationContext applicationContext)
 {
   Map<String, Object> quartzJobBeans = applicationContext.getBeansWithAnnotation(QuartzJob.class);

   Set<String> beanNames = quartzJobBeans.keySet();

   List<CronTrigger> cronTriggerBeans = new ArrayList<CronTrigger>();

   for (String beanName : beanNames) 
   {
     Object bean = quartzJobBeans.get(beanName);

     ReflectionUtils.doWithMethods(bean.getClass(), new MethodCallback(){

        @Override
        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
            if(method.isAnnotationPresent(Cron.class)){
                Cron cron = method.getAnnotation(Cron.class);
                System.out.println("Scheduling a job for "+ bean.getClass()+ " and method "+method.getName());
                MethodInvokingJobDetailFactoryBean jobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
                jobDetailFactoryBean.setName(beanName+"."+cron.name()+"."+method.getName());
                jobDetailFactoryBean.setTargetMethod(method.getName());
                jobDetailFactoryBean.setTargetObject(bean);

                try {
                    jobDetailFactoryBean.afterPropertiesSet();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                CronTriggerFactoryBean triggerFactoryBean = new CronTriggerFactoryBean();

                triggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
                triggerFactoryBean.setName(beanName+"_trigger_"+method.getName());
                triggerFactoryBean.setCronExpression(cron.cronExp()); 
                GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone(cron.timeZone()));
                System.out.println(calendar.getTime());
                triggerFactoryBean.setStartTime(calendar.getTime());
                triggerFactoryBean.setTimeZone(TimeZone.getTimeZone(cron.timeZone()));

                try {
                    triggerFactoryBean.afterPropertiesSet();
                    System.out.println(triggerFactoryBean.getObject().getFinalFireTime());
                    System.out.println(triggerFactoryBean.getObject().getCronExpression());
                } catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                cronTriggerBeans.add(triggerFactoryBean.getObject());
            }
        }

     });

   }

   return cronTriggerBeans;
 }


 public Trigger getCronTrigger(String cronExpression){
      CronScheduleBuilder cronScheduleBuilder=null;
      Trigger cronTrigger=null;
      cronScheduleBuilder=CronScheduleBuilder.cronSchedule(cronExpression);
    cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
    TriggerBuilder<Trigger> cronTtriggerBuilder=TriggerBuilder.newTrigger();
    cronTtriggerBuilder.withSchedule(cronScheduleBuilder);
    cronTrigger=cronTtriggerBuilder.build();

      return cronTrigger;
    }

}

4) Creating JavaConfig class-

package com.example.config;

import java.util.List;

import org.quartz.CronTrigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.example.job.AnotherBean;
import com.example.job.MyJobOne;

@Configuration 
public class QuartzConfiguration {

    @Bean
    public QuartJobSchedulingListener quartJobSchedulingListener(){
        return new QuartJobSchedulingListener();
    }

    @Bean
    public MyJobOne myJobOne(){
        return new MyJobOne(); 
    }

    @Bean(name="scheduler")
    @Scope(value="prototype")
    public SchedulerFactoryBean schedulerFactoryBean(List<CronTrigger> triggerFactoryBeans) {
        SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
        CronTrigger[] cronTriggers = new CronTrigger[triggerFactoryBeans.size()];
        cronTriggers = triggerFactoryBeans.toArray(cronTriggers);
        scheduler.setTriggers(cronTriggers);
        System.out.println(cronTriggers[0].getCronExpression());
        System.out.println(cronTriggers[0].getCalendarName());
        System.out.println(cronTriggers[0].getTimeZone());
        System.out.println(cronTriggers[0].getEndTime());
        return scheduler;
    }

    @Bean
    public AnotherBean anotherBean(){
        return new AnotherBean();
    }
}  

5) Creating main class to test it

package com.example;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import com.example.config.QuartzConfiguration;
@ComponentScan
@EnableAutoConfiguration
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(QuartzConfiguration.class);
        context.refresh();
    }
}
like image 130
Sushil Avatar answered Jan 15 '23 14:01

Sushil