What is Quartz Scheduler

advertisement
What is Quartz Scheduler?
Quartz is a full-featured, open source job scheduling framework written entirely in Java. It can be
integrated with, or used along side virtually any J2EE or J2SE application - from the smallest
stand-alone application to the largest e-commerce system. Job scheduler is a system that is
responsible for executing other software components when a pre-determined (scheduled) time
arrives.
Quartz is quite flexible. It contains multiple usage paradigms that can be used separately or
together to achieve the desired behavior. And it enables you to write the code in the way that
seems most natural to your project.
Quartz is a fault-tolerant, and can persist your scheduled jobs between system shutdown and
restarts. Quartz is very useful for simply executing certain system process on given schedules.
What
is
Quartz
-
From
a
Software
Component
View?
Quartz contains all of the core Quartz functionality and it is distributed as a small java library (.jar
file). Scheduler interface is the main interface (API) to this functionality. It provides some simple
operations like scheduling jobs, un-scheduling jobs, starting/stopping/pausing the scheduler.
If you want to schedule you software components then it must implement the Job interface which
override the execute() method. If you want components have to notify when scheduled fire-time
arrives, then you should implements either the TriggerListener or JobListener interface.
Why Quartz Scheduler?
Quartz Scheduler can be integrated with, or used along side virtually any J2EE or J2SE
application - from the smallest stand-alone application to the largest e-commerce system. Quartz
scheduler is a fault-tolerant, and can persist you scheduled jobs between system shutdown and
restarts. It contains the all core Quartz functionality. Once you configure the Job class and set up
the schedule, Quartz will take care of the rest. When the Scheduler determines the notifying time
to your job, the Quartz framework will call the execute() method on your Job class. You don't
have to report anything back to the Scheduler. If you configure your Job to be called again at a
later time, the framework will take care of calling again at the right time.
In the next section you will learn how to download Quartz Job Scheduler and then configure the
development environment in eclipse.
In this section we will download Quartz Job Scheduler from its distribution web site and then
create development environment in the eclipse integrated development environment.
Downloading Quartz Job Scheduler
Quartz is an open source enterprise grade software for the development of Job Scheduling
application in java. Quartz Scheduler is from OpenSymphony which can be downloaded from
http://www.opensymphony.com/. At the time of writing this tutorial the latest version of Quartz
Scheduler is 1.6.0. You can download the latest version of software and then try. For this tutorial
we have downloaded quartz-1.6.0.zip.
After downloading the zip file extract it and you will find the following directory in the extracted
directory.
Here is the description of files and directories:
Files/Directory
Purpose
quartz-all-<ver>.jar
Quartz library includes the core Quartz components
and all optional packages. If you are using this library
then no other quartz-*.jars need to include.
quartz-<ver>.jar
quartz-jboss-<ver>.jar
quartz-oracle-<ver>.jar
quartz-weblogic-<ver>.jar
build.xml
docs
docs/wikidocs
docs/dbTables
src/java/org/quartz
src/java/org/quartz/core
src/java/org/quartz/simpl
core Quartz library.
optional JBoss specific Quartz extensions such as
the Quartz startup MBean, QuartzService.
optional Oracle specific Quartz extensions such as
the OracleDelegate
optional WebLogic specific Quartz extensions such
as the WebLogicDelegate
an "ANT" build file, for building Quartz.
root directory of all documentation
the main documentation for Quartz. Start with the
"index.html"
sql scripts for creating Quartz database tables in a
variety of different databases.
the main package of the Quartz project, containing the
'public' (client-side) API for the scheduler
a package containing the 'private' (server-side)
components of Quartz.
this package contains simple implementations of
Quartz support modules (JobStores, ThreadPools,
Loggers, etc.) that have no dependencies on external
(third-party) products.
src/java/org/quartz/impl
src/java/org/quartz/utils
src/examples/org/quartz
webapp
lib
this package contains implementations of Quartz
support modules (JobStores, ThreadPools, Loggers,
etc.) that may have dependencies on external (thirdparty) products - but may be more robust.
this package contains some utility/helper components
used through-out the main Quartz components.
this directory contains some examples usage of
Quartz.
this directory contains a simple web-app for managing
Quartz schedulers.
this directory contains all third-party libraries that are
needed to use all of the features of Quartz.
Setting Up Development project in Eclipse
Run the eclipse IDE and create new java project. From the file menu select --> New --> Project
New Project dialog box displayed as follows:
Select "Java Project" and click on the "Next >" button.
Enter "Quartz Project" in the Project Name text box and click on the "Finish" button to create the
project. A new project is created and following screen is displayed.
Adding required quartz libraries to the project
Copy the lib directory and all the jar files from the unzipped directory and then paste into the
eclipse project (Ctrl +C and Ctrl +V).
.
Open the project property and then add all the jar files into the build path as shown below.
and then click on the "OK" button.
Now your development environment is ready for the development. In the next section we will
develop a simple scheduler application that prints "Hello Quartz Scheduler" on the console at
particular time interval.
In this section we are going to develop a simple Quartz Scheduler application with the help of
Quartz framework. That will display "Hello World Quartz Scheduler :<date & time>" on the
console window after specified time schedule.
Before using Scheduler you have to instantiate it. For doing this some users may keep an
instance of a factory serialized in a JNDI store, and some other users may find it just to
instantiate and use a factory instance. Firstly create the instance of SchedulerFactory by getting
the reference of org.Quartz.impl.StdSchedulerFactory Class. Invoke the getScheduler()
method by this instance to instantiate the Scheduler.
Description of code:
execute(): Any software components you want to schedule then you must implement the Job
interface and override it execute() method.
JobExecutionContext: The JobExecutionContext object that is passed to execute() method
provides the job instance with information about its "run-time" environment - a handle to the
Scheduler that executed it, a handle to the Trigger that triggered the execution, the job's
JobDetail object, and a few other items.
SchedulerFactory: SchedulerFactory is a interface provides a mechanism for obtaining clientusable handles to Scheduler instances.
StdSchedulerFactory(): A Class StdSchedulerFactory is a class and it is implementation of
SchedulerFactory interface. Here it just using for create an instance of SchedulerFactory
instance.
Scheduler: Scheduler interface is the main interface (API) to this functionality. It provides some
simple operations like scheduling jobs, unscheduling jobs, starting/stopping/pausing the
scheduler.
getScheduler(): SchedulerFactoy interface having the getScheduler() method that returns an
instance of Scheduler.
start(): This method is used to starts the Scheduler's threads that fire Triggers. At the first time
when we create the Scheduler it is in "stand-by" mode, and will not fire triggers. The scheduler
can also be send back into stand-by mode by invoking the standby() method.
JobDetail(String name, String group, Class jobclass): The JobDetail object is created at the
time the Job is added to scheduler. It contains various property settings like job name, group
name and job class name. It can be used to store state information for a given instance of job
class.
SimpleTrigger(String name, String group, Date startTime, Date endTime, int repeatCount,
long repeatInterval): Trigger objects are used to firing the execution of jobs. When you want to
schedule the job, instantiate the trigger and set the properties to provide the scheduling.
DEFAULT_GROUP: It is a constant, specified that Job and Trigger instances are belongs to
which group..
REPEAT_INDEFINITELY: It is a constant used to indicate the 'repeat count' of the trigger is
indefinite.
scheduleJob(JobDetail jd, SimpleTrigger st): This method is used to add the JobDetail to the
Scheduler, and associate the Trigger with it.
Here is the code of Job Class:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
public class HelloJob implements Job {
public void execute(JobExecutionContext arg0) throws JobExecutionException{
System.out.println("Hello World Quartz Scheduler: " + new Date());
}
}
Download this code
Here is the code of Scheduler Class:
import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
public class HelloSchedule {
public HelloSchedule()throws Exception{
SchedulerFactory sf=new StdSchedulerFactory();
Scheduler sched=sf.getScheduler();
sched.start();
JobDetail jd=new JobDetail("myjob",sched.DEFAULT_GROUP,HelloJob.class);
SimpleTrigger st=new SimpleTrigger("mytrigger",sched.DEFAULT_GROUP,new Date(),
null,SimpleTrigger.REPEAT_INDEFINITELY,60L*1000L);
sched.scheduleJob(jd, st);
}
public static void main(String args[]){
try{
new HelloSchedule();
}catch(Exception e){}
}
}
Download this code
Output of the program :
log4j:WARN No appenders could be found for logger
(org.quartz.simpl.SimpleThreadPool).
log4j:WARN
properly.
Please
initialize
the
log4j
system
Hello World Quartz Scheduler: Fri Feb 16 16:15:10
GMT+05:30 2007
Hello World Quartz Scheduler: Fri Feb 16 16:16:10
GMT+05:30 2007
Hello World Quartz Scheduler: Fri Feb 16 16:17:10
GMT+05:30 2007
Hello World Quartz Scheduler: Fri Feb 16 16:18:10
GMT+05:30 2007
Hello World Quartz Scheduler: Fri Feb 16 16:19:10
GMT+05:30 2007
Hello World Quartz Scheduler: Fri Feb 16 16:20:10
GMT+05:30 2007
If you want to schedule you software components then it must implement the Job interface which
override the execute() method. Here is the interface:
package org.quartz;
public interface Job {
public void execute(JobExecutionContext context)
throws JobExecutionException;
}
The JobExecutionContext object which is passed to execute() method provides the job instance
with information about its "run-time" environment - a handle to the Scheduler that executed it, a
handle to the Trigger that triggered the execution, the job's JobDetail object, and a few other
items.
The JobDetail object is created at the time the Job is added to the scheduler. The JobDetail
object various property settings for the Job, as well as a JobDataMap, which can be used to
store state information for a given instance of your job class.
Trigger objects are used to start the execution of jobs. When you want to schedule a job, you
instantiate a trigger and set' its properties to provide the scheduling according to your need.
There are currently two types of triggers: SimpleTrigger and CronTrigger.
Generally, SimpleTrigger is used if you need just single execution of a job at a given moment in
time or if you need to start a job at a given time, and have it repeat N times, with a delay of T
between executions. CronTrigger is used when you want to triggering based on calendar-like
schedules - such as "every Saturday, at noon" or "at 12:35 on the 15th day of every month."
Why Job & Triggers
Many job schedulers do not have separate notions of jobs and triggers. Some job Schedulers
define a 'job' as simply an execution time with some small job identifier. And some others are
much like the combination of Quartz's job and trigger objects. While developing Quartz, we
decided that it made sense to create a separation between the schedule and the work to be
performed on that schedule.
Identifiers
Jobs and Triggers are predefined identifying names as they are registered with the Quartz
scheduler. You can placed jobs and triggers into 'groups' also, for organizing the jobs and triggers
into categories for later maintenance. The name of a job or trigger must be unique within its
group.
More about Job & JobDetail
In this section you will understand some more things about nature of jobs, about the execute()
method of the Job interface, and about the JobDetails. While a class implementing the job
interface that is the actual 'job', and you have to inform to Quartz about some attributes that you
may want job to have. That can be done by the JobDetail class.
The JobDetail instance refers to the job to be executed by just providing the job's class. When
scheduler executes the job, it creates the new instance of the job class before invoking the
execute() method. The jobs must have a no-argument constructor that is the ramification of this
behaviour. And it is not useful to define data members on the job class - as their values would be
cleared every time job executes.
The JobDataMap, which is part of the JobDetail object. It is useful to provide
properties/configuration for Job instance and to keep track of a job's state between executions.
The JobDataMap can be hold any number of (serializable) objects which you want that available
to the job instance when it executes. JobDataMap is an implementation of the Java Map
interface, and has some added convenience methods for storing and retrieving data of primitive
types
Here is a code of putting data into the JobDataMap before adding the job to the Scheduler:
jobDetail.getJobDataMap().put("name",
jobDetail.getJobDataMap().put("floatValue",
"Rose
India");
5.141f);
Here is a of getting data from the JobDataMap during the job's execution:
JobDataMap databMap = context.getJobDetail().getJobDataMap();
String
name
=
float fvalue = dataMap.getFloat("floatValue");
dataMap.getString("name");
Description of the following example:
In the following example we are going to develop a simple Quartz Scheduler application with the
help of Quartz framework. To make a Quartz application we need to make two java classes. In
one class (job class) we provide the job that we want to execute and in another class (schedule
class) we provide the schedule to this class. Job class (NewJob.java) is a implementation of Job
interface and it overrides the execute() method that contains the job which we want to execute
and throws JobExecutionException. And in schedule class (NewSchedule.java) we just
provide the schedule to this job. That program displays a simple message, date, time, job name,
group name and float value indefinite times after the specified time.
Description of Code:
getName()
By this method we get the job name that specified in Schedule class in JobDetail properties.
;
getGroup()
;
By this method we get job group name that specified in Schedule class in JobDetail properties.
getJobDataMap()
;
This method just return the JobDataMap object. And by JobDataMap object we can invoke the
getString() and getFloat() method to retrieve any String or any float value that specified in
Schedule class.
put()
This method is used to just insert the object into the JobDataMap object.
Here is the code of Job Class (NewJob.java) :
import java.util.Date;
import org.quartz.*;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class NewJob implements Job {
public void execute(JobExecutionContext jcontext) throws JobExecutionException {
System.out.println("Welcome to RoseIndia.Net :"+new Date());
String jname = jcontext.getJobDetail().getName();
String jgroup = jcontext.getJobDetail().getGroup();
System.out.println("job Name :"+jname+" Job Group Name :"+jgroup);
JobDataMap jdMap = jcontext.getJobDetail().getJobDataMap();
String name = jdMap.getString("name");
float fval=jdMap.getFloat("floatValue");
System.out.println("Name :"+name+" Float value is :"+fval);
}
}
Download this code
Here is code of Schedule Class (NewSchedule.java) :
import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.*;
public class NewSchedule {
public
NewSchedule()throws Exception{
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
JobDetail jd = new JobDetail("myjob","group",NewJob.class);
jd.getJobDataMap().put("name", "Rose India");
jd.getJobDataMap().put("floatValue",5.14f);
SimpleTrigger simpleTrigger = new SimpleTrigger("mytrigger",sched.DEFAULT_GROUP,
new Date(),null,SimpleTrigger.REPEAT_INDEFINITELY,30L*1000L);
sched.scheduleJob(jd, simpleTrigger);
sched.start();
}
public static void main(String args[]){
try{
new NewSchedule();
}catch(Exception e){}
}
;
}
Download this code
Output of the program :
log4j:WARN No appenders could be found for logger
(org.quartz.simpl.SimpleThreadPool).
log4j:WARN Please initialize the log4j system properly.
Welcome to RoseIndia.Net :Wed Feb 21 14:43:55
GMT+05:30 2007
job Name :myjob Job Group Name :group
Name :Rose India Float value is :5.14
Welcome to RoseIndia.Net :Wed Feb 21 14:44:25
GMT+05:30 2007
job Name :myjob Job Group Name :group
Name :Rose India Float value is :5.14
Stateful vs. Non-Stateful Jobs
A Job instance can be defined as Stateful or Non-Stateful. Non-Stateful jobs only have their
JobDataMap and it stored at the time when the jobs are added to the scheduler. This means
during execution of the job any changes are made to the job data map will be lost and a Stateful
job is just opposite - its JobDataMap is re-stored after every execution of the job. One
disadvantage of Stateful job is that it cannot be executed concurrently. Or in other words: In
Stateful job, and a trigger attempts to 'fire' the job while it is already executing, the trigger will
block (wait) until the previous execution completes. You can specify a job as Stateful by
implementing the StatefulJob interface instead of Job interface.
Other Attributes of Jobs
Some other properties which can be defined for a job instance through the JobDetail object:




Durability - if a job is non-durable, it is automatically deleted from the scheduler once
there are no longer any active triggers associated with it.
Volatility - if a job is volatile, it is not persisted between re-starts of the Quartz scheduler.
RequestRecovery - if a job is "requests recovery", and the job is executing during 'hard
shutdown' time of the scheduler (i.e. the process it is running within crashes, or the
machine is shut off), then it is re-executed when the scheduler is started again. In this
case, the JobExecutionContext.isRecovering() method will return true.
JobListeners - a job can have a set of zero or more JobListeners associated with it.
When the job executes, the listeners are notified.
The Job execute() Method
The only JobExecutionException (including RunTimeExceptions) are allowed to throw from
the execute() method. That's why, you should wrap the entire body of this method in 'try-catch'
block.
In this section we will try to provide the brief description of triggers. As we know that the trigger
objects are used for executing the jobs or firing jobs. When we wish to schedule the jobs, then we
can used the properties of triggers. Here we are going to provide two types of triggers like:
Simple Trigger and Cron Trigger for scheduling the jobs.
Now, we will see how to use these triggers with the Calendar interface.
Calendars
Quartz Calendars (not java.util.Calendar) objects can be associated with triggers object at the
time of the triggers are stored in the scheduler. It is very useful to excluding blocks of time to fire
the triggers schedule. For example, we wish to create a trigger that fires a job every weekday at
4.15 am, in this case we would to add a Calendar that excludes all of the holidays.
We are going to implement the Calendar interface:
Here is the code of Calendar interface:
package org.quartz;
public interface Calendar {
public boolean isTimeIncluded(long timeStamp);
public long getNextIncludedTime(long timeStamp);
}
isTimeIncluded(long
timeStamp);
Above method returns a Boolean type values either true or false. Which takes long type value
(timeStamp) in milliseconds and included by the Calendar interface.
getNextIncluedeTime(long
timeStamp);
This method takes long type value (timeStamp) in millisecond and determine the next time which
is included by the Calendar after the given time.
The Quartz consists of the org.quartz.impl.HolidayCalendar class. The Calendar object
integrated with the scheduler through the addCalendar() method. If you want to use the
HolidayCalendar then first of all you must be initialized it, after that you will use the
addExcludedDate(Date date) method in the program. This method is used to exclude the days
from the scheduling.
Here we are going to implement a simple Calendar object to add and exclude with it:
HolidayCalendar
hcal
cal.addExcludedDate(Date date);
=
new
HolidayCalendar();
sched.addCalendar("myHoliday", hcal, false);
Misfire
Instructions
The triggers contains another important property that is "misfire instruction". Sometimes, a
persistent trigger misses to its firing time because the scheduler being shutdown, in this case the
misfire is occurred. More descriptions about the misfire instruction will provide below with the
Simple and Cron Triggers. The misfire instruction can be used with trigger object by using the
setMisfireInstruction() method.
Simple trigger can be used to one shot execution or fire a job and in other words, we can say that
just a single execution of job to the specified time. Sometimes, we wish to execute or fire a job at
the specified time that has till 'N' repetition times with delay between 'T' executions of jobs that
means if you need to have a job execute exactly once at a specific time, or at a specific moment
in time that is followed by repeats at a specified time interval.
The SimpleTrigger properties contains: a start-time and end-time, a repeat count and a repeat
interval. The repeat count properties can be zero, a positive integer or the constant value
SimpleTrigger.REPEAT_INDEFINITELY. The repeat interval property must be zero or a positive
long value that represents a number of milliseconds. The end-time property over-rides the repeat
count property that can be used for creating a trigger which fires every some specified time (20
seconds). It has to compute the number of times that would be repeated between the start-time
and end-time, if we want to specify the end-time then we can use a repeat count of
REPEAT_INDEFINITELY.
We are going to implement a SimpleTrigger constructor to following types:
public SimpleTrigger(String name, String group, Date startTime, Date endTime, int
repeatCount,
long
repeatInterval);
This is the constructor of java.org.quartz.SimpleTrigger class. Which fires or executes at the
specified time and repeat at the specified number of times. It takes following arguments like this:
name:
This
is
the
name
of
Simple
Trigger.
group:
This
is
the
name
of
scheduler
group.
startTime:
This is the time for firing or executing the Trigger.
endTime: This is the time for the Trigger to drop repeat firing or executing.
repeatCount: This is the number of repeat firing or executing the Trigger by using the
REPEAT_INDEFINITELY
for
no
any
foundation
of
time.
repeatInterval: This is the time (milliseconds) for stopping or pausing the repeat firing.
There are following examples for implementing the SimpleTrigger:
1. Example SimpleTrigger : Create a simple trigger which fires exactly once, 20 seconds from
now:
long startTime = System.currentTimeMillis() + (20L*1000L);
SimpleTrigger strigger = new SimpleTrigger("mySimpleTrigger", sched.DEFAULT_GROUP, new
Date(startTime), null, 0, 0L);
2. Example SimpleTrigger : Create a simple trigger that fires quickly and repeats every 20
seconds:
SimpleTrigger strigger = new SimpleTrigger("mySimpleTrigger", sched.DEFAULT_GROUP, new
Date(), null, SimpleTrigger.REPEAT_INDEFINITELY, 20L * 1000L);
3. Example SimpleTrigger: Create a Simple Trigger that fires quickly and repeats every 10
seconds until 50 seconds from now:
long endTime = System.currentTimeMillis() + (50L * 1000L);
SimpleTrigger strigger = new SimpleTrigger("mySimpleTrigger", sched.DEFAULT_GROUP, new
Date(), new Date(endTime), SimpleTrigger.REPEAT_INDEFINITELY, 10L * 1000L);
4. Example SimpleTrigger: Create a Simple Trigger that fires on February 19 of the year 2007
at accurately 9:15 am, and repeats 10 times with 20 seconds delay between each firing.
java.util.Calendar
cal
=
cal.set(cal.HOUR,
cal.set(cal.MINUTE,
cal.set(cal.SECOND,
cal.set(cal.MILLISECOND, 0);
new
java.util.GregorianCalendar(2007,cal.FEB,
19);
9);
15);
0);
Data startTime = cal.getTime();
SimpleTrigger trigger = new SimpleTrigger("mySimpleTrigger", sched.DEFAULT_GROUP,
startTime, 10, 20L*1000L);
Simple Trigger Misfire Instructions
When the misfire instruction occurs then what should to do the Quartz. There are following misfire
instructions to use for informing the Quartz.
MISFIRE_INSTRUCTION_FIRE_NOW
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_EXISTING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NOW_WITH_REMAINING_REPEAT_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT
MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_EXISTING_COUNT
Here is the also mis-fire instruction that have used for all trigger types:
Trigger.MISFIRE_INSTRUCTION_SMART_POLICY
When we will use the "smart policy" misfire instruction with the triggers then the SimpleTrigger
determine between its various types of mis-fire instructions that depends upon the configuration
and state of the specified SimpleTrigger instance. The JavaDOC has the
SimpleTrigger.updateAfterMisfire() method that describes the brief description of this dynamic
behavior.
The CronTriggers are more useful than the SimpleTrigger, if we want to performed the job
triggering based on the calendar schedules such as "every day", "every weekday" etc. This is
also useful when we need to fire jobs in a schedule that is based on the calendar schedule on the
exact specified time intervals of SimpleTrigger. Here we will execute an expression that fires at
8:30, 9:30, 10:30, and 11:30 on every Monday and Saturday.
Cron Expression
The Cron-Expressions are strings which are used for configuring the instances of CronTrigger.
The Cron-Expressions made up of following sub-expressions that performs individual works
according to it's schedule and that is separated by the white-space. :
1.
2.
3.
4.
5.
6.
Seconds
Minutes
Hours
Day-of-Month
Month
Day-of-Week
Example: The Cron-expression string is "0 0 10 ? * SUN" that means "every Sunday at 10
am". This example reads only the "SUN" from weekday and replaces to all weekday.
The Wild-cards ('* ' character) that can be used for inserting the every possible value of this field.
The '*' character is used in the "Month" field that means "every month" and "Day-Of-Week" field
means "every day of the week".
All fields have some specific values that are specified by us. Such as the numbers 0 to 23 for
hours, 0 to 59 that is used for minutes and seconds, 0 to 31 for Day-of-Month but here, we
should more careful about how many day are used in a month. Months have the specified values
between 0 to 11, for this we will use the some string as like: JAN, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV and DEC. Similarly, the Days-of-week has specified values between
1 to 7. Here 1 for Sunday, 2 for Monday, 3 for Tuesday,....... so on. But here we will use the some
string for this like: SUN, MON, TUE, WED, THU, FRI and SAT.
The Cron-Expressions are used the '/' character for increments to specify values. If we will put
"0/10" in the seconds field that means every 10 seconds will start at second zero and if we will put
"0/20" in the Minutes field then it will simply fires every 20 minutes.
The Cron-Expressions are also used the '?' character that allows for the day-of-month and dayof-week fields for specifying "no specific value".
The 'L' character, it is the short form of "last" that allows us for using the day-of -month and dayof-week fields. If we can use the value 'L' in the day-of-month field that means last day of the
month like: 31 for January, 28 for February not the leap years. In case of day-of-week field that
means "7 stands for SAT".
There are following example of expressions for specify the JavaDOC for CronTrigger:
1.Example: Write an expression to create a trigger that fires ever 10 minutes.
"0 0/10 * * * ?"
2.Example: Write an expression to create a trigger that fires every 10 minutes, at 10 seconds
after the minute.
"10 0/10 * * * ?"
(That means each firing after the 10 seconds interval like: 8:00:00am,
8:10:00am,8:20:00am etc.)
3.Example: Write an expression to create a trigger that fires at 9:30, 10:30, 11:30, 12:30 and
13:30 on every Sunday and Saturday.
"0 30 9-13 ? * SUN, SAT"
In this section we are just providing you a Cron Trigger example and by this, you can better
understand the working of cron trigger.
Description of Program
In this following program we are just creating a Quartz application with the help of cron trigger.
For this, we have to make two classes one is job class (CronJob.java) that is implementation of
Job interface and second one is scheduler class. In scheduler class (CronSchedule.java), firstly
we need the object of scheduler and for this we have to instantiate the SchedulerFactory and
invoke its getScheduler() method. After getting the scheduler we require to instantiate the
JobDetail object with the attributes like job name, group name and the job class name. Now we
used Cron Trigger to firing the job repetitively after the specified time. After doing all these things
we get the simple message like "Welcome to RoseIndia.net" and date specified intervals.
Description of Code
CronTrigger("cronTrigger","group2","0 0/1 * * * ?");
By the above constructor we just create the CronTrigger object with the trigger name, group
name and the cron expression. Cron Expression are used to configuring the instance of CronTrigger. And this corn expression are used to just execute the job after one minute indefinitely.
Here is the code of Job Class (CronJob.class) :
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.*;
public class CronJob implements Job {
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println("Welcome to RoseIndia.net :"+new Date());
}
}
Download this code
Here is the code of Schedule Class (CronSchedule.class) :
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.JobDetail;
public class CronSchedule {
public CronSchedule ()throws Exception {
SchedulerFactory sf=new StdSchedulerFactory();
Scheduler sched=sf.getScheduler();
JobDetail jd=new JobDetail("job1","group1",CronJob.class);
CronTrigger ct=new CronTrigger("cronTrigger","group2","0 0/1 * * * ?");
sched.scheduleJob(jd,ct);
sched.start();
}
public static void main(String args[]){
try{
new CronSchedule();
}catch(Exception e){}
}
}
Download this code
Output of the program :
log4j:WARN No appenders could be found for logger
(org.quartz.simpl.SimpleThreadPool).
log4j:WARN Please initialize the log4j system properly.
Welcome to RoseIndia.net
GMT+05:30 2007
:Fri
Feb
23
15:17:00
Welcome to RoseIndia.net
GMT+05:30 2007
:Fri
Feb
23
15:18:00
Welcome to RoseIndia.net
GMT+05:30 2007
:Fri
Feb
23
15:19:00
In this quartz tutorial, we will learn how to implement more than one triggers and jobs with a
quartz scheduler. We know that the scheduler is a main interface of quartz scheduler that
contains Job Details and Triggers. It has a name and group associated with them and it can be
identified by the single scheduler. See below for an implementation of more than one job details
and triggers.
Description of program:
Here, we are going to implement more than one job details and triggers with the help of following
program that jobs name, triggers name and its firing date and time. We have known about the
quartz application, when we wish to implement any quartz application then we will require two
classes: one is Scheduler class (MoreTriggerSchedule.java) and another is Job class
(MoreTriggerJob.java) that will implement in the Job interface. In this program, the Job class will
represent the job's name, trigger's name and its firing times with day and date as well as GMT
format time. The scheduler class is a main class of this quartz application that implements the
Scheduler instance. But, when we will go to implement this instance then we need an object of
the SchedulerFactory invoked by the getScheduler() method. Now, we start the scheduler by
using the start() method. The quartz Scheduler has JobDetail and CronTrigger objects. These
are attached in the quartz by the scheduleJob() method. After completing the entire processes
then we will get all jobs and triggers to be used in it.
Description of code:
(0/5 * * * * ?): This corn expression provides the facility for firing the trigger every 5 seconds
to un-limit time.
(0/8 * * * * ?): This expression allows to the trigger for firing every 8 seconds to infinite time.
Here is the code of Scheduler class (MoreTriggerSchedule.java):
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
public class MoreTriggerSchedule {
public static void main(String args[]){
try{
new MoreTriggerSchedule();
}catch(Exception e){
e.printStackTrace();
}
}
public MoreTriggerSchedule()throws Exception{
JobDetail jDetail;
CronTrigger cronTrigger;
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sche = sf.getScheduler();
sche.start();
jDetail = new JobDetail("Job1","group1",MoreTriggerJob.class);
cronTrigger = new CronTrigger("cronTrigger1","group1","0/5 * * * * ?");
sche.scheduleJob(jDetail, cronTrigger);
jDetail = new JobDetail("Job2","group2",MoreTriggerJob.class);
cronTrigger = new CronTrigger("cronTrigger2","group2","0/8 * * * * ?");
sche.scheduleJob(jDetail, cronTrigger);
}
}
Download this example.
Here is the code of Job class (MoreTriggerJob.java):
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class MoreTriggerJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
// TODO Auto-generated method stub
System.out.println("Job name: " + context.getJobDetail().getName());
System.out.println("Trigger name: " + context.getTrigger().getName());
System.out.println("Firing Time: " + context.getFireTime());
}
}
Download this example.
Output of program:
log4j:WARN No appenders could be found for logger
(org.quartz.simpl.SimpleThreadPool).
log4j:WARN
properly.
Please
initialize
the
log4j
system
Job name: Job2
Trigger name: cronTrigger2
Firing Time: Tue Feb 27 10:06:56 GMT+05:30 2007
Job name: Job1
Trigger name: cronTrigger1
Firing Time: Tue Feb 27 10:07:00 GMT+05:30 2007
Job name: Job2
Trigger name: cronTrigger2
Firing Time: Tue Feb 27 10:07:00 GMT+05:30 2007
In this section we will see how to shutdown the scheduler in quartz application. As we know that
the scheduler is a main interface of a Quartz Scheduler it maintains the list of JobDetail and
Trigger. If we will implement the Scheduler instances then must have to need the
SchedulerFactory object. After implementation of this, we have to start it by using the start()
method then it will execute (fire) any jobs. Shutdown process of scheduler is given below with
code:
Description of program:
In this program we are going to shutdown the scheduler (SDS) of a quartz application and get the
job name, group name, trigger name and its firing time. When we discuss about implementation
of any quartz application then we needed two classes: one is scheduler class
(StatusSchedule.java) and another is job class (StatusJob.java) that implements the Job
interface. For this, firstly we need to implement a quartz scheduler. If we will implement the quartz
scheduler then it requires the instance of SchedulerFactory and invokes its getScheduler()
method. After that we will start this scheduler with the help of start() method. We know that the
quartz scheduler have list of JobDetail and Trigger. The JobDetail object has the job name, job
group and its class name that implements in Job interface and the CronTrigger object has the
trigger name, trigger group and string type cron expression that is used for configuring the
instance of CronTrigger for firing the job relatively after some specified time. Both are added in
the quartz scheduler by using the scheduleJob() method. After doing this, it will check the
scheduler is shutdown or not. If the scheduler is shutdown then it displays the message
"Scheduler is shutdown" and "Job can't be executed here." Otherwise it will show "Scheduler isn't
shutdown" and "Job is executed here.". Now, we will get the result like: job name, group name,
trigger name and it firing times.
Description of code:
shutdown();
Above method used to shutdown the quartz scheduler that means breaking the scheduler firing of
triggers. The scheduler can not be re-started here.
isShutdown();
This method has the scheduler reports and returns a Boolean type date either true or false. When
it will return true that means scheduler is shutdown otherwise it couldn't be shutdown and
operations are executed here.
getFireTime();
This method has exact trigger firing time.
Here is the code of Scheduler class (StatusSchedule.java):
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
public class StatusSchedule {
public static void main(String args[])
{
try{
new StatusSchedule();
}catch(Exception e){
e.printStackTrace();
}
}
public StatusSchedule()throws Exception{
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sche = sf.getScheduler();
sche.start();
JobDetail jDetail = new JobDetail(
"Show status",sche.DEFAULT_GROUP,StatusJob.class);
CronTrigger cronTrigger = new CronTrigger(
"Cron Trigger",sche.DEFAULT_GROUP,"0 0/1 * * * ?");
sche.scheduleJob(jDetail, cronTrigger);
// sche.shutdown();
if(sche.isShutdown()){
System.out.println("Scheduler is shutdown!");
System.out.println("Job cann't be executed here.");
}
else{
System.out.println("Scheduler isn't shutdown!");
System.out.println("Job is executed here.");
}
}
}
Download this code.
Here is the code of Job class (StatusJob.java):
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class StatusJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
// TODO Auto-generated method stub
String name = context.getJobDetail().getName();
String group = context.getJobDetail().getGroup();
System.out.println("Job name: " + name + "\t" + "Group: " + group);
System.out.println("Trigger name: " + context.getTrigger().getName());
System.out.println("Friring Time: " + context.getFireTime());
}
}
Download this code.
Output of program (Scheduler is not shutdown) :
log4j:WARN No appenders could be found for logger
(org.quartz.simpl.SimpleThreadPool).
log4j:WARN
properly.
Please
initialize
the
log4j
system
Scheduler isn't shutdown!
Job is executed here.
Job name: Show status Group: DEFAULT
Trigger name: Cron Trigger
Friring Time: Mon Feb 26 09:47:00 GMT+05:30 2007
Output of program (Scheduler is shutdown) :
log4j:WARN No appenders could be found for logger
(org.quartz.simpl.SimpleThreadPool).
log4j:WARN
properly.
Please
initialize
Scheduler is shutdown!
Job cann't be executed here.
the
log4j
system
To perform any action you create Listeners objects and these actions are based on events
occurring within the scheduler. TriggerListeners receive events related to triggers, and
JobListeners receive events related to jobs.
Events related to Trigger : trigger firings, trigger mis-firings and trigger completions.
Events related to Job : a notification when the job is about to be executed, and a notification that
the job has completed execution
For creating listener, simply create an object that implements either the org.quartz.JobListener
and/or org.quartz.TriggerListener interface. Then during run time listeners are registered with
the scheduler, and must be given a name. Listeners can be registered as either "global" or "nonglobal". Global listeners receive events for ALL triggers/jobs, and non-global listeners receive
events only for the specific triggers/jobs that explicitly name the listener in their
getJobListenerNames() or getTriggerListenerNames() properties.
scheduler.addGlobalJobListener(myJobListener);
or
scheduler.addJobListener(myJobListener);
SchedulerListeners
SchedulerListeners are much same as TriggerListeners and JobListeners, but they receive
notification of events within the Scheduler itself - its not necessary events related to a specific
trigger or job.
Events related to Scheduler : the addition of a job/trigger, the removal of a job/trigger, a serious
error within the scheduler, notification of the scheduler being shutdown, and others.
SchedulerListeners are created and registered in the same way as the Trigger & Job Listener, but
there is no distinction between global and non-global listeners. SchedulerListeners can be
virtually any object that implements the org.quartz.SchedulerListener interface
Job Store are used to keep track of all the "work data" that you give to the scheduler: jobs,
triggers, calendars, etc. The important step for Quartz Scheduler step is selecting the appropriate
JobStore. You declare which JobStore your scheduler should use (and it's configuration settings)
in the properties file (or object) that you provide to the SchedulerFactory that you use to produce
your
scheduler
instance.
The JobStore is for behind-the-scenes use of Quartz itself. That's why never use JobStore
instance directly in you code. Through configuration you have to tell to Quartz which JobStore to
use, but then you should only work with the Scheduler interface in your code.
RAMJobStore
RAMJobStore is used to keep all of its data in RAM. That's why it is most performant (lightning
fast in terms of CPU time) and simple to configure. The disadvantage is only that at the time of
application crashes or ends all of the scheduling information is lost - this means RAMJobStore
cannot honor the setting of "non-volatility" on jobs and triggers. In other words, this method's
major deficiency is lack of data persistence because it kept all the data in RAM, all information
will be lost upon an application or system crash.
Configuring Quartz to use RAMJobStore :
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
To solve this problem, Quartz offers the JDBCJobStore. This job store keeps all data in a
database through JDBC. The trade-off for data persistence is a lower level of performance, as
well as a higher level of complexity.
JDBCJobStore
As the name infers, it stores all data in a database via JDBC. That's why it is a little bit more
complicated to configure and it is also as faster than RAMJobStore. But the performance
deficiency is not terrible bad, especially when you make the database with indexes on the primary
keys. The JDBCJobStore is compatible with all major databases, it mostly used with Oracle,
MySQL, DB2, MS SQLServer2000.
For using JDBCJobStore your application required two steps. These are follows :
1. You must create the database tables to be used by the job store. Quartz offers a series of
table-creation SQL scripts that ease the setup process. In Quartz distribution
""docs/dbTables" directory you find these SQL scripts. If there is no script according to
you database type, the modify the existing ones in any way according to your database.
In these scripts all table names start with "QRTZ_" prefix. This prefix can be anything
according to your wish, but you have to inform JDBCJobStore what the prefix is (in your
Quartz properties). Different prefixes can be useful for creating multiple set of tables, for
multiple
scheduler
instances,
within
the
same
database.
org.quartz.jobStore.tablePrefix = QRTZ_(optional, customizable)
2. You must set the JobStore class properties of your Quartz configuration :

