Creating A Quartz.Net Plug-in

In this post I’ll walk you through creating and configuring a Quartz.Net plug-in. It’s not very complicated, but this will depend on what you are trying to do with your plug-in. For the example we will create a plug-in that attaches a global job listener to the quartz scheduler. This will come in handy later on, since I will be posting another article describing how to create a job listener for Quartz.Net. The Quartz.net source code also includes an example of how to do this in the LoggingJobHistoryPlugin.
Why do we need to create a plug-in to register a global job listener? Global job listeners are not stored in the job store, so they need to be added to the scheduler every time it starts. That’s why we’re going with the global job listener / plug-in combo.

The Plug-in Interface

To create the plug-in we need to implement the ISchedulerPlugin interface. Here is the ISchedulerPlugin interface:
public interface ISchedulerPlugin
{
    void Initialize(string pluginName, IScheduler sched);
    void Start();
    void Shutdown();
}


This interface has 3 methods that we could implement. Let’s look at these methods in a little more detail.


The Initialize method



The comments in the code say that this method is “Called during creation of the IScheduler in order to give the ISchedulerPlugin a chance to initialize. At this point, the Scheduler's IJobStore is not yet (ready?). If you need direct access (to) your plug-in, you can have it explicitly put a reference to itself in the IScheduler's SchedulerContext Initialize(string, IScheduler) method”. We’re just adding a global listener to the scheduler, so we’ll include the code to do this in the Initialize method. Alternatively, we could move this code to the Start method and the result would be the same.


The Start Method



The comments in the code say that this method is called when the associated IScheduler is started, in order to let the plug-in know it can now make calls into the scheduler if it needs to. We’re not going to be making any calls into the scheduler, so there is no need to implement this method.


The Shutdown Method



For this method the code comments say that it is called in order to inform the ISchedulerPlugin that it should free up all of it's resources because the scheduler is shutting down. We don’t have any resources to free up, so we aren’t going to implement this method either.


Creating the Plug-In



Now, let’s take a look at the code for the plug-in. We’re doing something pretty simple here, so the implementation is very short.


public void Initialize(string pluginName, IScheduler sched)
{
    sched.AddGlobalJobListener(new JobListener());
}


Yes, that’s all there is to creating a very simple plug-in. We’re not entirely done though, since now we need to tell the scheduler to load the load the plug-in upon startup.


Configuring the Scheduler to Load the Plug-In



The last step is to let the scheduler know that it needs to load your plug-in upon start. This is done via the configuration file, by setting a property as follows:



quartz.plugin.{name}.type = {type name}, {assembly name}



Let’s look at all the components of this property in detail. First there is quartz.plugin, which tells the scheduler that this is a plug-in that needs to be loaded. The {name} portion is the name that you want to give to your plug-in, and is the name that is passed in to the Initialize method above. The value of the property indicates the Type of the plug-in, so that the scheduler can load it into memory. {type name} is the full name of your plug-in, which in our case would be something.something.JobListener. {assembly name} is the name of your assembly file, minus the .dll extension.


Once you add your configuration information, you are done. Make sure that your dll is in the same folder as the Quartz.Net binaries and that should be all you need to do.


In my next post we’ll tackle the implementation of the JobListener that we used as an example in this post.

Continue Reading

Running Quartz.Net 1.0.2 on .Net 4.0

We recently upgraded one of our application to .Net 4.0. As part of this upgrade, we also upgraded out Quartz.net jobs to run on the 4.0 version of the .Net framework. The process was fairly straightforward, but not without surprises, so I figured I would post it here in case it’s useful. I hope that there will be an official 4.0 release made soon, so I have only included the steps of the process I followed in this post. If there’s enough interest I can upload the updates solution file. If you want to try it out for yourself, I’ve broken the process down into simple steps. Feel free to skip over the steps that are familiar to you.

Step 1 – Downloading the Source Code

First, I downloaded the source code from sourceforge using subversion. The subversion url for the project is: https://quartznet.svn.sourceforge.net/svnroot/quartznet. If you’re using TortoiseSVN, then you just have to right click on the folder you want to download the source to, and then select SVN Checkout. Paste the URL above into the box and select OK. Here’s a screenshot of what I’m talking about:
image

