10 years late(r)

June 2, 2011

Quartz.NET IJob Dependency Injection With StructureMap

Filed under: Dependency Injection,Quartz.NET,StructureMap — asmiki @ 4:51 am

In the previous post we saw how to quickly setup scheduler solution with Quartz.NET in ASP.NET MVC application. Also, I blogged about how to setup SturctureMap IoC to work in your ASP.NET MVC project.

Though, there is not an obvious solution to inject dependencies in Quartz.NET IJob concrete class implementation using the IoC of your choice.

Let’s do this. First thing we need to change is how we get the Scheduler instance, so instead of having:

    // construct a scheduler factory
    ISchedulerFactory schedFact = new StdSchedulerFactory();

    // get a scheduler
    IScheduler sched = schedFact.GetScheduler();

we will have:

IScheduler sched = StructureMap.ObjectFactory.GetInstance();

To be able to test we will need MyModel and MyComponent the same way we created them in this blog post.

Then we are going to change the IJob implementation to have constructor overloaded dependency injection.

using System;
using System.Diagnostics;
using MyModel;
using Quartz;

namespace QuartzNetMvc.Jobs
{
    public class HelloJob : IJob
    {
        private readonly IBar _bar;
        public HelloJob(IBar bar)
        {
            _bar = bar;
        }

        public void Execute(JobExecutionContext context)
        {
            Debug.WriteLine("Hello at " + DateTime.Now.ToString());
            Debug.WriteLine(_bar.Foo());
        }
    }
}

At the end we need to update the DependencyResolution/IoC.cs code to hook things up:

using StructureMap;
using MyModel;
using MyComponent;
using Quartz;
using Quartz.Impl;

namespace QuartzNetMvc {
    public static class IoC {
        public static IContainer Initialize() {
            ObjectFactory.Initialize(x =>
                        {
                            x.Scan(scan =>
                                    {
                                        scan.TheCallingAssembly();
                                        scan.WithDefaultConventions();
                                    });

                            x.For<IBar>().Use<HelloWorldBar>();
                            x.Scan(s =>
                            {
                                s.TheCallingAssembly();
                                s.WithDefaultConventions();
                                s.AddAllTypesOf<IJob>().NameBy(c => c.Name);
                            });

                            x.SelectConstructor<StdSchedulerFactory>(() => new StdSchedulerFactory());
                            x.For<ISchedulerFactory>().Use<StdSchedulerFactory>();
                            x.For<IScheduler>().Use(() => ObjectFactory.GetInstance<ISchedulerFactory>().GetScheduler());
                        });
            return ObjectFactory.Container;
        }
    }
}

Let’s try to run the web app.
We will realize that HelloJob is actually never triggered. That’s because the JobFactory Quartz.NET by default expects parameterless constructor and we have dependency injection with the constructor overload.

So to complete the solution we need to do two more things, to create our DI JobFactory implementation and also tell Quartz.NET to use it.

Let’s create StructureMapJobFactory first which have to implement IJobFactory interface

using System;
using Quartz;
using Quartz.Spi;
using StructureMap;

namespace QuartzNetMvc.Jobs
{
    public class StructureMapJobFactory : IJobFactory
    {
        public IJob NewJob(TriggerFiredBundle bundle)
        {
            try
            {
                return (IJob)ObjectFactory.GetInstance(bundle.JobDetail.JobType);
            }
            catch (Exception e)
            {
                var se = new SchedulerException("Problem instantiating class", e);
                throw se;
            }
        }

    }
}

The last thing to do is to create quartz.config file and add this line:

quartz.scheduler.jobFactory.type = QuartzNetMvc.Job.StructureMapJobFactory, QuartzNetMvc

Now, if we run the code we will see that our HelloJob has been triggered and that HelloWorldBar has been injected properly.

1 Comment »

  1. Very nice!! Helped me a lot. Thank you for share it!

    Comment by João Carlos — February 17, 2014 @ 11:54 pm | Reply


RSS feed for comments on this post. TrackBack URI

Leave a comment

Create a free website or blog at WordPress.com.