After creating table, you have to decide: what type of transactions you application
needs, before configuring & firing up the JDBCJobStore. If your application don't
need to tie the scheduling commands like adding trigger and removing trigger, to
other transaction, then Quartz manage the transaction by using JobStoreTX as
your
JobStore.
org.quartz.jobStore.class
=
org.quartz.impl.jdbcjobstore.JobStoreTX

If you need Quartz to work along with other transactions (i.e. within a J2EE
application server), then you should use JobStoreCMT - in that case Quartz will
let
the
application
server
container
manage
the
transactions.
org.quartz.jobStore.class
=
org.quartz.impl.jdbcjobstore.JobStoreCMT

Then select the DriverDelegate for JobStore to use. It is responsible for doing
any JDBC work. StdJDBCDelegate is a delegate that uses JDBC code, SQL
statements to do its work. Some other delegates are include in the package
"org.quartz.impl.jdbcjobstore" and in its sub-packages like DB2v6Delegate,
HSQLDelegate, MSSQLDelegate, PostgreSQLDelegate, WeblogicDelegate
and OracleDelegate. After selecting the delegate set its class name for
JDBCJobStore
to
use:
org.quartz.jobStore.driverDelegateClass
=
org.quartz.impl.jdbcjobstore.StdJDBCDelegate