Step 2 – Convert the Solution File

Next locate the main solution file for the maintenance release (this is the branch I used, since it corresponds to the latest released version). The file is called Quartz.2008.sln and is located under branches –> Quartz-1.0-Maintenance. Open this file in VS2010 (right click, select open with… VS2010) and run through the upgrade wizard. Once that’s done, there are some small changes to be made.

Step 3. – Target .Net 4.0

This is the tedious part… you’ll have to right click on each project, select properties and then under the Applications tab, select the new target framework:
image

Step 4 – Fix the Build

If you build the solution now, you’ll get some warnings are errors. You have 2 options:
1. Fix the errors, which are basically documentation errors. You’ll have to look at each of the individual errors to fix them, so I won’t describe the process in detail. Just keep pressing F8 until you’ve fixed them all.
2. Turn off warnings as errors. This is the path of least resistance.
At this point, whether you selected option 1 or 2, you should have a working build. By default, the results of the build are put under the build\2.0 folder:
image

Step 5 – Fix the Version Number and Service Name

Note: this part is optional…
Since I already have a working scheduler and didn’t want to risk screwing it up, I changed the name of the scheduler in the installer file so that I could install it side by side with my existing scheduler to be able to test it. I also changed the version numbers in case for some reason the dlls got mixed up. To change the service name, open Configuration.cs file. It’s under the Quartz.Server.Core project. Change these lines as follows (or use your imagination):
private const string DefaultServiceName = "QuartzServerForNet4";
private const string DefaultServiceDisplayName = "Quartz Server For Net4";
private const string DefaultServiceDescription = "Quartz Job Scheduling Server For Net4";


This will let you install the updated scheduler side by side with the old scheduler.


To update the version number you will have to right click on each project, select properties and then under the application tab, click on the Assembly Information button to update it:


image


Then just, update it to the version number of your preference. Something like this:


image


Step 6 – Final Steps



You should be ready to use Quartz.Net with the 4.0 framework now. If you’re going to install Quartz.net as a service, then take a look at this post. The steps you need to follow will be identical, just remember to use the new files you just built. If you are running Quartz.net embedded in your application, then update your references so they point to the new dlls.

Continue Reading

Configuring Quartz.Net with an ADO.Net Job Store (AdoJobStore) – Part 2

In Part 1 we set up our database so that we could use it as a job store for Quartz.Net. Now, we need to set up our scheduler job store properties to use said database. Here are the most common properties and values that need to be set in order to get the scheduler to use the database as its job store:

Property Value
quartz.jobStore.type Quartz.Impl.AdoJobStore.JobStoreTX, Quartz
quartz.jobStore.dataSource default
quartz.jobStore.tablePrefix QRTZ_
quartz.jobStore.clustered true
quartz.jobStore.lockHandler.type Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz
quartz.jobStore.driverDelegateType Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz
quartz.dataSource.default.connectionString Server=localhost;Database=youeverseethefly;Uid=brundle;Pwd=fly;
quartz.dataSource.default.provider SqlServer-20
quartz.jobStore.useProperties true
You can set these properties in your config file, but the specific file will depend on whether you are using the default configuration file or something else. If you are using the default (distribution) settings, these properties will go in your quartz.config file.
That’s all there is to setting up an AdoJobStore. Start up your service and take a look at the event log to see if the scheduler started up correctly.

Continue Reading

Configuring Quartz.Net with an ADO.Net Job Store (AdoJobStore) – Part 1

Quartz.Net stores all of its job related configuration in an aptly named JobStore. There are two different kinds of job stores available out of the box: RAMJobStore and AdoJobStore. By default, Quartz.Net uses a RAMJobstore. The RAMJobStore is extremely simple to configure, but it is a volatile store, so all job configuration is lost whenever the scheduler is restarted.
If you need your job configuration to be persisted between scheduler restarts and/or you are going to be running more than one instance of the scheduler in a cluster, you will need to use the AdoJobStore. This job store uses ADO.Net to persist all the job configuration information in a database. The following table shows the most common database providers that are supported, as well the name of the Quartz.Net database provider to use. The full list of providers can be found in lesson 9 of the Quartz.Net tutorial.

