Learn to execute multiple Spring batch jobs using quartz scheduler and persistent database storage recording used by quartz to record jobs and trigger information. I am using H2
database with web console enabled to view data in DB tables. You can select DB as per your requirement.
Table of Contents Project Structure Maven Dependencies Configure Spring Batch Jobs and Tasks Configure Quartz Jobs and Triggers Configure H2 Database Run the Demo
Project Structure
Goals
In this tutorial, we will create an Spring application and perform following tasks.
- Create 2 spring batch jobs. Each job has multiple steps.
- Create quartz jobs and triggers which will run spring batch jobs create in step 1.
- Quartz jobs and triggers will be stored in persistent H2 database in file-system.
- Verify the trigger information stored in DB through H2 console.
- Logging complete trigger history in logs using
LoggingTriggerHistoryPlugin
.
Package Structure

Maven Dependencies
We need to have following dependencies to run this project.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd; <modelVersion>4.0.0</modelVersion> <groupId>com.howtodoinjava</groupId> <artifactId>App</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>App</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.3.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>repository.spring.release</id> <name>Spring GA Repository</name> <url>http://repo.spring.io/release</url> </repository> </repositories> </project>
Configure Spring Batch Jobs and Tasks
Create some Tasklets
and batch jobs to execute.
import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; public class MyTaskOne implements Tasklet { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { System.out.println("MyTaskOne start.."); // ... your code System.out.println("MyTaskOne done.."); return RepeatStatus.FINISHED; } } public class MyTaskTwo implements Tasklet { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { System.out.println("MyTaskTwo start.."); // ... your code System.out.println("MyTaskTwo done.."); return RepeatStatus.FINISHED; } }
import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.howtodoinjava.demo.tasks.MyTaskOne; import com.howtodoinjava.demo.tasks.MyTaskTwo; @Configuration @EnableBatchProcessing public class BatchConfig { @Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory steps; @Bean public Step stepOne(){ return steps.get("stepOne") .tasklet(new MyTaskOne()) .build(); } @Bean public Step stepTwo(){ return steps.get("stepTwo") .tasklet(new MyTaskTwo()) .build(); } @Bean(name="demoJobOne") public Job demoJobOne(){ return jobs.get("demoJobOne") .start(stepOne()) .next(stepTwo()) .build(); } @Bean(name="demoJobTwo") public Job demoJobTwo(){ return jobs.get("demoJobTwo") .flow(stepOne()) .build() .build(); } }
#Disable batch job's auto start spring.batch.job.enabled=false
Configure Quartz Jobs and Triggers
Now create quartz job, which will run the spring batch jobs.
import org.quartz.DisallowConcurrentExecution; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.PersistJobDataAfterExecution; import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.JobLocator; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; @PersistJobDataAfterExecution @DisallowConcurrentExecution public class CustomQuartzJob extends QuartzJobBean { private String jobName; private JobLauncher jobLauncher; private JobLocator jobLocator; public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { try { ApplicationContext applicationContext = (ApplicationContext) context.getScheduler().getContext().get("applicationContext"); jobLocator = (JobLocator) applicationContext.getBean(JobLocator.class); jobLauncher = (JobLauncher) applicationContext.getBean(JobLauncher.class); Job job = jobLocator.getJob(jobName); JobParameters params = new JobParametersBuilder() .addString("JobID", String.valueOf(System.currentTimeMillis())) .toJobParameters(); jobLauncher.run(job, params); } catch (Exception e) { e.printStackTrace(); } } }
import java.io.IOException; import java.util.Properties; import org.quartz.JobBuilder; import org.quartz.JobDataMap; import org.quartz.JobDetail; import org.quartz.SchedulerException; import org.quartz.SimpleScheduleBuilder; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.springframework.batch.core.configuration.JobRegistry; import org.springframework.batch.core.configuration.support.JobRegistryBeanPostProcessor; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import com.howtodoinjava.demo.jobs.CustomQuartzJob; @Configuration public class QuartzConfig { @Bean public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) { JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor(); jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry); return jobRegistryBeanPostProcessor; } @Bean public JobDetail jobOneDetail() { //Set Job data map JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("jobName", "demoJobOne"); return JobBuilder.newJob(CustomQuartzJob.class) .withIdentity("demoJobOne",null) .setJobData(jobDataMap) .storeDurably() .build(); } @Bean public JobDetail jobTwoDetail() { //Set Job data map JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put("jobName", "demoJobTwo"); return JobBuilder.newJob(CustomQuartzJob.class) .withIdentity("demoJobTwo",null) .setJobData(jobDataMap) .storeDurably() .build(); } @Bean public Trigger jobOneTrigger() { SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(10) .repeatForever(); return TriggerBuilder .newTrigger() .forJob(jobOneDetail()) .withIdentity("jobOneTrigger",null) .withSchedule(scheduleBuilder) .build(); } @Bean public Trigger jobTwoTrigger() { SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder .simpleSchedule() .withIntervalInSeconds(20) .repeatForever(); return TriggerBuilder .newTrigger() .forJob(jobTwoDetail()) .withIdentity("jobTwoTrigger",null) .withSchedule(scheduleBuilder) .build(); } @Bean public SchedulerFactoryBean schedulerFactoryBean() throws IOException, SchedulerException { SchedulerFactoryBean scheduler = new SchedulerFactoryBean(); scheduler.setTriggers(jobOneTrigger(), jobTwoTrigger()); scheduler.setQuartzProperties(quartzProperties()); scheduler.setJobDetails(jobOneDetail(), jobTwoDetail()); scheduler.setApplicationContextSchedulerContextKey("applicationContext"); return scheduler; } public Properties quartzProperties() throws IOException { PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties")); propertiesFactoryBean.afterPropertiesSet(); return propertiesFactoryBean.getObject(); } }
#scheduler name will be "MyScheduler" org.quartz.scheduler.instanceName=TestScheduler org.quartz.scheduler.instanceId=AUTO #maximum of 3 jobs can be run simultaneously org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool org.quartz.threadPool.threadCount=50 #Log trigger history org.quartz.plugin.triggerHistory.class=org.quartz.plugins.history.LoggingTriggerHistoryPlugin org.quartz.plugin.triggerHistory.triggerFiredMessage=Trigger [{1}.{0}] fired job [{6}.{5}] scheduled at: {2, date, dd-MM-yyyy HH:mm:ss.SSS}, next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS} org.quartz.plugin.triggerHistory.triggerCompleteMessage=Trigger [{1}.{0}] completed firing job [{6}.{5}] with resulting trigger instruction code: {9}. Next scheduled at: {3, date, dd-MM-yyyy HH:mm:ss.SSS} org.quartz.plugin.triggerHistory.triggerMisfiredMessage=Trigger [{1}.{0}] misfired job [{6}.{5}]. Should have fired at: {3, date, dd-MM-yyyy HH:mm:ss.SSS}
Configure H2 Database
Configure quartz to use H2 database using properties in quartz.properties
file.
#Quartz persistent jobStore config org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.tablePrefix=QRTZ_ org.quartz.jobStore.dataSource=myDS org.quartz.jobStore.useProperties=false org.quartz.jobStore.isClustered=false #Quartz dataSource org.quartz.dataSource.myDS.driver=org.h2.Driver org.quartz.dataSource.myDS.URL=jdbc:h2:file:~/h2/testdb;INIT=RUNSCRIPT FROM 'classpath:schema.sql' org.quartz.dataSource.myDS.user=sa org.quartz.dataSource.myDS.password = org.quartz.dataSource.myDS.maxConnections=5 org.quartz.dataSource.myDS.validationQuery=select 1
Quartz does not create the necessary tables in database automatically, you need to create them while application startup. I have done using org.quartz.dataSource.myDS.URL
property above. Schema queries are in schema.sql
file.
DROP TABLE IF EXISTS QRTZ_CALENDARS; DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; DROP TABLE IF EXISTS QRTZ_LOCKS; DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; DROP TABLE IF EXISTS qrtz_simprop_triggers; DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; DROP TABLE IF EXISTS QRTZ_TRIGGERS; DROP TABLE IF EXISTS qrtz_simprop_triggers; CREATE TABLE QRTZ_CALENDARS ( SCHED_NAME VARCHAR(120) NOT NULL, CALENDAR_NAME VARCHAR (200) NOT NULL , CALENDAR IMAGE NOT NULL ); CREATE TABLE QRTZ_CRON_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR (200) NOT NULL , TRIGGER_GROUP VARCHAR (200) NOT NULL , CRON_EXPRESSION VARCHAR (120) NOT NULL , TIME_ZONE_ID VARCHAR (80) ); CREATE TABLE QRTZ_FIRED_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, ENTRY_ID VARCHAR (95) NOT NULL , TRIGGER_NAME VARCHAR (200) NOT NULL , TRIGGER_GROUP VARCHAR (200) NOT NULL , INSTANCE_NAME VARCHAR (200) NOT NULL , FIRED_TIME BIGINT NOT NULL , SCHED_TIME BIGINT NOT NULL , PRIORITY INTEGER NOT NULL , STATE VARCHAR (16) NOT NULL, JOB_NAME VARCHAR (200) NULL , JOB_GROUP VARCHAR (200) NULL , IS_NONCONCURRENT BOOLEAN NULL , REQUESTS_RECOVERY BOOLEAN NULL ); CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_GROUP VARCHAR (200) NOT NULL ); CREATE TABLE QRTZ_SCHEDULER_STATE ( SCHED_NAME VARCHAR(120) NOT NULL, INSTANCE_NAME VARCHAR (200) NOT NULL , LAST_CHECKIN_TIME BIGINT NOT NULL , CHECKIN_INTERVAL BIGINT NOT NULL ); CREATE TABLE QRTZ_LOCKS ( SCHED_NAME VARCHAR(120) NOT NULL, LOCK_NAME VARCHAR (40) NOT NULL ); CREATE TABLE QRTZ_JOB_DETAILS ( SCHED_NAME VARCHAR(120) NOT NULL, JOB_NAME VARCHAR (200) NOT NULL , JOB_GROUP VARCHAR (200) NOT NULL , DESCRIPTION VARCHAR (250) NULL , JOB_CLASS_NAME VARCHAR (250) NOT NULL , IS_DURABLE BOOLEAN NOT NULL , IS_NONCONCURRENT BOOLEAN NOT NULL , IS_UPDATE_DATA BOOLEAN NOT NULL , REQUESTS_RECOVERY BOOLEAN NOT NULL , JOB_DATA IMAGE NULL ); CREATE TABLE QRTZ_SIMPLE_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR (200) NOT NULL , TRIGGER_GROUP VARCHAR (200) NOT NULL , REPEAT_COUNT BIGINT NOT NULL , REPEAT_INTERVAL BIGINT NOT NULL , TIMES_TRIGGERED BIGINT NOT NULL ); CREATE TABLE qrtz_simprop_triggers ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR(200) NOT NULL, TRIGGER_GROUP VARCHAR(200) NOT NULL, STR_PROP_1 VARCHAR(512) NULL, STR_PROP_2 VARCHAR(512) NULL, STR_PROP_3 VARCHAR(512) NULL, INT_PROP_1 INTEGER NULL, INT_PROP_2 INTEGER NULL, LONG_PROP_1 BIGINT NULL, LONG_PROP_2 BIGINT NULL, DEC_PROP_1 NUMERIC(13,4) NULL, DEC_PROP_2 NUMERIC(13,4) NULL, BOOL_PROP_1 BOOLEAN NULL, BOOL_PROP_2 BOOLEAN NULL, ); CREATE TABLE QRTZ_BLOB_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR (200) NOT NULL , TRIGGER_GROUP VARCHAR (200) NOT NULL , BLOB_DATA IMAGE NULL ); CREATE TABLE QRTZ_TRIGGERS ( SCHED_NAME VARCHAR(120) NOT NULL, TRIGGER_NAME VARCHAR (200) NOT NULL , TRIGGER_GROUP VARCHAR (200) NOT NULL , JOB_NAME VARCHAR (200) NOT NULL , JOB_GROUP VARCHAR (200) NOT NULL , DESCRIPTION VARCHAR (250) NULL , NEXT_FIRE_TIME BIGINT NULL , PREV_FIRE_TIME BIGINT NULL , PRIORITY INTEGER NULL , TRIGGER_STATE VARCHAR (16) NOT NULL , TRIGGER_TYPE VARCHAR (8) NOT NULL , START_TIME BIGINT NOT NULL , END_TIME BIGINT NULL , CALENDAR_NAME VARCHAR (200) NULL , MISFIRE_INSTR SMALLINT NULL , JOB_DATA IMAGE NULL ); ALTER TABLE QRTZ_CALENDARS ADD CONSTRAINT PK_QRTZ_CALENDARS PRIMARY KEY ( SCHED_NAME, CALENDAR_NAME ); ALTER TABLE QRTZ_CRON_TRIGGERS ADD CONSTRAINT PK_QRTZ_CRON_TRIGGERS PRIMARY KEY ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ); ALTER TABLE QRTZ_FIRED_TRIGGERS ADD CONSTRAINT PK_QRTZ_FIRED_TRIGGERS PRIMARY KEY ( SCHED_NAME, ENTRY_ID ); ALTER TABLE QRTZ_PAUSED_TRIGGER_GRPS ADD CONSTRAINT PK_QRTZ_PAUSED_TRIGGER_GRPS PRIMARY KEY ( SCHED_NAME, TRIGGER_GROUP ); ALTER TABLE QRTZ_SCHEDULER_STATE ADD CONSTRAINT PK_QRTZ_SCHEDULER_STATE PRIMARY KEY ( SCHED_NAME, INSTANCE_NAME ); ALTER TABLE QRTZ_LOCKS ADD CONSTRAINT PK_QRTZ_LOCKS PRIMARY KEY ( SCHED_NAME, LOCK_NAME ); ALTER TABLE QRTZ_JOB_DETAILS ADD CONSTRAINT PK_QRTZ_JOB_DETAILS PRIMARY KEY ( SCHED_NAME, JOB_NAME, JOB_GROUP ); ALTER TABLE QRTZ_SIMPLE_TRIGGERS ADD CONSTRAINT PK_QRTZ_SIMPLE_TRIGGERS PRIMARY KEY ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ); ALTER TABLE QRTZ_SIMPROP_TRIGGERS ADD CONSTRAINT PK_QRTZ_SIMPROP_TRIGGERS PRIMARY KEY ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ); ALTER TABLE QRTZ_TRIGGERS ADD CONSTRAINT PK_QRTZ_TRIGGERS PRIMARY KEY ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ); ALTER TABLE QRTZ_CRON_TRIGGERS ADD CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ) REFERENCES QRTZ_TRIGGERS ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ) ON DELETE CASCADE; ALTER TABLE QRTZ_SIMPLE_TRIGGERS ADD CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ) REFERENCES QRTZ_TRIGGERS ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ) ON DELETE CASCADE; ALTER TABLE QRTZ_SIMPROP_TRIGGERS ADD CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ) REFERENCES QRTZ_TRIGGERS ( SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP ) ON DELETE CASCADE; ALTER TABLE QRTZ_TRIGGERS ADD CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS FOREIGN KEY ( SCHED_NAME, JOB_NAME, JOB_GROUP ) REFERENCES QRTZ_JOB_DETAILS ( SCHED_NAME, JOB_NAME, JOB_GROUP ); COMMIT;
Run the Demo
Configure logging and start the application
To format log statements, I have created custom logback.xml
.
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true"> <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <charset>UTF-8</charset> <Pattern>%d{yyyy-MM-dd HH:mm:ss} %p %X{TXNID} - %m%n</Pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="consoleAppender" /> </root> </configuration>
Start the application as Spring boot application.
package com.howtodoinjava.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
Verify job executions
Verify the executing Spring batch jobs in server console.
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.3.RELEASE) 2018-07-06 09:29:07 INFO - Starting App on MACHINE-ID with PID 13456 (C:\Users\lokesh\workspace\App\target\classes started by lokesh in C:\Users\lokesh\workspace\App) 2018-07-06 09:29:07 INFO - No active profile set, falling back to default profiles: default 2018-07-06 09:29:08 INFO - Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@23529fee: startup date [Fri Jul 06 09:29:08 IST 2018]; root of context hierarchy 2018-07-06 09:29:10 INFO - Bean 'quartzConfig' of type [com.howtodoinjava.demo.config.QuartzConfig$$EnhancerBySpringCGLIB$$78eca775] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:10 INFO - Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$11c34f14] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:10 INFO - Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:10 INFO - Bean 'org.springframework.boot.context.properties.ConversionServiceDeducer$Factory' of type [org.springframework.boot.context.properties.ConversionServiceDeducer$Factory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:10 INFO - Bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:10 INFO - Bean 'dataSource' of type [com.zaxxer.hikari.HikariDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:10 INFO - HikariPool-1 - Starting... 2018-07-06 09:29:11 INFO - HikariPool-1 - Start completed. 2018-07-06 09:29:11 INFO - Executing SQL script from URL [file:/C:/Users/lokesh/workspace/App/target/classes/schema.sql] 2018-07-06 09:29:11 INFO - Executed SQL script from URL [file:/C:/Users/lokesh/workspace/App/target/classes/schema.sql] in 66 ms. 2018-07-06 09:29:11 INFO - Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker' of type [org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:11 INFO - Bean 'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration' of type [org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$1186297a] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:11 INFO - Bean 'jobRegistry' of type [com.sun.proxy.$Proxy49] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2018-07-06 09:29:12 INFO - Tomcat initialized with port(s): 8080 (http) 2018-07-06 09:29:12 INFO - Initializing ProtocolHandler ["http-nio-8080"] 2018-07-06 09:29:12 INFO - Starting service [Tomcat] 2018-07-06 09:29:12 INFO - Starting Servlet Engine: Apache Tomcat/8.5.31 2018-07-06 09:29:12 INFO - Initializing Spring embedded WebApplicationContext 2018-07-06 09:29:12 INFO - Root WebApplicationContext: initialization completed in 4505 ms 2018-07-06 09:29:12 INFO - Servlet webServlet mapped to [/console/*] 2018-07-06 09:29:12 INFO - Servlet dispatcherServlet mapped to [/] 2018-07-06 09:29:12 INFO - Mapping filter: 'characterEncodingFilter' to: [/*] 2018-07-06 09:29:12 INFO - Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2018-07-06 09:29:12 INFO - Mapping filter: 'httpPutFormContentFilter' to: [/*] 2018-07-06 09:29:12 INFO - Mapping filter: 'requestContextFilter' to: [/*] 2018-07-06 09:29:13 INFO - No database type set, using meta data indicating: H2 2018-07-06 09:29:13 INFO - No TaskExecutor has been set, defaulting to synchronous executor. 2018-07-06 09:29:13 INFO - Executing SQL script from class path resource [org/quartz/impl/jdbcjobstore/tables_h2.sql] 2018-07-06 09:29:13 INFO - Executed SQL script from class path resource [org/quartz/impl/jdbcjobstore/tables_h2.sql] in 21 ms. 2018-07-06 09:29:13 INFO - Using ConnectionProvider class 'org.quartz.utils.C3p0PoolingConnectionProvider' for data source 'myDS' 2018-07-06 09:29:13 INFO - MLog clients using slf4j logging. 2018-07-06 09:29:13 INFO - Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10] 2018-07-06 09:29:13 INFO - Using default implementation for ThreadExecutor 2018-07-06 09:29:14 INFO - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2018-07-06 09:29:14 INFO - Quartz Scheduler v.2.3.0 created. 2018-07-06 09:29:14 INFO - Using thread monitor-based data access locking (synchronization). 2018-07-06 09:29:14 INFO - JobStoreTX initialized. 2018-07-06 09:29:14 INFO - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 50 threads. Using job-store 'org.quartz.impl.jdbcjobstore.JobStoreTX' - which supports persistence. and is not clustered. 2018-07-06 09:29:14 INFO - Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance. 2018-07-06 09:29:14 INFO - Quartz scheduler version: 2.3.0 2018-07-06 09:29:14 INFO - JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@3db64bd4 2018-07-06 09:29:14 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 -> 8jgsvm9wug78a3djgl4a|73ab3aac, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.h2.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 8jgsvm9wug78a3djgl4a|73ab3aac, idleConnectionTestPeriod -> 50, initialPoolSize -> 3, jdbcUrl -> jdbc:h2:file:~/h2/testdb;INIT=RUNSCRIPT FROM 'classpath:schema.sql', maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 5, maxStatements -> 0, maxStatementsPerConnection -> 120, minPoolSize -> 1, numHelperThreads -> 3, preferredTestQuery -> select 1, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ] 2018-07-06 09:29:15 INFO - Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-07-06 09:29:15 INFO - Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@23529fee: startup date [Fri Jul 06 09:29:08 IST 2018]; root of context hierarchy 2018-07-06 09:29:15 INFO - Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2018-07-06 09:29:15 INFO - Mapped "{[/error],produces=}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2018-07-06 09:29:15 INFO - Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-07-06 09:29:15 INFO - Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2018-07-06 09:29:15 INFO - Executing SQL script from class path resource [org/springframework/batch/core/schema-h2.sql] 2018-07-06 09:29:16 INFO - Executed SQL script from class path resource [org/springframework/batch/core/schema-h2.sql] in 105 ms. 2018-07-06 09:29:16 INFO - Registering beans for JMX exposure on startup 2018-07-06 09:29:16 INFO - Bean with name 'dataSource' has been autodetected for JMX exposure 2018-07-06 09:29:16 INFO - Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource] 2018-07-06 09:29:16 INFO - Starting beans in phase 2147483647 2018-07-06 09:29:16 INFO - Starting Quartz Scheduler now 2018-07-06 09:29:16 INFO - Freed 0 triggers from 'acquired' / 'blocked' state. 2018-07-06 09:29:16 INFO - Recovering 0 jobs that were in-progress at the time of the last shut-down. 2018-07-06 09:29:16 INFO - Recovery complete. 2018-07-06 09:29:16 INFO - Removed 0 'complete' triggers. 2018-07-06 09:29:16 INFO - Removed 0 stale fired job entries. 2018-07-06 09:29:16 INFO - Scheduler schedulerFactoryBean_$_NON_CLUSTERED started. 2018-07-06 09:29:16 INFO - Starting ProtocolHandler ["http-nio-8080"] 2018-07-06 09:29:16 INFO - Using a shared selector for servlet write/read 2018-07-06 09:29:16 INFO - Tomcat started on port(s): 8080 (http) with context path '' 2018-07-06 09:29:16 INFO - Started App in 9.709 seconds (JVM running for 10.821) 2018-07-06 09:29:17 INFO - Trigger [DEFAULT.jobOneTrigger] fired job [DEFAULT.demoJobOne] scheduled at: 06-07-2018 09:29:13.524, next scheduled at: 06-07-2018 09:29:23.524 2018-07-06 09:29:17 INFO - Trigger [DEFAULT.jobTwoTrigger] fired job [DEFAULT.demoJobTwo] scheduled at: 06-07-2018 09:29:13.565, next scheduled at: 06-07-2018 09:29:33.565 2018-07-06 09:29:17 INFO - Job: [FlowJob: [name=demoJobTwo]] launched with the following parameters: [{JobID=1530849557198}] 2018-07-06 09:29:17 INFO - Executing step: [stepOne] MyTaskOne start.. MyTaskOne done.. 2018-07-06 09:29:17 INFO - Job: [FlowJob: [name=demoJobTwo]] completed with the following parameters: [{JobID=1530849557198}] and the following status: [COMPLETED] 2018-07-06 09:29:17 INFO - Trigger [DEFAULT.jobTwoTrigger] completed firing job [DEFAULT.demoJobTwo] with resulting trigger instruction code: DO NOTHING. Next scheduled at: 06-07-2018 09:29:33.565 2018-07-06 09:29:17 INFO - Job: [SimpleJob: [name=demoJobOne]] launched with the following parameters: [{JobID=1530849557093}] 2018-07-06 09:29:17 INFO - Executing step: [stepOne] MyTaskOne start.. MyTaskOne done.. 2018-07-06 09:29:17 INFO - Executing step: [stepTwo] MyTaskTwo start.. MyTaskTwo done.. 2018-07-06 09:29:17 INFO - Job: [SimpleJob: [name=demoJobOne]] completed with the following parameters: [{JobID=1530849557093}] and the following status: [COMPLETED] 2018-07-06 09:29:17 INFO - Trigger [DEFAULT.jobOneTrigger] completed firing job [DEFAULT.demoJobOne] with resulting trigger instruction code: DO NOTHING. Next scheduled at: 06-07-2018 09:29:23.524 2018-07-06 09:29:23 INFO - Trigger [DEFAULT.jobOneTrigger] fired job [DEFAULT.demoJobOne] scheduled at: 06-07-2018 09:29:23.524, next scheduled at: 06-07-2018 09:29:33.524 2018-07-06 09:29:23 INFO - Job: [SimpleJob: [name=demoJobOne]] launched with the following parameters: [{JobID=1530849563538}] 2018-07-06 09:29:23 INFO - Executing step: [stepOne] MyTaskOne start.. MyTaskOne done.. 2018-07-06 09:29:23 INFO - Executing step: [stepTwo] MyTaskTwo start.. MyTaskTwo done.. 2018-07-06 09:29:23 INFO - Job: [SimpleJob: [name=demoJobOne]] completed with the following parameters: [{JobID=1530849563538}] and the following status: [COMPLETED] 2018-07-06 09:29:23 INFO - Trigger [DEFAULT.jobOneTrigger] completed firing job [DEFAULT.demoJobOne] with resulting trigger instruction code: DO NOTHING. Next scheduled at: 06-07-2018 09:29:33.524
Verify H2 Console
Access the H2 console using browser URL: http://localhost:8080/console/

Drop me your questions in comments section.
Happy Learning !!
Leave a Reply