JDBCJobStore can get the connections to your database by setting up a
DataSource. In Quartz properties DataSource can be defined in different
approaches. One approach is, Quartz can create and manage the DataSource
itself through providing the all connection information to the database. And
another approach is, DataSource is used by Quartz which is managed by an
application server that Quartz is running inside of - by providing JDBCJobStore
the
JNDI
name
of
the
DataSource.
org.quartz.jobStore.dataSource = qzDS
If your Scheduler is very busy that means it always executing the same number of jobs as the
size of the thread pool, then in the DataSource you should set the number of connections about
the size of the thread pool + 1.
Quartz is architected in modularized way, that's why before running it, several components need
to be snapped together. Components need to be configure before Quartz :

ThreadPool - It provides a set of Threads to Quartz and Quartz used these Threads for
executing jobs. The more threads available in pool allows the number of jobs can run
concurrently. Some Quartz users find that they need 5 threads are enough because they
have fewer jobs at any given time, but generally all jobs are not scheduled to execute at
the same time and the jobs complete quickly. But some other users find that they need
10,50 and 100 threads because they have some thousands of triggers with various
schedule, which can end up by around 10 and 100 jobs trying to execute at any given
time. There is no any rule for finding the size of scheduler's pool, it is only depend on
what you are using for the scheduler. Too many threads can bog down your system but
make
sure
you
have
enough
threads
for
executing
the
jobs.
A ThreadPool interface is defined in the "org.quartz.spi" package. Quartz ships with a
simple thread pool named org.quartz.simpl.SimpleThreadPool. It simply maintains a
fixed set of threads in its pool that never shrinks and never grows. But it is otherwise
quite robust and is very well tested - as nearly everyone using Quartz uses this pool.

