0

I have list of templates and each has different set of parameters , and each template has to execute at specific time.How do i approach this problem in Quartz scheduler

 Template  Parameters list                 Time of execution
 T1        ['date','frequency']            3:30 AM
 T2        ['Id']                          10:20 AM
 T3        ['customerid','houseNo','Info'] 6:06 PM

and execute() method will perform some operation on parameter list for each template.I want to do this in a single Quartz job. I was trying something like this :

  def list = ["*/2 * * * * ?","*/10 * * * * ?","*/20 * * * * ?"]
  String triggerName;
  int j=0;
  for(cronExpr in list)
  {
        j++;
        triggerName="trigger"+Integer.toString(j)
        triggerName = new CronTrigger();
        triggerName.setName(triggerName);
        triggerName.setGroup(job.getGroup());
        triggerName.setJobName(job.getName());
        triggerName.setJobGroup(job.getGroup());
        triggerName.setCronExpression(cronExpr);
  }

I have asked similar question before without any satisfactory answer ,it would be very helpful if someone can provide a better way to approach this problem along with some guide or useful link on quartz scheduling which can walk me through basic and advanced topics so that i have better understanding on how to use multiple triggers or some way to approach the above problem.

elyon
  • 181
  • 2
  • 6
  • 16

1 Answers1

0

What I would probably do in your case is that I would create multiple triggers for a single job that implements the required business logic that is common to all your templates.

Each trigger would have the template parameters specified in its JobDataMap that you can associated with a trigger. Once your job gets triggered and its execute method is invoked you can use the following code to access the relevant template parameters:

context.getMergedJobDataMap()

See the getMergedJobDataMap JavaDoc for details.

Example in Java:

    public class TemplateJob implements Job {

      public void execute(JobExecutionContext context)
        throws JobExecutionException
      {
        JobDataMap dataMap = context.getMergedJobDataMap();

        String templateId = dataMap.getString("templateId");

        if ("T1".equals(templateId))
        {
          // template1 params
          String t1Date = dataMap.getString("date");
          String t1Frequency = dataMap.getString("frequency");

          doTemplate1Logic(t1Date, t1Frequency);
        }
        else if ("T2".equals(templateId))
        {    
          // template2 params
          String t2Id = dataMap.get("Id");

          doTemplate2Logic(t1Id);
        }    
        else if ("T3".equals(templateId))
        {    
          // template3 params
          String t3CustomerId = dataMap.get("customerid");
          String t3HouseNo = dataMap.get("houseNo");
          String t3Info = dataMap.get("Info");

          doTemplate3Logic(t1Id);
        }
        else
        {
          throw new JobExecutionException("Unrecognized template ID: " + templateId);
        }
      }

      ...
    }


    public class TestCase
    {
      public static void main(String[] args)
      {
        Scheduler scheduler = ....

        JobDetail templateJob = JobBuilder.newJob(TemplateJob.class)
          .withIdentity("templateJob", "myJobGroup")
          .build();          

        // trigger for Temlate1
        Trigger template1Trigger = TriggerBuilder.newTrigger()
          .withIdentity("template1Trigger", "myTriggerGroup")
          .withSchedule(TriggerBuilder.cronSchedule("*/2 * * * * ?"))
          .usingJobData("date", "...")
          .usingJobData("frequency", "...")
          .forJob("templateJob", "myJobGroup")
          .build();      
        scheduler.scheduleJob(templateJob, template1Trigger);

        // trigger for Temlate2
        Trigger template2Trigger = TriggerBuilder.newTrigger()
        ...
        scheduler.scheduleJob(templateJob, template2Trigger);

        ...
      }
    }

If the template processing logic differs significantly for individual templates, you should probably implement a separate job for each of your templates.

Jan Moravec
  • 1,808
  • 1
  • 15
  • 18
  • hi jan ..can you provide me with a basic code that uses JobDataMap inside the Quartz scheduler job and each time passes different parameters...even a basic code will do.I also wanted to know if triggers {} and execute() are mandatory in any quartz job ? – elyon Jan 08 '15 at 20:32
  • OK, added sample code. Hopefully you can get the idea and port it to Grails. As for your questions, I am not sure about Grails, but in Java, the execute method is mandatory. A job can have 0 to N triggers. Please note that when you have a job without any associated triggers and you execute the job, then unless the job is marked as durable, the job will be automatically deleted by Quartz as soon as it completes. I suggest that you read through Quartz documentation including the tutorials. – Jan Moravec Jan 08 '15 at 21:10
  • Thanks a lot for the code :) was trying it out --> JobDetail TrialJob = JobBuilder.newJob(TemplateJob.class) this line fails (Groovy:Apparent variable 'TemplateJob' was found in a static scope but doesn't refer to a local variable, static field or class.) ? – elyon Jan 08 '15 at 22:55
  • JobBuilder is a class in the or.quartz package and its javadoc is here http://quartz-scheduler.org/api/2.2.1/org/quartz/JobBuilder.html. You will notice the the JobBuilder uses a so-called fluent API and that means that you can chain its methods like so JobBuilder.usingJobJavaMap("p1", ...).usingJobDataMap("p2", ...). – Jan Moravec Jan 09 '15 at 13:12
  • hi jan is it required that both of these classes should be inside grails-app/jobs .is it required that the test class also be created by using grails create-job :jobname ? as i am getting error at this line JobDetail TemplateJob = JobBuilder.newJob(TemplateJob.class) Groovy:Apparent variable 'TrialJob' was found in a static scope but doesn't refer to a local variable, static field or class – elyon Jan 09 '15 at 20:51
  • The test class was created to show you the concept only. You do not need this class. In general, all (Quartz) classes that you invoke from your app MUST be on your application's classpath. How you do it in Grails I do not know, I am showing you the concepts, the actual coding and figuring out the dependencies is up to you - I do not know your application, your set up etc. – Jan Moravec Jan 09 '15 at 22:38