How can I use SQLite in Quartz?

喜夏-厌秋 提交于 2019-12-12 04:07:48

问题


I'm trying to use quartz with SQLite in an application . When I read the documentation here I notice that they didn't mention SQLite among the databases available. They say:

JDBCJobStore works with nearly any database, it has been used widely with Oracle, PostgreSQL, MySQL, MS SQLServer, HSQLDB, and DB2. To use JDBCJobStore, you must first create a set of database tables for Quartz to use. You can find table-creation SQL scripts in the “docs/dbTables” directory of the Quartz distribution.

So, from this question: Which setup script to use for setting up quartz sqlite table? I use derby script to be applied as my sqlite script.

The problem is when I trying to schedule a trigger in a previous inserted job. This is part of my code:

// and start it off
scheduler.start();

Map<String, String> map = new HashMap<>();
map.put("key", "value");

JobDataMap jdm = new JobDataMap(map);

JobKey key = new JobKey("job1", "key1");

 if(!scheduler.checkExists(key)){
     JobDetail job = newJob(HelloJob.class).withIdentity(key).storeDurably().usingJobData(jdm).build();
     addJob(scheduler, job);

     // Trigger the job to run now, and then repeat every 40 seconds
    Trigger trigger = newTrigger()
         .withIdentity("trigger1", "group1")
         .startNow()
            .forJob(job)
               .withSchedule(simpleSchedule()
                 .withIntervalInSeconds(40)
                 .repeatForever())            
         .build();

    // Tell quartz to schedule the job using our trigger
    scheduler.scheduleJob(trigger); // here is where I get an error
 }

Thread.sleep(60000);

scheduler.shutdown();

My quartz.properties is this:

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 5
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.dataSource.SQLiteDB.driver = org.sqlite.JDBC
org.quartz.dataSource.SQLiteDB.URL = jdbc:sqlite:bota.db
org.quartz.dataSource.SQLiteDB.maxConnections = 30
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.dataSource = SQLiteDB

I'm using sqlite v-3.8.11.2 and quartz v-2.2.2. This is what I get in the log:

org.quartz.JobPersistenceException: Couldn't store trigger 'group1.trigger1' for 'key1.job1' job:Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: org.quartz.JobPersistenceException: Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: java.sql.SQLException: not implemented by SQLite JDBC driver]]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1223)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$4.executeVoid(JobStoreSupport.java:1159)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3715)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3713)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3799)
    at org.quartz.impl.jdbcjobstore.JobStoreTX.executeInLock(JobStoreTX.java:93)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1155)
    at org.quartz.core.QuartzScheduler.scheduleJob(QuartzScheduler.java:932)
    at org.quartz.impl.StdScheduler.scheduleJob(StdScheduler.java:258)
    at javaapplication2.JavaApplication2.main(JavaApplication2.java:174)
Caused by: org.quartz.JobPersistenceException: Couldn't retrieve job: not implemented by SQLite JDBC driver [See nested exception: java.sql.SQLException: not implemented by SQLite JDBC driver]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1396)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1205)
    ... 9 more
Caused by: java.sql.SQLException: not implemented by SQLite JDBC driver
    at org.sqlite.jdbc4.JDBC4ResultSet.unused(JDBC4ResultSet.java:320)
    at org.sqlite.jdbc4.JDBC4ResultSet.getBlob(JDBC4ResultSet.java:345)
    at com.mchange.v2.c3p0.impl.NewProxyResultSet.getBlob(NewProxyResultSet.java:285)
    at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.getObjectFromBlob(StdJDBCDelegate.java:3190)
    at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:860)
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1385)
    ... 10 more
BUILD STOPPED (total time: 11 seconds)

回答1:


The problem seems to be that the sqlite jdbc driver does not support the method ResultSet.getBlob().

But quartz uses this method to retrieve the JobDataMap that is assigned to a Job.

If you still want to use quartz with sqlite you could extend the StdJDBCDelegate and retrieve/set blobs like suggested in this answer.

At first glance it seems that you only must override the methods

  1. StdJDBCDelegate.getObjectFromBlob() and
  2. StdJDBCDelegate.getJobDataFromBlob()

Since I'm not sure wether later come more problems ( for example you could see that the sqlite jdbcdriver has a lot more unsupported ResultSet methods ) I would rather recommend to use a database which works out-of the-box.




回答2:


As per the suggestions of mam10eks, following code worked for me.

package com.example.quartz.sqlite;   

import org.quartz.impl.jdbcjobstore.StdJDBCDelegate;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.sql.ResultSet;
import java.sql.SQLException;

public class CustomJDBCDelegate extends StdJDBCDelegate {
  @Override
  protected Object getObjectFromBlob(ResultSet rs, String colName) throws ClassNotFoundException, IOException, SQLException {
    byte[] bytes = rs.getBytes(colName);
    Object map = null;
    ByteArrayInputStream bais = null;
    ObjectInputStream ois = null;
    try {
      bais = new ByteArrayInputStream(bytes);
      ois = new ObjectInputStream(bais);
      map = ois.readObject();
    } catch (EOFException ex1) {
      bais.close();
    } catch (IOException e) {
      // Error in de-serialization
      e.printStackTrace();
    }

    return map;
  }

  @Override
  protected Object getJobDataFromBlob(ResultSet rs, String colName) throws ClassNotFoundException, IOException, SQLException {
    return getObjectFromBlob(rs, colName);
  }
}

Now put following in quartz.properties

org.quartz.jobStore.driverDelegateClass=com.example.quartz.sqlite.CustomJDBCDelegate


来源:https://stackoverflow.com/questions/36779788/how-can-i-use-sqlite-in-quartz

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!