JobStore - Job Store are used to keep track of all the "work data" that you give to the
scheduler: jobs, triggers, calendars, etc. The important step for Quartz Scheduler step is
selecting the appropriate JobStore. You declare which JobStore your scheduler should
use (and it's configuration settings) in the properties file (or object) that you provide to the
SchedulerFactory
that
you
use
to
produce
your
scheduler
instance.

DataSource - JDBCJobStore can get the connections to your database by setting up a
DataSource. In Quartz properties DataSource can be defined in different approaches.
One approach is, Quartz can create and manage the DataSource itself through providing
the all connection information to the database. And another approach is, DataSource is
used by Quartz which is managed by an application server that Quartz is running inside
of - by providing JDBCJobStore the JNDI name of the DataSource.

Scheduler - Finally, you need to create the instance of your Scheduler. Now the
Scheduler itself needs to be given a name, told its RMI settings, and handed instances of
a JobStore and ThreadPool. The RMI settings include the Scheduler should create itself
as an RMI server object, what host and port to use, etc.. StdSchedulerFactory can create
Scheduler instances that are actually proxies (RMI stubs) to Schedulers created in
remote
processes.
StdSchedulerFactory
StdSchedulerFactory is a class, that is implementation of org.quartz.SchedulerFactory
interface and does all of its work of creating a Quartz Scheduler instance based on the content of
properties file. Generally, properties are stored in and loaded from a file, but can also be created
by your program and handed directly to the factory. Simply invoking getScheduler() on the
factory you get the instance of scheduler.
DirectSchedulerFactory
DirectSchedulerFactory is a class, that is singleton implementation of SchedulerFactory
interface. It is useful for those user that want to create their Scheduler instance in more
programatic way. Generally, it can be used for the following reasons: (1) it requires the user to
have a greater understanding of what they're doing (2) it does not allow for declarative
configuration - or in other words, you end up hard-coding all of the scheduler's settings.
Logging
"org.apache.commons.logging" framework is used by Quartz for its logging needs. Quartz does
not produce so much logging information, it produce some information during initialization and
then messages about serious problems while jobs are executing.
Clustering
Clustering feature works with only JDBCJobStore. It include job fail-over and loaded - balancing.
Setting up the "org.quartz.jobStore.isClustered" property to "true" for enabling the clustering.
Each instance in the cluster used the same copy of the quartz.properties file. Exceptions of this
would be to use properties files that are identical, with the following allowable exceptions:
Different value for the "org.quartz.scheduler.instanceId" property and different thread pool size.
Every node in the cluster MUST have a unique instanceId, which is easily done by placing
"AUTO" as the value of this property.
Never use cluster features on separate machines, until and unless their clocks are synchronized
using some form of time-sync service that runs very regularly. And you can get a serious data
corruption if you fire-up a non clustered instance against the same set of tables that any other
instance is running against.
JTA Transaction
Quartz jobs can execute within a JTA transaction (UserTransaction) by setting the
"org.quartz.scheduler.wrapJobExecutionInUserTransaction" property to "true". After this
setting, a JTA transaction will begin() just before the Job's execute method is invoked, and
commit()
just
after
the
call
to
execute
terminates.
Miscellaneous Features
Plug-Ins
For plugging-in additional functionality Quartz provides an org.quartz.spi.SchedulerPlugin
interface. Plugins are ship with Quartz to provide various utility capabilities. And that can be found
documented in org.quartz.plugins package.
Jobs
Quartz also includes a number of utility jobs. You can add this additional utility jobs in you
application for doing something like sending email and invoking EJBs. These out-of-the-box Jobs
can be found documented in the org.quartz.jobs package.
In this section, we will learn coding methods of establishing the connection between MySQL
database and quartz application for updating and manipulating the data of MySQL database
tables. Here, we are going to provide a simple way for establishing the connection with the help of
following program. See below for detail information.
Description of program:
As we know a quartz application needs two classes: first is scheduler class
(ConnectionScheduler.java) and second one is job class (ConnectionJob.java) that implement
in the Job interface. We will require the SchedulerFactory instance for implementing the
scheduler. After that we have to start the scheduler by using the start() method then we will add
jobs with the help of JobDetail() method. Which contains the name of jobs, job groups and the
class name that has some job to be performed by users. Then we have to create a trigger to
perform the job at a specified time. Both (JobDetail and CronTrigger) objects are added in the
quartz scheduler to the scheduleJob() method. By following the entire process we will implement
the scheduler class. Now, we will require the job class that establishes the connection with the
MySQL database by using the JDBC driver in forName() method. If the JDBC driver doesn't
support then exception is occurred that can be thrown by the ClassNotFoundException and it
will display a message "Class not found!". After getting the JDBC driver we can give the string
type 'url' in the getConnection() method. If we get the connection then it displays the connection
with a message "Connection is created!" and also shows the job name, group name, trigger name
and its firing time.
Here is the code of Scheduler Class (ConnectionScheduler.java):
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
public class ConnectionScheduler {
public static void main(String arg[]){
try{
new ConnectionScheduler();
}
catch(Exception e){
e.printStackTrace();
}
}
public ConnectionScheduler()throws Exception{
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sche = sf.getScheduler();
sche.start();
JobDetail jDetail = new JobDetail(
"JDBC Connection","mysql",ConnectionJob.class);
CronTrigger crTrigger = new CronTrigger(
"cronTrigger","mysql","0/8 * * * * ?");
sche.scheduleJob(jDetail, crTrigger);
}
}
Download this code.
Here is the code of Job Class (ConnectionJob.java):
import java.sql.DriverManager;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
public class ConnectionJob implements Job {
public void execute(JobExecutionContext context)
throws JobExecutionException {
// TODO Auto-generated method stub
System.out.println("Job name:"+context.getJobDetail().getName());
System.out.println("Group name:"+context.getJobDetail().getGroup());
System.out.println("Trigger name:"+context.getTrigger().getName());
System.out.println("Firing Time:"+context.getFireTime());
try{
Class.forName("com.mysql.jdbc.Driver");
}
catch(ClassNotFoundException c){
System.out.println("Class not found!");
}
try{
String url =
"jdbc:mysql://localhost/JDBCquartz?user=root&password=root";
Connection con = (Connection)DriverManager.getConnection(url);
System.out.println("Connection :"+con);
System.out.println("Connection
is
created!");
con.close();
System.exit(0);
}
catch(Exception s){
System.out.println("Doesn't establish the connection!");
System.exit(0);
}
}
}
Download this code.
Download