Database Provider Quartz.Net Provider Name
SQL Server driver for .NET Framework 2.0 SqlServer-20
Oracle Driver (by Microsoft) OracleClient-20
MySQL Connector/:NET v. 5.1 (.NET 2.0) MySql-51
SQLite ADO.NET 2.0 Provider v. 1.0.56 (.NET 2.0) SQLite-10
This post will focus on configuring the job store for SQL Server. If you’d like to see similar posts for the other databases, please let me know in the comments.
First, let’s take a look at the steps you will need to follow to start using an ADO.Net job store:
  1. Set up the database by creating the tables that Quartz.Net will use.
  2. Configure the scheduler to use the database server that you just set up.
It’s not that complicated, is it?

Step 1: Setting up the database

First, you will need to locate the setup script for your database server. In our case, we will use the SQL Server setup script. All setup scripts are located under the database/tables folder of the Quartz.Net distribution. The script we are looking for is called tables_sqlServer.sql. Open the script in a text editor and update the USE [enter_db_name_here] statement to point to whatever database you want to use. Once you’ve changed the database name in the script, you can go ahead and execute it. This script will create several tables in the database you set in the script. All of the Quartz.Net tables will be prefixed by QRTZ_ . Once you’ve successfully created all the tables, it’s time to configure the scheduler.
In Part 2 we will cover configuration of the scheduler.

Continue Reading

Creating a Custom Job in Quartz.Net

If you use Quartz.Net and you want to do anything other than run  a batch file, then chances are you’ll want to create a custom job. Fortunately, creating it is not hard at all. Let’s get started.
Here’s a quick rundown of what you need to do. First, you’ll need to add a reference to Quartz.dll in your project, Second, create a class that implements IJob. Third, put the code you want to run inside the Execute method. That’s it! That’s all you really need to create a custom job.
However, in order to get this job to execute, there are a couple more steps to follow and a few more things to be aware of, including some not-so-evident gotchas.
I’m going to assume that at this point, you have created your MyJob class and that it implements the IJob interface. Let’s talk  about what you need to do in addition to implementing the logic that you want your job to execute.

Handle Exceptions
You should wrap the code in the Execute method and handle any exceptions that you can. For exceptions that you cannot handle but that can be solved by running the job again, you should wrap your exception inside a JobExecutionException.
If you want the scheduler to try running the job again, then set the RefireImmediately property to true. Otherwise, set it to false. You also have other options, such as un-scheduling triggers, so take a look at the documentation for JobExecutionException.
If your job doesn’t know how to handle the exception that was thrown, then don’t catch it and let the scheduler handle it.
Deploy Your Custom Job
Deploying the custom job is as simple as copying the dll to the same folder where the Quartz.dll is. You can also deploy your dll in any manner that allows the runtime to locate the dll per the normal rules for dll resolution.
Beware of ConfigurationManager
Finally, I’d like to give you a heads up about using the ConfigurationManager to provide your job with configuration information. Don’t do it! It is best to include all the information that your job needs to execute in the job’s JobDataMap. The reason for this is simple. If you use ConfigurationManager and you are running Quartz.Net as a windows service, then the ConfigurationManager will try to look for configuration information in the Quartz.Net config file. If you are running Quartz.Net embedded inside your application, then this might not be an issue for you, but then again… it might.
Let’s wrap up this post by summarizing the steps needed to create a custom Quartz.Net job.
  1. Add a reference to Quartz.dll in your project.
  2. Create a class that implements IJob
  3. Implement the Execute method of the IJob interface.
  4. Catch exceptions and throw a JobExecutionException as needed.
  5. Copy the CustomJob dll to the same folder as Quartz.dll or somewhere that the runtime can locate it.
If you need more information, please let me know in the comments or read over documentation for IJob and for JobExcecutionException.

Continue Reading