Introduction
Quartz.Net allows you to schedule jobs to run. These jobs are often configured with variables from a JobDataMap
object. I wanted a simple and effective class that will allow me to use .NET properties instead of relying on configuring and setting up a JobDataMap
when I needed to schedule a job.
Background
An important aspect that I wanted to address was that although the Quartz.Net JobDataMap
class will allow you to store objects, I only wanted to store string values. The problem is that if you store .net objects in the JobDataMap
, you will also run the risk of running into type or versioning issues.
Taking advantage of the Json.NET framework, I built a simple QuartzJobBase
class that allowed me to only store string values but also allow me to store more complex objects in the JobDataMap
.
Using the code
Before you start, make sure you are referencing the Json.NET assembly.
The QuartzJobBase class is an abstract implementation of a Quartz.Net job. It is in charge of 3 important aspects.
- Serializing current property values into a JobDataMap
- Deserializing property values from a JobDataMap
- Wrapping exceptions thrown by implementations with a
JobExecutionException
.
To seralize proeprty values in a JobDataMap, you can simple call BuildJobDataMap()
on your object to build a JobDataMap
instance with your current property values.
Deserializing the object is being handled automatically by the class because it is executed when the job is executed by the Quartz scheduler.
using System;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
namespace Quartz.Custom
{
public abstract class QuartzJobBase : IJob
{
private static readonly Newtonsoft.Json.JsonSerializerSettings JsonSettings;
static QuartzJobBase()
{
JsonSettings = new JsonSerializerSettings();
JsonSettings.TypeNameHandling = TypeNameHandling.Auto;
JsonSettings.TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
}
public void Execute(IJobExecutionContext context)
{
try
{
ReadFromJobDataMap(context.MergedJobDataMap);
InternalExecute(context);
}
catch (Exception ex)
{
JobExecutionException jex = new JobExecutionException(ex);
throw jex;
}
}
protected abstract void InternalExecute(IJobExecutionContext context);
#region JobDataMap & Serialization
public JobDataMap BuildJobDataMap()
{
JobDataMap data = new JobDataMap();
foreach (var prop in GetType().GetProperties())
{
object value = prop.GetValue(this, null);
string s = GetPropertyValue(prop);
data.Add(prop.Name, s);
}
return data;
}
private void ReadFromJobDataMap(JobDataMap data)
{
PropertyInfo[] properties = GetType().GetProperties();
foreach (var key in data.Keys)
{
var p = properties.Where(x => x.Name == key).SingleOrDefault();
if (p != null)
{
SetPropertyValue(p, data.GetString(key));
}
}
}
private string GetPropertyValue(PropertyInfo property)
{
object value = property.GetValue(this, null);
return JsonConvert.SerializeObject(value, Formatting.None, JsonSettings);
}
private void SetPropertyValue(PropertyInfo property, string value)
{
object obj = JsonConvert.DeserializeObject(value, property.PropertyType, JsonSettings);
property.SetValue(this, obj, null);
}
#endregion
}
}
A sample job implementation would look like this.
public class HelloWorldJob : QuartzJobBase
{
public string Name { get; set; }
public int FavoriteNumber { get; set; }
public List<string> CustomList { get; private set; }
public HelloWorldJob()
{
CustomList = new List<string>();
}
protected override void InternalExecute(Quartz.IJobExecutionContext context)
{
Console.WriteLine("Hello World from {0} ({1})", Name, FavoriteNumber);
foreach (var item in CustomList)
{
Console.WriteLine("{0} CUSTOM LIST: {1}", Name, item);
}
}
}
To schedule a job by providing a JobDataMap
HelloWorldJob j = new HelloWorldJob();
j.Name = "My Name";
j.FavoriteNumber = r.Next(100);
for (int x = 0; x < 10; x++)
{
j.CustomList.Add(r.Next().ToString());
}
sched.ScheduleJob(
JobBuilder.Create(typeof.HellowWorldJob)
.UsingJobData(j.BuildJobDataMap())
.Build(),
TriggerBuilder.Create()
.StartNow()
.Build());
Enjoy!