Quartz Scheduler using JDBC JobStore - java

For the first time i stored the jobs and scheduled them using crontrigger with the below code.
package com.generalsentiment.test.quartz;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import java.util.Date;
import java.util.Properties;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SchedulerMetaData;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CronTriggerExample {
public void run() throws Exception {
Logger log = LoggerFactory.getLogger(CronTriggerExample.class);
System.out.println("------- Initializing -------------------");
Xml config = new Xml("src/hibernate.cfg.xml", "hibernate-configuration");
Properties prop = new Properties();
prop.setProperty("org.quartz.scheduler.instanceName", "ALARM_SCHEDULER");
prop.setProperty("org.quartz.threadPool.class",
"org.quartz.simpl.SimpleThreadPool");
prop.setProperty("org.quartz.threadPool.threadCount", "4");
prop.setProperty("org.quartz.threadPool
.threadsInheritContextClassLoaderOfInitializingThread", "true");
prop.setProperty("org.quartz.jobStore.class",
"org.quartz.impl.jdbcjobstore.JobStoreTX");
prop.setProperty("org.quartz.jobStore.driverDelegateClass",
"org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
prop.setProperty("org.quartz.jobStore.dataSource", "tasksDataStore");
prop.setProperty("org.quartz.jobStore.tablePrefix", "QRTZ_");
prop.setProperty("org.quartz.jobStore.misfireThreshold", "60000");
prop.setProperty("org.quartz.jobStore.isClustered", "false");
prop.setProperty("org.quartz.dataSource.tasksDataStore.driver",
config.child("session-factory").children("property").get(1).content());
prop.setProperty("org.quartz.dataSource.tasksDataStore.URL", config.child("session-
factory").children("property").get(2).content());
prop.setProperty("org.quartz.dataSource.tasksDataStore.user", config.child("session-
factory").children("property").get(3).content());
prop.setProperty("org.quartz.dataSource.tasksDataStore.password",
config.child("session-factory").children("property").get(4).content());
prop.setProperty("org.quartz.dataSource.tasksDataStore.maxConnections", "20");
// First we must get a reference to a scheduler
SchedulerFactory sf = new StdSchedulerFactory(prop);
Scheduler sched = sf.getScheduler();
System.out.println("------- Initialization Complete --------");
System.out.println("------- Scheduling Jobs ----------------");
// jobs can be scheduled before sched.start() has been called
// job 1 will run exactly at 12:55 daily
JobDetail job = newJob(SimpleJob.class).withIdentity("job2", "group2").build();
CronTrigger trigger = newTrigger().withIdentity("trigger2", "group2")
.withSchedule(cronSchedule("00 15 15 * *
?")).build();
Date ft = sched.scheduleJob(job, trigger);
System.out.println(sched.getSchedulerName());
System.out.println(job.getKey() + " has been scheduled to run at: " + ft
+ " and repeat based on expression: "
+ trigger.getCronExpression());
System.out.println("------- Starting Scheduler ----------------");
/*
* All of the jobs have been added to the scheduler, but none of the
* jobs will run until the scheduler has been started. If you have
* multiple jobs performing multiple tasks, then its recommended to
* write it in separate classes, like SimpleJob.class writes
* organization members to file.
*/
sched.start();
System.out.println("------- Started Scheduler -----------------");
System.out.println("------- Waiting five minutes... ------------");
try {
// wait five minutes to show jobs
Thread.sleep(300L * 1000L);
// executing...
} catch (Exception e) {
}
System.out.println("------- Shutting Down ---------------------");
sched.shutdown(true);
System.out.println("------- Shutdown Complete -----------------");
SchedulerMetaData metaData = sched.getMetaData();
System.out.println("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
}
public static void main(String[] args) throws Exception {
CronTriggerExample example = new CronTriggerExample();
example.run();
}
}
And the details are stored in Tables - QRTZ_CRON_TRIGGERS, QRTZ_JOB_DETAILS & QRTZ_TRIGGERS
My doubt is How to schedule the jobs that are stored in DB. How to display the list of jobs in a jsp page & how to trigger them automatically.
Ours is a struts2 application with Hibernate3 ORM. I am trying to initialize the quartz scheduler when the application loads. But am unable to.

Date ft = sched.scheduleJob(job, trigger);
When this is called, your job would be scheduled for the next fire time. The scheduled job would stored in the appropriate DB tables.
To Display the list of jobs on a jsp, you should persist you job key as well as custom description of what your job entails to another DB table so that during retrieval you can retrieve this custom description as well as data Quartz persist into its own tables.
Triggering this jobs automatically is something Quartz handles for you. Once the crone expression is set to what is desired and your Job class implements org.quartz.Job, Quartz would run the execute() method at your desired next fire time

JobDetail job = newJob(SimpleJob.class).withIdentity("job2", "group2").build();
this means you will have a class named SimpleJob that implements org.quartz.Job. In that class execute() method need to be implemented. Job is triggered automatically at the time you specified by cron expression. That execute method is called when job is triggered.

Related

How to create a scheduler task in Window Task Scheduler using Java?

I want to create a task under Window Task Scheduler using my java code.
OS I am using is win7 64bit.
After creating the task I have to edit the scheduled time weekly or biweekly.
Is there any window scheduler API to use in java code or command to use under command prompt?
Launch the command line utility schtasks.
To create the task.
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TestWinScheduler {
public static void main(String args[]) throws IOException, InterruptedException {
// schtasks /create /tn "HowToTask" /tr c:\temp\test.cmd /sc once /st 00:00:00 /sd 2022/01/01 /ru username /rp password
List<String> commands = new ArrayList<String>();
commands.add("schtasks.exe");
commands.add("/CREATE");
commands.add("/TN");
commands.add("\"HowToTask\"");
commands.add("/TR");
commands.add("\"c:/temp/test.cmd\"");
commands.add("/SC");
commands.add("once");
commands.add("/ST");
commands.add("00:00:00");
commands.add("/SD");
commands.add("2022/10/10");
commands.add("/RU");
commands.add("username");
commands.add("/RP");
commands.add("password");
ProcessBuilder builder = new ProcessBuilder(commands);
Process p = builder.start();
p.waitFor();
System.out.println(p.exitValue()); // 0 : OK
// 1 : Error
}
}
To execute a task :
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class TestWinScheduler {
public static void main(String args[]) throws IOException, InterruptedException {
// schtasks /run /tn "HowToTask"
List<String> commands = new ArrayList<String>();
commands.add("schtasks.exe");
commands.add("/RUN");
commands.add("/TN");
commands.add("\"HowtoTask\"");
ProcessBuilder builder = new ProcessBuilder(commands);
Process p = builder.start();
p.waitFor();
System.out.println(p.exitValue()); // 0 : OK
// 1 : Error
}
}
Ref
Windows have already a task scheduler that you can invoke from command line: Schtasks.exe
SCHTASKS /parameter [arguments]
Description:
Enables an administrator to create, delete, query, change, run and
end scheduled tasks on a local or remote system.
Parameter List:
/Create Creates a new scheduled task.
/Delete Deletes the scheduled task(s).
/Query Displays all scheduled tasks.
/Change Changes the properties of scheduled task.
/Run Runs the scheduled task on demand.
/End Stops the currently running scheduled task.
/ShowSid Shows the security identifier corresponding to a scheduled t
ask name.
/? Displays this help message.
Try this one http://yajsw.sourceforge.net/. Using "YAJSW" (Yet Another Java Service Wrapper) you can register your java service as a windows service.

Closing and releasing JMS resources

The question is simple: How do I properly close and release JMS resources in a Java SE application. I use IBM MQ v8.
My problem is that IBM MQ for JMS seems to start a thread named "JMSCCThreadPoolMaster" which doesn't die when there's no more JMS in the application. It lives on until the application itself dies. This is not what I want. I want to be able to close down that thread pool programmatically. My application only does 2 secs of JMS on startup and then goes on to to do other things for weeks or even months in a fairly resource constrained environment. It seems unreasonable that that I'm not able to tell JMS that I'm done with using it after the first 2 secs, so that resources are properly released.
Here's a little test to prove the point:
package org.test.jms.producer.simpleconsumer;
import com.ibm.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsConstants;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.wmq.WMQConstants;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Queue;
import javax.jms.Session;
public class MyTest {
private static final Logger LOGGER = Logger.getLogger(MyTest.class.getName());
public static void main(String[] args) throws JMSException, InterruptedException {
// Do some JMS stuff in a separate thread.
Thread jmsThread = new Thread(new JmsRunnable());
jmsThread.start();
// Wait some time to allow any background thread to properly
// close down.
Thread.sleep(60*1000);
// Print the threads that exist at this point in time.
Thread[] threads = new Thread[100];
int noOfThreads = Thread.enumerate(threads);
for (Thread t : threads) {
if (t != null) {
System.out.println(" Active thread : " + t.getName());
}
}
}
private static class JmsRunnable implements Runnable {
#Override
public void run() {
try {
// just do a connect and then immediately disconnect.
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(JmsConstants.WMQ_PROVIDER);
JmsConnectionFactory factory = ff.createConnectionFactory();
Map<String, Object> props = new HashMap<>();
props.put(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
props.put(WMQConstants.WMQ_HOST_NAME, "localhost");
props.put(WMQConstants.WMQ_QUEUE_MANAGER, "dev");
props.put(WMQConstants.WMQ_CHANNEL, "mychannel");
factory.setBatchProperties(props);
Connection connection = factory.createConnection(); // ++
connection.close();
LOGGER.log(Level.INFO, "Thread is closing");
} catch (JMSException ex) {
LOGGER.log(Level.SEVERE, "Something bad happened", ex);
}
}
}
}
At the point where I list active threads there should no longer be any active JMS resources held onto by application. Yet there's this background thread.
The line marked with "++" is what triggers the creation of the background thread named "JMSCCThreadPoolMaster".
How to properly close down? A solution specific to IBM MQ is acceptable, i.e. it will be ok for me to cast to IBM MQ specific JMS class.

Implement Quartz Scheduler in mule

This is the first time i am trying to use a Quartz scheduler in Mule.
I am trying to schedule the start time of a flow based on the list of DateTimes that i took from DB.
To study the working of a Quatrz scheduler and to schedule jobs based on a 'list of times' in java, i did the following sample.
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
public class Main {
public static void main(String[] args) throws SchedulerException {
List<SimpleTrigger> triggerList = scheduleMyJob();
int i=0;
for(SimpleTrigger trigger: triggerList){
JobDetail jobDetail = new JobDetail();
jobDetail.setJobClass(Hellojob.class);
jobDetail.setName("MyJob"+ ++i);
Scheduler jobScheduler = new StdSchedulerFactory().getScheduler();
jobScheduler.start();
jobScheduler.scheduleJob(jobDetail, trigger);
}
}
public static List<SimpleTrigger> scheduleMyJob(){
List<SimpleTrigger> triggerList = new ArrayList<SimpleTrigger>();
SimpleTrigger sTrigger = new SimpleTrigger();
sTrigger.setStartTime(new Date(System.currentTimeMillis()+10000));
sTrigger.setName("C Trigger 1");
triggerList.add(sTrigger);
sTrigger = new SimpleTrigger();
sTrigger.setStartTime(new Date(System.currentTimeMillis()+20000));
sTrigger.setName("C Trigger 2");
triggerList.add(sTrigger);
sTrigger = new SimpleTrigger();
sTrigger.setStartTime(new Date(System.currentTimeMillis()+30000));
sTrigger.setName("C Trigger 3");
triggerList.add(sTrigger);
sTrigger = new SimpleTrigger();
sTrigger.setStartTime(new Date(System.currentTimeMillis()+40000));
sTrigger.setName("C Trigger 4");
triggerList.add(sTrigger);
return triggerList;
}
}
My helloJob.java looks like..
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class Hellojob implements Job {
public void execute(JobExecutionContext arg0) throws JobExecutionException {
System.out.println(new Date() +": Hello Quartz World!! "+arg0.getJobDetail().getFullName());
}
}
This works well, I got the following output
Sat Oct 24 15:41:47 IST 2015: Hello Quartz World!! DEFAULT.MyJob1
Sat Oct 24 15:41:57 IST 2015: Hello Quartz World!! DEFAULT.MyJob2
Sat Oct 24 15:42:07 IST 2015: Hello Quartz World!! DEFAULT.MyJob3
Sat Oct 24 15:42:17 IST 2015: Hello Quartz World!! DEFAULT.MyJob4
Now i understood the working of Quartz,but i have a hardtime relating the java code with the concept of Quartz in mule. I want to implement exactly the same thing in mule, and later i can replace the dates with those from DB. If you could guide me or show me an example, it will be of great help.
I only know about Quartz scheduler, if you got a different idea, you are always welcome...
FYI. Hellojob will be replaced by a flow with a logger in it.
[Tyring to implemant the logic in mule ended up no where.So i am not posting that code here since it may give a wrong assumtion of what my real target is!!. Java code above is a perfect example]
To implement Batch Processing in Mule you can Mule Batch Processing Module which internally uses quartz scheduler and will make your life easier. You can assign CRON expression to schedule jobs. Please refer to the below mention docs to learn how Batch jobs works in mule.
https://docs.mulesoft.com/mule-user-guide/v/3.6/batch-processing
https://docs.mulesoft.com/mule-user-guide/v/3.7/batch-streaming-and-job-execution

java quartz scheduler run at specific time

For example, I want to write a Java program to print "Hello World" at each day 12 am, how can I use Quartz scheduler to achieve this?
Trigger trigger = TriggerUtils.makeDailyTrigger(0, 0);
trigger.setName("trigger1");
trigger.setGroup("group1");
Like this? Where should I put print "hello world" method?
You could use an expression to schedule the execution of the job. e.g.:
public static class HelloJob implements Job {
#Override
public void execute(JobExecutionContext ctx) throws JobExecutionException {
System.out.println("Hello World");
}
}
public static void main(String[] args) throws SchedulerException {
String exp = "0 0 0 1/1 * ? *";
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
scheduler.start();
JobDetail job = JobBuilder.newJob(HelloJob.class).build();
Trigger trigger = TriggerBuilder.newTrigger()
.startNow()
.withSchedule(
CronScheduleBuilder.cronSchedule(exp))
.build();
scheduler.scheduleJob(job, trigger);
}
See http://www.cronmaker.com/ for build another expression. e.g. 0 0/1 * 1/1 * ? * every minute for to see the output. See also Cron Expressions.
Download quartz Jar Put in lib folder build project
Create Class (Job) from which you want to schedule task
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class MyJob implements Job {
private Logger log = Logger.getLogger(MyJob.class);
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
log.debug("Hi....");
System.out.println("Corn Executing.....");
}
}
Create Class for schedule your task
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
public class JobScheduler {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myjob").build();
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(30).repeatForever()).build();
SchedulerFactory schFactory = new StdSchedulerFactory();
Scheduler scheduler = schFactory.getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
}catch (SchedulerException e) {
e.printStackTrace();
}
}
}
You have to create your custom job by implementing Job interface and providing your implementation of execute method.In execute method you can print "hello world". Then you can schedule your job like this
scheduler.scheduleJob(job, trigger);
Refer this link for step by step details:
Quartz tutorial
you can create cron expression for this. to have quartz job you need to have following objects
Job
Task which will be associated to a Job
Finally create a trigger and associate a Job to the trigger
Triggers of two type
Simple triggers, where you can control job , you can run every min or 10 mins and so on. you can also have additional parameters
initial delay - to kick off
repeatcount - no of times the job should be executes, if -1 then job will be executed infinitely
In your case you can use cron triggers since you want to run every day at 12 am.
For more details and sample program look at this below link
http://www.mkyong.com/spring/spring-quartz-scheduler-example/
and about quartz cron expression , see the quartz documentation
http://quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger

Have an EJB schedule tasks with "crontab syntax"

I am trying to figure out the possibilities I have to solve the following problem.
a) I want to have a database table that uses "crontab syntax" to schedule tasks, the structure would be something like this:
|-Id-|---Crontab Syntax---|---------Task----------|
| 1 | 30 * * * * * | MyClass.TaskA(args[]) |
| 2 | 0 1 * * 1-5 * | MyClass.TaskB(args[]) |
| | | |
The above table will be modified at any time by an external application. Tasks added or removed should instantly affect the scheduler.
b) The scheduler itself should reside on a Java application server. It should constantly be synched with the active scheduled tasks in the database table. Whenever a schedule event occurs it should trigger/call an EJB with the value in 'Task' as argument.
I am not looking for an answer to the above problem. But rather some input in what frameworks can be used for the crontab parsing and in what manner the EJB representing the scheduler should be deployed.
Thanks in advance.
See the EJB 3.1 #Schedule API. The API we chose for the spec is a little closer to Quartz syntax than cron -- tiny variances between the two.
Here's an annotation example:
package org.superbiz.corn;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import javax.ejb.Singleton;
import java.util.concurrent.atomic.AtomicInteger;
/**
* This is where we schedule all of Farmer Brown's corn jobs
*/
#Singleton
#Lock(LockType.READ) // allows timers to execute in parallel
public class FarmerBrown {
private final AtomicInteger checks = new AtomicInteger();
#Schedules({
#Schedule(month = "5", dayOfMonth = "20-Last", minute = "0", hour = "8"),
#Schedule(month = "6", dayOfMonth = "1-10", minute = "0", hour = "8")
})
private void plantTheCorn() {
// Dig out the planter!!!
}
#Schedules({
#Schedule(month = "9", dayOfMonth = "20-Last", minute = "0", hour = "8"),
#Schedule(month = "10", dayOfMonth = "1-10", minute = "0", hour = "8")
})
private void harvestTheCorn() {
// Dig out the combine!!!
}
#Schedule(second = "*", minute = "*", hour = "*")
private void checkOnTheDaughters() {
checks.incrementAndGet();
}
public int getChecks() {
return checks.get();
}
}
Full source for this here
You can do the same thing programmatically via the ScheduleExpression class which is just a constructable version of the above annotation. Here's what the above example would look like if the schedule was done in code:
package org.superbiz.corn;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.ScheduleExpression;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import java.util.concurrent.atomic.AtomicInteger;
/**
* This is where we schedule all of Farmer Brown's corn jobs
*
* #version $Revision$ $Date$
*/
#Singleton
#Lock(LockType.READ) // allows timers to execute in parallel
#Startup
public class FarmerBrown {
private final AtomicInteger checks = new AtomicInteger();
#Resource
private TimerService timerService;
#PostConstruct
private void construct() {
final TimerConfig plantTheCorn = new TimerConfig("plantTheCorn", false);
timerService.createCalendarTimer(new ScheduleExpression().month(5).dayOfMonth("20-Last").minute(0).hour(8), plantTheCorn);
timerService.createCalendarTimer(new ScheduleExpression().month(6).dayOfMonth("1-10").minute(0).hour(8), plantTheCorn);
final TimerConfig harvestTheCorn = new TimerConfig("harvestTheCorn", false);
timerService.createCalendarTimer(new ScheduleExpression().month(9).dayOfMonth("20-Last").minute(0).hour(8), harvestTheCorn);
timerService.createCalendarTimer(new ScheduleExpression().month(10).dayOfMonth("1-10").minute(0).hour(8), harvestTheCorn);
final TimerConfig checkOnTheDaughters = new TimerConfig("checkOnTheDaughters", false);
timerService.createCalendarTimer(new ScheduleExpression().second("*").minute("*").hour("*"), checkOnTheDaughters);
}
#Timeout
public void timeout(Timer timer) {
if ("plantTheCorn".equals(timer.getInfo())) {
plantTheCorn();
} else if ("harvestTheCorn".equals(timer.getInfo())) {
harvestTheCorn();
} else if ("checkOnTheDaughters".equals(timer.getInfo())) {
checkOnTheDaughters();
}
}
private void plantTheCorn() {
// Dig out the planter!!!
}
private void harvestTheCorn() {
// Dig out the combine!!!
}
private void checkOnTheDaughters() {
checks.incrementAndGet();
}
public int getChecks() {
return checks.get();
}
}
The source for this example is here
Side note, both examples are runnable in a plain IDE and have test cases that use the Embeddable EJBContainer API also new in EJB 3.1.
#Schedule vs ScheduleExpression
#Schedule
Statically configured
Many schedule methods are possible
Not possible to pass arguments
Cannot be cancelled
The above is all done in the deployment descriptor and is therefore limited to only things that can be configured in advance. The more dynamic version uses the following signature of the TimerService:
TimerService.createCalendarTimer(javax.ejb.ScheduleExpression, javax.ejb.TimerConfig)
ScheduleExpression
Dynamically created
Exactly one #Timeout supports all ScheduleExpression
The timeout method must take javax.ejb.Timer as a parameter
Arguments can be passed
The caller wraps arguments in a TimerConfig.setInfo(Serializable) object
The #Timeout method accesses them via Timer.getInfo()
Can be cancelled by the caller or the #Timeout method
Also note that there is an interceptor #AroundTimeout annotation that functions identically to #AroundInvoke and allows interceptors to participate in the bean's timer functionality.
EJB has its own built in timers, but you'll have to write the boilerplate code to translate cron parsing. The parsing of the cron instructions themselves should be trivial.
If you're not afraid of venturing outside of EJB, Quartz is as lexicore mentioned an excellent option.
Take a look at Quartz. If you use Spring there's very good support there. A neat, reliable good-working thing.

Categories

Resources