Quartz 1.8.x to Quartz 2.1 Migration Guide

If you find errors, or encounter difficulties that you wish had been covered by this document, please help the
entire community by notifying the Quartz team of the needed improvements by posting a message in the forums.

This document outlines how to migrate an application using Quartz Scheduler 1.8.x to version 2.0 - it does not
document every change or new feature in version 2.0. For information related to what has changed with Quartz 2.0
please refer to the What's New In Quartz Scheduler 2.0 document, or refer to the
2.0 change list in
the project's Jira issue tracker.

Depending upon the particular Quartz features made use of by your existing Quartz 1.x application, there are
various migration issues that you may or may not need address. Hence, this document attempts to organize the migration
instructions by major feature sets / configuration types.

Making Changes Required For All Quartz Setups

The Quartz Scheduler API was significantly overhauled with the 2.0 release. Effort was made to balance making real
improvements with the desire to have minimal effort to migrate existing applications to usage of version 2.0. Not every
change is explicitly covered below - but those that aren't should be very easy to figure out on your own using your
IDE's code-completion offerings, or a quick look at the 2.0 JavaDoc.

Quartz Configuration (properties files)

This is the really easy part: No changes are required, existing properties files should work just fine.

Scheduler API

As you proceed toward making your code build again, remember to refer to JavaDoc for full reference of the API.

Typed Collections

API methods that return (or take as parameters) arrays now return (or take) typed collections. For example, rather
than getJobGroupNames(): String[] we now have getJobGroupNames(): List<String>. After updating your
project code's dependency to be upon the Quartz 2.0 library, the compiler will find and indicate errors at all of your
usages of arrays rather than Lists, Sets, etc. Many applications will have very few occurrences to fix, while others
with have many dozens - depending upon the nature of the application and its usages of the Quartz API.

Example old code:

String[] triggerGroups = sched.getTriggerGroupNames();

New code:

List<String> triggerGroups = sched.getTriggerGroupNames();

Job and Trigger Identification (Keys)

Jobs and Triggers are now identified by keys, JobKey and TriggerKey respectively. Keys are composed
of two String properties: name and group. As such, methods that once took name and group as two parameters,
now take a key as a single parameter. Your IDE's compiler will identify all occurrences that need to be fixed. Note
that JobKey and TriggerKey have static methods on them for easily creating keys, consider using static imports to make
your code cleaner (to avoid code that looks like this: new TriggerKey("name", "group")). In some cases the new
usage of keys will make your code a tiny bit longer, but in other cases it greatly simplifies things (e.g. passing/receiving
one argument rather than two). Also note that group does not need to be specified (just leave the parameter off) when
creating a key if you are not making usage of groups.

Constructing Jobs and Triggers (the new, preferred way - see next section for easier migration)

A new builder-based API provides a Domain Specific Language (DSL) for constructing job and trigger definitions.
Usage of static imports makes your code nice and clean when using the new DSL. Aside from being a less cumbersome API,
the new builders have provided a means for removing/hiding many methods that were once on various classes (such as
Trigger) that were not meant to be called by the client code.

Please take note of related new classes (that you should use static imports from): TriggerBuilder, JobBuilder,
SimpleScheduleBuilder, CronScheduleBuilder, CalendarIntervalSchedulerBuilder, DateBuilder.

Constructing Jobs and Triggers (the easy but not recommended way - see above for preferred)

If you want to get going quicker, without re-writing code to use the new builder/DSL API, you can make some quick
changes to existing code to make the compiler happy. Trigger and JobDetail are now interfaces, but implementations
still exists that you can "sneakily" reference. Note that this is only recommended as a temporary way to get your
code working quickly, and you should plan on eventually converting your code to use the new API.

Rather than importing and using org.quartz.SimpleTrigger, org.quartz.CronTrigger, and
org.quartz.JobDetail change your code to import and use org.quartz.impl.triggers.SimpleTriggerImpl,
org.quartz.impl.triggers.CronTriggerImpl, and org.quartz.impl.JobDetailImpl. (A similar name
substitution pattern can be used for other concrete trigger types).

Changes Relating To Trigger Comparison

Trigger's compareTo() method now correctly relates to its equals() method, in that it compares the trigger's key,
rather than next fire time. A new Comparator that sorts triggers according to fire time, priority and key was added as
Trigger.TriggerTimeComparator.

This will not affect most Quartz 1.x users, but may, if your own code attempts to sort triggers by placing them
in a sortable collection (e.g. TreeSet), or uses Collections.sort(..) with them. Please be aware of the change,
and make appropriate adjustment to your code as needed.

Significant changes were made to the way listeners are registered with the scheduler. There is no longer a
distinction between "global" and "non-global" listeners. Jobs and Triggers are no longer configured with a list of
names of non-global listeners that should be notified of events related to them. Instead all listeners are registered
with one or more Matcher rules that select which jobs/triggers the listener will be notified of events for.

Additionally, all methods related to the management of listeners were removed from the Scheduler interface and were
placed on a new ListenerManager interface.

Most Quartz-using applications do not make use of listeners, but if yours does, you'll have some work to do to make
the compiler happy.

See the new org.quartz.impl.matchers package for the complete set of available Matcher implementations.

Changes Related To TriggerUtils

Methods on TriggerUtils related to construction of Date instances have been moved to DateBuilder
and can be made easy use of via static imports. Dates can then easily and cleanly be constructed and used in-line with
the new trigger builder DSL.

Methods on TriggerUtils related to construction of Trigger instances have been moved to
SimpleScheduleBuilder and CronScheduleBuilder (and other ScheduleBuilder implementations) and can be
made easy use of via static imports.

Changes Related To DateIntervalTrigger

DateIntervalTrigger, which was introduced late in the 1.x code line was renamed to
CalendarIntervalTrigger. This change is rather significant for those who were using DateIntervalTrigger
with JDBC-JobStore, as a class of that name no longer exists, yet the database will contain serialized instances of
it!

To help with this problem a "backward compatibility" JAR (quartz-backward-compat-2.0.0.jar) is shipped with
Quartz 2.0, which contains a new version of the missing class that has been updated to be compatible with Quartz 2.0,
yet has the same name and serialVersionUID as the old class. Make sure to put this JAR in your classpath if you have
stored instances of DateIntervalTrigger!

It is recommended that you change all code that references/uses DateIntervalTrigger to use the new
CalendarIntervalTrigger, which will not store to the database in BLOB (serialized) form.

Changes Related To NthIncludedDayTrigger

NthIncludedDayTrigger (a rarely used and issue-fraught Trigger implementation) was removed from Quartz 2.0
code base. This change is rather significant for those who were using NthIncludedDayTrigger
with JDBC-JobStore, as a class of that name no longer exists, yet the database will contain serialized instances of
it!

To help with this problem a "backward compatibility" JAR (quartz-backward-compat-2.0.0.jar) is shipped with
Quartz 2.0, which contains a new version of the missing class that has been updated to be compatible with Quartz 2.0,
yet has the same name and serialVersionUID as the old class. Make sure to put this JAR in your classpath if you have
stored instances of NthIncludedDayTrigger!

If you were using NthIncludedDayTrigger, it is recommended that you find alternative ways to schedule your jobs
(using other Triggers).

Making Changes For Setups Using JDBCJobStore

Database Schema Changes

If you use JDBCJobStore, you will need to make several changes to the database to transform it to the new expected schema.

Exact syntax will vary between databases, but most should work with the following commands or small variations (the
table creation script for each database (found in the Quartz distribution's "docs/dbTables" directory) can also serve
as reference.