Search code examples
springh2quartz

How do I persist jobs to a H2 database from a Spring project


How do I persist Quartz jobs to a H2 file database from a Spring project?

I have a Spring app that schedules jobs using Quartz. It works, but I lose all the jobs when the app shuts down. I would like to persist these jobs to a H2 database (in a local file). My project is built with gradle. I have read a lot of examples built using older versions of the various libraries, but either I can't get them to work or I cannot replicate them in my test project. I have read some docs that seemed helpful, and tried many different settings in application.properties, but my app still starts up using the default in memory job store.

Amongst a lot of other things, I have looked at:

http://www.quartz-scheduler.org/documentation/quartz-2.1.7/configuration/ConfigJobStoreTX.html

http://www.quartz-scheduler.org/documentation/quartz-2.1.7/configuration/ConfigDataSources.html

https://dzone.com/articles/mule-quartz-connector-how-to-use-jdbc-jobstore-ins

https://www.candlepinproject.org/docs/candlepin/quartz_setup.html

application.properties

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate

spring.datasource.driver-class-name=org.h2.Driver  
spring.datasource.url=jdbc:h2:file:~/testqrtz  
spring.datasource.username=admin   
spring.datasource.password=admin  
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect  

spring.h2.console.enabled=true  
spring.h2.console.path=/h2  

build.gradle

plugins {
    id 'org.springframework.boot' version '2.2.0.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {  
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'  
    implementation 'org.springframework.boot:spring-boot-starter-quartz'  
    implementation 'org.springframework.boot:spring-boot-starter-web'  
    runtimeOnly 'com.h2database:h2'  
}

What happens when I run this project

Triggers are not persisted. Quartz tables are not created. The project continues to use the default job store. This message shows on boot up:

Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

Solution

  • I think the question is why does quartz uses the RAMJobStore despite that fact the the OP shows that the JDBC store was configured.

    I think that the answer is in the wrong spring integration done with quartz in this project.

    Obviously quartz starts "somehow" with a default configuration (which is among other things uses RAMJobStore).

    application.properties where all the properties are defined sounds more like spring boot's configuration file and not the quartz's one (usually called quartz.properties).

    Usually, you need to define the scheduler bean and specify where exactly would you like to read the configuration from:

    @Bean
    public SchedulerFactoryBean scheduler(Trigger trigger, JobDetail job, DataSource 
       quartzDataSource) {
         SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
         schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
         ...
         schedulerFactory.setJobDetails(job);
         schedulerFactory.setTriggers(trigger);
         schedulerFactory.setDataSource(quartzDataSource);
         return schedulerFactory;
    }
    

    This is one possible reason of what can go wrong, Here please find more details and all-in-all check the spring integration with quartz.