2

I am using .NET MVC 4. All services are injected using Ninject. I am trying to schedule a job using Quartz. Right now, jobs are registered in Global.asax as follows:

Global.asax:

protected void Application_Start() {
    // ... configuration stuff

    ScheduledJobs.RegisterJobs();
}

ScheduleJobs.cs has the ScheduledJobs class, which creates jobs with triggers and adds them to a standard schedule.

In ScheduleJobs.cs:

public class ScheduledJobs {

  public static void RegisterJobs() {
    IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();

    scheduler.Start();

    IJobDetail job = JobBuilder.Create<JobUsingService>()
        .WithIdentity("JobUsingService")
        .Build();

    ITrigger trigger = TriggerBuilder.Create()
        .WithDailyTimeIntervalSchedule(s =>
            s.WithIntervalInHours(1)
            .OnEveryDay()
            .StartingDailyAt(new Quartz.TimeOfDay(DateTime.Now.Hour, DateTime.Now.Minute)))
        .Build();

    scheduler.ScheduleJob(job, trigger);
  }
}

This is the job code:

public class JobUsingService : IJobUsingService, IJob {

   private ISomeService someService;

   public JobUsingService(ISomeService _someService) {
       someService = _someService;
   }

   public void Execute(IJobExecutionContext context) {
       someService.someStuff();
   }
}

The problem is that JobUsingService has to be initialized using Ninject so that SomeService is injected into it (also by Ninject). Calling IJobDetail job = JobBuilder.Create<JobUsingService>().WithIdentity("JobUsingService").Build(); skips over the Ninject injection and creates a regular instance of the class without injecting the necessary services.

How can I create a job of type JobUsingService using Ninject?

This SO answer suggests creating a NinjectJobFactory, but I am not sure how to actually use this factory and create jobs.

Community
  • 1
  • 1
lpytel
  • 105
  • 1
  • 9

2 Answers2

3

Yes you'll have to use the NinjectJobFactory of the referenced answer. In an app initialization routine (Application_Start or wherever you configure the application to use ninject. Just after the creation of the kernel) you have to do:

Quartz.IScheduler.JobFactory = kernel.Get<NinjectJobFactory>();

or alternatively:

Quartz.IScheduler.JobFactory = new NinjectJobFactory(kernel);

(doesn't matter which, they're completely interchangeable)

From then on Quarty will create the job types (JobUsingService using the NinjectJobFactory which in turns uses the kernel to create the jobs...

Community
  • 1
  • 1
BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
2

In the end, we needed to add the NinjectJobFactory class described in this SO answer

We also had to make the following changes:

In ScheduleJobs.cs:

public class ScheduledJobs {

    public static void RegisterJobs() {
        // Create a new kernel and create the necessary bindings
        IKernel kernel = new StandardKernel();
        kernel.Bind<IJobUsingService>().To<JobUsingService>();

        // Create a scheduler and give it the Ninject job factory created earlier
        IScheduler scheduler = new StdSchedulerFactory().GetScheduler();
        scheduler.JobFactory = new NinjectJobFactory(kernel);

        // Create the job with the interface which will be injected
        IJobDetail job = JobBuilder.Create<IJobUsingService>()
             .WithIdentity("IJobUsingService")
             .Build();

         // Create the trigger
         ITrigger trigger = TriggerBuilder.Create()
             .WithDailyTimeIntervalSchedule(s =>
                 s.WithIntervalInHours(23)
                  .OnEveryDay()
                  .StartingDailyAt(new Quartz.TimeOfDay(DateTime.Now.Hour, DateTime.Now.Minute)))
             .Build();

         scheduler.ScheduleJob(job, trigger);
    }
}
Community
  • 1
  • 1
lpytel
  • 105
  • 1
  • 9