Sunday, April 27, 2014

Quartz Scheduler with Google Guice

To integrate Quartz with Guice. One can follow below steps. The most important part is, we should be able to inject dependencies inside Job.

To provide injectable Scheduler Instance we need to write Scheduler provider as follows:
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

/**
 * @author Pandurang Patil 27-Apr-2014
 * 
 */
@Singleton
public class SchedulerProvider implements Provider<Scheduler> {
 private Scheduler scheduler;

 @Inject
 public SchedulerProvider(SchedulerJobFactory jobFactory) throws SchedulerException {
  scheduler = new StdSchedulerFactory().getScheduler();
  scheduler.setJobFactory(jobFactory);
 }

 @Override
 public Scheduler get() {
  return scheduler;
 }

}


Now that we have defined provider for Scheduler we need to map the same inside Guice Module

import org.quartz.Scheduler;

import com.google.inject.AbstractModule;

/**
 * @author Pandurang Patil 27-Apr-2014
 *
 */
public class SchedulerModule extends AbstractModule {

 @Override
 protected void configure() {
  bind(Scheduler.class).toProvider(SchedulerProvider.class);
 }

}


With the above code, we should be able to inject Scheduler instance where we want. Lets look at how we would be able to get dependencies injected inside Job. As instantiation of the Job object is done by Scheduler itself, we just pass on the class name through JobDetails. We need intercept this instantiation process to do that we will write our own Job Factory as follows:

import org.quartz.Job;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;

import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;

/**
 * @author Pandurang Patil 27-Apr-2014
 * 
 */
@Singleton
public class SchedulerJobFactory implements JobFactory {

 @Inject
 private Injector injector;

 @Override
 public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
  return (Job) injector.getInstance(bundle.getJobDetail()
    .getJobClass());
 }

}

We need ask scheduler to use this JobFactory while instantiating Job object. We have already connected scheduler with JobFactory inside SchedulerProvider, look at line number 20 for SchedulerProvider code above
As we are returning same instance from Providers get method. Where ever you will inject Schedular, you will get the same object. Schedule your jobs the way it is done normally there is no change in it. 


import org.quartz.Scheduler;
import org.quartz.SchedulerException;

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;

/**
 * @author Pandurang Patil 27-Apr-2014
 * 
 */
public class SchedulerSample {

 @Inject
 private Scheduler scheduler;

 void start() throws SchedulerException {

  scheduler.start();
 }

 public static void main(String[] args) {
  Injector injector = Guice.createInjector(new SchedulerModule());
  SchedulerSample sample = injector.getInstance(SchedulerSample.class);
  try {
   sample.start();
  } catch (SchedulerException e) {
   System.out.println("Error while starting the scheduler...");
  }
  ...
  ...
 }
}


8 comments:

  1. Google Guice is basically used for AdWords product .

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Thanks for the blog.Proved to be helpful. I felt schedulerFactory can be injected instead of creating the object in provider. This dependency injection helps with unit testing

    ReplyDelete
  4. Where before you were constrained to one arrangement of promotions for countless keyterms, now you can target particular advertisements for particular keyterms. Edkent Media

    ReplyDelete
  5. Showbox not Working Error Looking a way How to fix Showbox not working error? Here is complete method which helps you to update Showbox for latest version

    ReplyDelete
  6. 192.168.0.1 D-Link Login is a private IP address (sometimes it could be mistyping to 192.168.o.1 or 192.168.0.l ), familiar to every router-user, who is setting up LAN-network

    ReplyDelete
  7. I would like to say thank you for the amazing details and concepts you are sharing in this.The style of writing is excellent and also the content is top-notch. Thanks for that shrewdness you provide the readers!

    Microstrategy Training in Chennai
    Microstrategy Training

    ReplyDelete