Quartz.Net Job Factories

In my previous post we talked about the IJobFactory interface in detail. Today we will look at the 2 job factories that are included in the Quartz.Net distribution.

SimpleJobFactory

We will look at the SimpleJobFacotry first, since it is the base class used by the other job factory. This is a pretty simple implementation, so let’s look at the source code and talk about it in detail. Here is the source code for the NewJob method:

public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
	IJobDetail jobDetail = bundle.JobDetail;
	Type jobType = jobDetail.JobType;
	try
	{
		if (Log.IsDebugEnabled)
		{
			Log.Debug(string.Format(CultureInfo.InvariantCulture, "Producing instance of Job '{0}', class={1}", jobDetail.Key, jobType.FullName));
		}
    return ObjectUtils.InstantiateType(jobType);
}
catch (Exception e)
{
    SchedulerException se = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Problem instantiating class '{0}'", jobDetail.JobType.FullName), e);
    throw se;
}

}

Take a look at lines 3 and 4. Here we get the job detail and the job type so that we can create a new job of the given type. The job is instantiated in line 12 using a Quartz.Net utility class that essentially calls the type’s default constructor. Lines 16 and 17 handle any exceptions that happen during the object creation and throw a SchedulerException if any exception gets thrown.

As you can see, the class’ name is pretty accurate. This is a simple job factory. Now, let’s take a look at the other job factory that is included in Quartz.Net.

PropertySettingJobFactory

As its name indicates, the PropertySettingJobFactory creates a new job instance and then tries to set the properties on the job. This job factory inherits from SimpleJobFactory and reuses the mechanism to create the job (calling the default constructor). Once the new job is instantiated, this factory will pull all of the data from the JobDataMap and from the scheduler’s Context, merging them into one big data map.

Here is the code that we were just describing, inside the NewJob method of PropertySettingJobFactory:

public override IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
	IJob job = base.NewJob(bundle, scheduler);
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.PutAll(scheduler.Context);
jobDataMap.PutAll(bundle.JobDetail.JobDataMap);
jobDataMap.PutAll(bundle.Trigger.JobDataMap);

SetObjectProperties(job, jobDataMap);

return job;

}

The SetObjectProperties method that is called in line 10 does the actual setting of properties on the job that is passed in. This method is pretty long because of extensive checks and error handling, but the crux of what it does is loop through all of the keys in the data map and try to find a property with the same name as the key. If a match is found and the property is compatible with the value associated to the key, then the property is set.

The PropertySettingJobFactory includes two properties that you can set to change what happens when a key is present in the job map but an equivalent property is not found. These two properties are here:

public virtual bool ThrowIfPropertyNotFound { get; set; }

public virtual bool WarnIfPropertyNotFound { get; set; }

Their names are pretty descriptive so I will just point out that you would set ThrowIfPropertyNotFound to true if you want an exception to be thrown if an equivalent property is not found. On the other hand, if you just want a warning message to be logged instead of throwing an exception, you would set WarnIfPropertyNotFound to true. Both properties default to false.

This concludes our tour of the built-in job types and interfaces for job creation in Quartz.Net. On my next post we will implement our own custom job factory,