Click here to Skip to main content
Click here to Skip to main content
Go to top

Quartz.Net - Custom Base Job

, 7 Jun 2012
Rate this:
Please Sign up or sign in to vote.
Creating a custom base job class for quartz scheduler development

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.

  1. Serializing current property values into a JobDataMap
  2. Deserializing property values from a JobDataMap
  3. 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)
            {
                // Jobs should throw JobExecutionException if error occurred.
                // Wrap internal exceptions with JobExecutionException.
                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!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

AndrewSmith
Software Developer
United States United States
I'm a proud father and a software developer. I'm fascinated by a few particular .Net projects such as Lucene.Net, NHibernate, Quartz.Net, and others. I love learning and studying code to learn how other people solve software problems.

Comments and Discussions

 
QuestionAbout Quartz.net 2.0 trigger stop problem Pinmemberjiangmm28-Aug-12 22:28 
AnswerRe: About Quartz.net 2.0 trigger stop problem Pinmemberhahaclj28-Aug-12 23:01 
GeneralRe: About Quartz.net 2.0 trigger stop problem Pinmemberjiangmm29-Aug-12 0:49 
QuestionMy vote of 5 Pinmemberbobfox10-Jun-12 12:06 
AnswerRe: My vote of 5 PinmemberAndrewSmith11-Jun-12 17:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140916.1 | Last Updated 7 Jun 2012
Article Copyright 2012 by AndrewSmith
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid