Sunday, 22 July 2018

Quartz Scheduler with Derby database

In this post, I am going to explain how to setup quartz using derby database. Procedure is same for other databases.

Procedure in Brief
a.   Set up Derby Server
b.   Start the derby server
c.   Connect to Derby Server using Derby client
d.   Create Quartz tables
e.   Create java maven project

Set up Derby Server
Software Requirements
Install Java 8 or higher.

Below step-by-step procedure explains how to set up Derby in your machine.

Step 1: Download Derby.
Go to below location and get the latest version of the Derby.

At the time of writing this post, derby 10.14.2.0 is the latest.

Extract the downloaded zip file, you can see below structure.



Add the bin path of derby installation to your system path.

Set the DERBY_HOME environment variable to the path where you installed Derby

Start the derby server
Open terminal or command prompt and start the derby server by executing below command.

java -jar %DERBY_HOME%\lib\derbyrun.jar server start


C:\>java -jar %DERBY_HOME%\lib\derbyrun.jar server start
Fri Jul 20 14:17:20 IST 2018 : Security manager installed using the Basic server security policy.
Fri Jul 20 14:17:21 IST 2018 Thread[main,5,main] java.io.FileNotFoundException: C:\derby.log (Access is denied)
Fri Jul 20 14:17:21 IST 2018 : Apache Derby Network Server - 10.14.2.0 - (1828579) started and ready to accept connections on port 1527
Fri Jul 20 14:17:21 IST 2018 : Apache Derby Network Server - 10.14.2.0 - (1828579) started and ready to accept connections on port 1527

Connect to Derby Server using Derby client
Open command prompt and execute the statement ‘ij’.
C:\>ij
ij version 10.14
ij>

Execute below statement to create database quartzDemo
CONNECT 'jdbc:derby://localhost:1527/quartzDemo;create=true;user=krishna;password=krishna';

ij> CONNECT 'jdbc:derby://localhost:1527/quartzDemo;create=true;user=krishna;password=krishna';

If you are interested to learn more about above command, I would recommend you to go through my below tutorial.

Create Quartz tables by executing the sql statements located at below location.

Execute all the sql statements from above .sql file.

Below tables are created.

Create new maven project
Add below maven dependencies.
         <dependencies>
                  <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
                  <dependency>
                           <groupId>org.quartz-scheduler</groupId>
                           <artifactId>quartz</artifactId>
                           <version>2.3.0</version>
                  </dependency>

                  <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz-jobs -->
                  <dependency>
                           <groupId>org.quartz-scheduler</groupId>
                           <artifactId>quartz-jobs</artifactId>
                           <version>2.3.0</version>
                  </dependency>

                  <!-- https://mvnrepository.com/artifact/org.apache.derby/derbyclient -->
                  <dependency>
                           <groupId>org.apache.derby</groupId>
                           <artifactId>derbyclient</artifactId>
                           <version>10.14.2.0</version>
                  </dependency>

         </dependencies>

Step 1: Create HelloJob.


HelloJob.java

package com.sample.jobs;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class HelloJob implements Job {
 public void execute(JobExecutionContext jec) throws JobExecutionException {
  System.out.println("Hello!!!");
 }
}

Step 2: Create App.java like below.


App.java

package com.sample.app;

import static org.quartz.DateBuilder.futureDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.TriggerKey.triggerKey;

import java.util.Properties;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

import com.sample.jobs.HelloJob;

public class App {
 public static void main(String[] args) {
  try {
   Properties prop = new Properties();
   
   //RMI configuration to make the client to connect to the Quartz server
            prop.put("org.quartz.scheduler.rmi.export", "true");
            prop.put("org.quartz.scheduler.rmi.createRegistry", "true");
            prop.put("org.quartz.scheduler.rmi.registryHost", "localhost");
            prop.put("org.quartz.scheduler.rmi.registryPort", "1099");
            prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
            prop.put("org.quartz.threadPool.threadCount", "2");
            
   // Quartz Server Properties
   prop.put("quartz.scheduler.instanceName", "ServerScheduler");
   prop.put("org.quartz.scheduler.instanceId", "AUTO");
   prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
   prop.put("org.quartz.scheduler.instanceId", "CLUSTERED");
   prop.put("org.quartz.scheduler.jobFactory.class", "org.quartz.simpl.SimpleJobFactory");
   prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
   prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
   prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");
   prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
   prop.put("org.quartz.jobStore.isClustered", "false");

   // Database properties
   prop.put("org.quartz.dataSource.quartzDataSource.driver", "org.apache.derby.jdbc.ClientDriver");
   prop.put("org.quartz.dataSource.quartzDataSource.URL", "jdbc:derby://localhost:1527/quartzDemo");
   prop.put("org.quartz.dataSource.quartzDataSource.user", "krishna");
   prop.put("org.quartz.dataSource.quartzDataSource.password", "krishna");
   prop.put("org.quartz.dataSource.quartzDataSource.maxConnections", "2");
   
   /* Configure standard scheduler */
   SchedulerFactory stdSchedulerFactory = new StdSchedulerFactory(prop);
   Scheduler scheduler = stdSchedulerFactory.getScheduler();
   scheduler.start();

   /* Configure Job */
   JobDetail printJobDetails = newJob(HelloJob.class).withIdentity("HelloJob", "HelloJobMessagesGroup")
     .build();

   /* Configure Trigger */
   CronTrigger trigger = (CronTrigger) (newTrigger().withIdentity(triggerKey("myTrigger", "myTriggerGroup"))
     .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ?"))
     .startAt(futureDate(500, IntervalUnit.MILLISECOND)).withDescription("Job executes every 3 seconds")
     .build());

   /* Schedule the job */
   scheduler.scheduleJob(printJobDetails, trigger);

  } catch (SchedulerException e) {
   e.printStackTrace();
  }
 }
}


Run App.java, you can able to see below messages in console.

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
MLog initialization issue: slf4j found no binding or threatened to use its (dangerously silent) NOPLogger. We consider the slf4j library not found.
Jul 20, 2018 3:03:28 PM com.mchange.v2.log.MLog 
INFO: MLog clients using java 1.4+ standard logging.
Jul 20, 2018 3:03:29 PM com.mchange.v2.c3p0.C3P0Registry 
INFO: Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
Jul 20, 2018 3:03:30 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 2tzkeo9w1esb05a1v51nwn|1175e2db, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.apache.derby.jdbc.ClientDriver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2tzkeo9w1esb05a1v51nwn|1175e2db, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:derby://localhost:1527/quartzDemo, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 2, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
Jul 20, 2018 3:03:30 PM com.mchange.v2.resourcepool.BasicResourcePool 
WARNING: Bad pool size config, start 3 > max 2. Using 2 as start.
Hello!!!
Hello!!!
Hello!!!
Hello!!!
Hello!!!
Hello!!!
Hello!!!
Hello!!!


As you see above image, trigger is stored in QRTZ_CRON_TRIGGERS table.



Job details are stored in QRTZ_JOB_DETAILS table.



Fired trigger details are stored in QRTZ_FIRED_TRIGGERS table.


All the triggers are stored in QRTZ_TRIGGERS.

Procedure is same for all the other databases integration.
Previous                                                 Next                                                 Home

1 comment: