Skip to main content

Job storage in Quartz using Files, A FileJobStore Class

Quartz supports mainly two types of Job Storage for Scheduler information.
• Memory (non persistent) storage


The memory job storage facility for Quartz is provided by a class called org.quartz.simpl.RAMJobStore, The RAMJobStore is the default, i.e unless you change the configuration, and this is the JobStore that will be used for any Quartz application. Using this JobStore has some advantage
1. Easy to configure, because already configured by Scheduler as a default
2. It’s fast - a plain old simple memory access
But, as a computer memory is volatile, when your Quartz application is stopped, it releases the memory back to the operating system. Of course, along with everything else stored in that released memory is the scheduling information.


• Persistent storage


Second is using database for Job storage which implements JobStoreSupport abstract class
Quartz offers two different types of concrete persistent JobStores, each one designed for a specific database environment and configuration:
1. org.quartz.impl.jdbcjobstore.JobStoreTX - Persistent Storage in a Stand-Alone Environment
2. org.quartz.impl.jdbcjobstore.JobStoreCMT - Persistent Storage in an Application Container
(For more information on this two concrete classes see, Quartz Docs)


This storage classes implements the JobStore interface.

Now to implement the FileJobStore for which saves our jobs in file by using serialization, we need to implement the JobStore interface

Implementing the JobStore Interface


The JobStore interface has 40 methods that must be implemented by any JobStore implementation, including user defined methods. How you implement those methods depends entirely on the type of JobStore that you are building. That doesn't mean that your JobStore will have only 40 methods; this is just the minimum that the interface requires. These 40 methods represent the public contract between a JobStore and the Scheduler.
Let's consider a method,
public void schedulerStarted() throws SchedulerException ;
The Scheduler calls the JobStore's schedulerStarted() method to inform the JobStore that the Scheduler has been started. If you look at the implementation in RAMJobStore, you can see that nothing is done inside this method for this implementation:



public void schedulerStarted() throws SchedulerException {
// nothing to do
}

The org.quartz.spi.JobStore interface has too many methods to list here, but the API for the JobStore interface can be generalized into the following categories:


• Job-related API
• Trigger-related API
• Calendar-related API
• Scheduler-related API


Quartz users almost never access or see concrete classes that implement the JobStore interface; they are used internally by the Quartz Scheduler to retrieve job and trigger information during runtime.
Now to implement FileJobStore, there are some important to method to override, eg

Store job

/**
Store the Job
*/
public void storeJob(SchedulingContext ctxt, JobDetail newJob,
boolean replaceExisting) throws ObjectAlreadyExistsException
{
// Here comes some other logic to store various parameters of Job
jobDetailMap.put(newJob.getName(), newJob);

}


/**
Called by the QuartzScheduler to inform the JobStore that it should free up all of it's resources because the scheduler is shutting down.
*/
public void shutdown()
{

log.info("SYSTEM IS SHUTTING DOWN .. SERILAZING THE JOBS ..");
// A temporary JobDetail object,
JobDetail jobDetailTemp = null;
try
{
// create the job.txt file to searilaze Jobs
objOutStream = new ObjectOutputStream(new FileOutputStream("job.txt", false));

// fetch each Job from joDetailMap
Iterator<Map.Entry<String, JobDetail>> it = jobDetailMap.entrySet().iterator();
// this list is serilized
ArrayList<JobDetail> jobDetailList = new ArrayList<JobDetail>();
while(it.hasNext())
{
jobDetailTemp = it.next().getValue();
// add Jobs to list
jobDetailList.add(jobDetailTemp);
}

// write to file
objOutStream.writeObject(jobDetailList);
objOutStream.flush();
objOutStream.close();
} catch (FileNotFoundException fnfex)
{
log.error("Problem in reading job file, job.txt; Exception " + fnfex.getMessage());
} catch (IOException ioex)
{
log.error("Problem in output stream; Exception :" + ioex.getMessage());
}
}

You can implement your own method for Job storage or enhance this code; I’m giving the source file of my implementation.
Download: FileJobStore.java
I know this implementation need some enhancements, as I’m not Java Guru, your comments are welcomed.
Updates: Removed a bug, new revision 1.2 of FileJobStore.java uploaded !!

Comments

Anonymous said…
Can you paste a link that works to your source code please?
techmythoughts said…
@Anonymous - Sorry buddy, I lost that file somewhere...
Anonymous said…
Hey mate,

Any chance you can find the source code? I'm doing something similar to what you describe- would love to compare. Thanks!
techmythoughts said…
The file is lost, but the implementation shouldn't be difficult. If you read post, you will know which methods are need to implement.

Popular posts from this blog

Installing i3lock-color on Ubuntu

i3lock is fancy lock screen for Linux. There is i3lock dep available on Ubuntu but its not what I was looking for; I was more interested in i3lock-color . Lets see how we can install the same on ubuntu. PS: I'm using Ubuntu 16.04 Get source code for i3lock-color $ git clone https://github.com/PandorasFox/i3lock-color.git  $ cd i3lock-color Install required packages to build i3lock  $ apt install libev-dev $ apt install libxcb-composite0 libxcb-composite0-dev libxcb-xinerama0 libxcb-randr0  $ apt install libxcb-xinerama0-dev  $ apt install libxcb-xkb-dev  $ apt install libxcb-image0-dev  $ apt install libxcb-util-dev $ apt install libxkbcommon-x11-dev $ apt install libjpeg-turbo8-dev  $ apt install libpam0g-dev Build  $ autoreconf -i && ./configure && make Execute $ ./lock.sh Assign Shortcut In order to assign shortcut, install compizconfig $ sudo apt-get install compizconfig-settings-manager co...

GlassFish V3 admin console taking too much time to load.

If you have installed Glassfish V3 and trying to load admin console, but after signing in, is it taking too much time to get to the main page ? Do you have server.log entry like this: admin console: initSessionAttributes() Cannot refresh Catalog : Connection timed out then its time to tweak some files. Here its how: 1. Update the %GLASSFISH_HOME/glassfish/domains/domain1/domain.xml -Dcom.sun.enterprise.tools.admingui.NO_NETWORK=true This will block up the News item, the registration item, etc 2. Remove update tool jar (Backup and remove this JAR) %GLASSFISH_HOME/glassfish/modules/console-updatecenter-plugin.jar Delete this dir: %GLASSFISH_HOME/glassfish/domains/domain1/osgi-cache %GLASSFISH_HOME/glassfish/domains/domain1/generated Now start the server (bin/asadmin start-domain) and you will see the admin console won't be hang up and take you directly to main page.

INTO OUTFILE query, How to modify & output null values ?

I tried one query (originally asked at JR) on MySQL which export the table data into a file, with a comma delimited field. The query is straight forward and replace the null column value by "\N" character, but when I want to replace that "\N" value by some other character like "0" or simple empty field like " ", its gets little tricky. Here is the base query SELECT Id, name, age FROM student INTO OUTFILE 'c:/result.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; And it outputs like, 1, "sagar", 23 2, "anant", 24 Now suppose some 'name' fields are null, then it outputs like 1, "sagar", 23 2, \N, 24 Now to obtain my desired results, which replace this null (\N) values by empty string like, "", I tried out two solutions --1. Using CASE statement SELECT Id, CASE WHEN name IS NULL THEN '' ELSE name END AS NewName, age FROM s...