如何配置Postgres + Spring + Quartz?

时间:2013-06-01 02:25:32

标签: spring quartz-scheduler

我正在尝试为quartz jdbc store配置Spring 3.2 + Quartz 2.1 + PostgreSQL。但是我得到了下面的例外情况。我已经为石英创建了所有必需的postgres表。

弹簧配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    ">

    <context:annotation-config />
    <context:component-scan base-package="com.example.spring.task.quartz"></context:component-scan>


    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://localhost:5432/springquartz" />
        <property name="username" value="springquartz" />
        <property name="password" value="password" />
    </bean>

    <tx:annotation-driven mode="proxy" transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="persistenceUnitName" value="testUnit" />
        <property name="packagesToScan">
            <list>
                <value>com.example.spring.tx.jpa</value>
            </list>
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQL82Dialect" />
                <property name="database" value="POSTGRESQL" />
            </bean>
        </property>
        <property name="jpaProperties">
            <map>
                <entry key="hibernate.format_sql" value="true" />
            </map>
        </property>
    </bean>

    <task:annotation-driven executor="myExecutor" scheduler="myScheduler" mode="proxy" proxy-target-class="true" />
    <task:executor id="myExecutor" pool-size="5" />
    <task:scheduler id="myScheduler" pool-size="10" />

    <bean name="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.example.spring.task.quartz.ExampleJob" />
        <property name="durability" value="true" />
        <property name="jobDataAsMap">
            <map>
                <entry key="timeout" value="5" />
            </map>
        </property>
    </bean>

    <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail" />
        <property name="startDelay" value="0" />
        <property name="repeatInterval" value="1" />
    </bean>

    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="jobDetail" />
        <property name="cronExpression" value="0 0 6 * * ?" />
    </bean>

    <bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="schedulerName" value="example-scheduler"></property>
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager"></property>
        <property name="quartzProperties">
            <map>
                <entry key="org.quartz.scheduler.skipUpdateCheck" value="true" />
            </map>
        </property>
        <property name="triggers">
            <list>
                <ref bean="cronTrigger" />
                <ref bean="simpleTrigger" />
            </list>
        </property>
    </bean>
</beans>

我正在使用的代码

package com.example.spring.task.quartz;

import org.quartz.Scheduler;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class QuartzExampleJobMain
{
    @SuppressWarnings("resource")
    public static void main(String[] args) throws Throwable
    {
        String path = QuartzExampleJobMain.class.getName().replace('.', '/') + ".xml";
        ClassPathXmlApplicationContext beanFactory = new ClassPathXmlApplicationContext(path);

        Scheduler scheduler = (Scheduler) beanFactory.getBean("quartzScheduler");
    }
}

例外,我到了。

22:43:44,915 INFO  [QuartzScheduler] Quartz Scheduler v.2.1.7 created.
22:43:44,923 DEBUG [DataSourceUtils] Fetching JDBC Connection from DataSource
22:43:44,924 DEBUG [DriverManagerDataSource] Creating new JDBC DriverManager Connection to [jdbc:postgresql://localhost:5432/springquartz]
22:43:44,929 DEBUG [DataSourceUtils] Returning JDBC Connection to DataSource
22:43:44,930 INFO  [LocalDataSourceJobStore] Using db table-based data access locking (synchronization).
22:43:44,932 INFO  [LocalDataSourceJobStore] JobStoreCMT initialized.
22:43:44,932 INFO  [QuartzScheduler] Scheduler meta-data: Quartz Scheduler (v2.1.7) 'example-scheduler' 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 10 threads.
  Using job-store 'org.springframework.scheduling.quartz.LocalDataSourceJobStore' - which supports persistence. and is not clustered.

22:43:44,932 INFO  [StdSchedulerFactory] Quartz scheduler 'example-scheduler' initialized from an externally provided properties instance.
22:43:44,932 INFO  [StdSchedulerFactory] Quartz scheduler version: 2.1.7
22:43:44,934 INFO  [QuartzScheduler] JobFactory set to: org.springframework.scheduling.quartz.AdaptableJobFactory@2d403f93
22:43:44,935 DEBUG [DataSourceTransactionManager] Creating new transaction with name [null]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
22:43:44,935 DEBUG [DriverManagerDataSource] Creating new JDBC DriverManager Connection to [jdbc:postgresql://localhost:5432/springquartz]
22:43:44,941 DEBUG [DataSourceTransactionManager] Acquired Connection [org.postgresql.jdbc4.Jdbc4Connection@b2bfd8a] for JDBC transaction
22:43:44,943 DEBUG [DataSourceTransactionManager] Switching JDBC Connection [org.postgresql.jdbc4.Jdbc4Connection@b2bfd8a] to manual commit
22:43:44,957 DEBUG [LocalDataSourceJobStore] Adding TriggerPersistenceDelegate of type: org.quartz.impl.jdbcjobstore.SimpleTriggerPersistenceDelegate
22:43:44,957 DEBUG [LocalDataSourceJobStore] Adding TriggerPersistenceDelegate of type: org.quartz.impl.jdbcjobstore.CronTriggerPersistenceDelegate
22:43:44,958 DEBUG [LocalDataSourceJobStore] Adding TriggerPersistenceDelegate of type: org.quartz.impl.jdbcjobstore.CalendarIntervalTriggerPersistenceDelegate
22:43:44,959 DEBUG [LocalDataSourceJobStore] Adding TriggerPersistenceDelegate of type: org.quartz.impl.jdbcjobstore.DailyTimeIntervalTriggerPersistenceDelegate
22:43:44,966 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' is desired by: main
22:43:44,966 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' is being obtained: main
22:43:44,966 DEBUG [StdRowLockSemaphore] Inserting new lock row for lock: 'TRIGGER_ACCESS' being obtained by thread: main
22:43:44,967 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' given to: main
22:43:44,977 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' returned by: main
22:43:44,979 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' is desired by: main
22:43:44,979 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' is being obtained: main
22:43:44,979 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' given to: main
22:43:44,983 DEBUG [StdRowLockSemaphore] Lock 'TRIGGER_ACCESS' returned by: main
22:43:44,983 DEBUG [DataSourceTransactionManager] Initiating transaction rollback
22:43:44,983 DEBUG [DataSourceTransactionManager] Rolling back JDBC transaction on Connection [org.postgresql.jdbc4.Jdbc4Connection@b2bfd8a]
22:43:44,984 DEBUG [DataSourceTransactionManager] Releasing JDBC Connection [org.postgresql.jdbc4.Jdbc4Connection@b2bfd8a] after transaction
22:43:44,984 DEBUG [DataSourceUtils] Returning JDBC Connection to DataSource
22:43:44,984 INFO  [DefaultListableBeanFactory] Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@8a0cbbe: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,dataSource,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,transactionManager,entityManagerFactory,org.springframework.context.annotation.internalAsyncAnnotationProcessor,org.springframework.context.annotation.internalScheduledAnnotationProcessor,myExecutor,myScheduler,jobDetail,simpleTrigger,cronTrigger,quartzScheduler,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
22:43:44,988 DEBUG [DisposableBeanAdapter] Invoking destroy() on bean with name 'entityManagerFactory'
22:43:44,988 INFO  [LocalContainerEntityManagerFactoryBean] Closing JPA EntityManagerFactory for persistence unit 'testUnit'
22:43:44,988 DEBUG [SessionFactoryImpl] HHH000031: Closing
22:43:44,989 DEBUG [EntityManagerFactoryRegistry] Remove: name=testUnit
22:43:44,989 DEBUG [DefaultListableBeanFactory] Retrieved dependent beans for bean 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#5c7d517': [entityManagerFactory]
22:43:44,989 DEBUG [DisposableBeanAdapter] Invoking destroy() on bean with name 'org.springframework.context.annotation.internalScheduledAnnotationProcessor'
22:43:44,989 DEBUG [DisposableBeanAdapter] Invoking destroy() on bean with name 'myScheduler'
22:43:44,989 INFO  [ThreadPoolTaskScheduler] Shutting down ExecutorService 'myScheduler'
22:43:44,989 DEBUG [DisposableBeanAdapter] Invoking destroy() on bean with name 'myExecutor'
22:43:44,989 INFO  [ThreadPoolTaskExecutor] Shutting down ExecutorService
    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'quartzScheduler' defined in class path resource [com/example/spring/task/quartz/QuartzExampleJobMain.xml]: Invocation of init method failed; nested exception is org.quartz.JobPersistenceException: Couldn't store trigger 'DEFAULT.cronTrigger' for 'DEFAULT.jobDetail' job:Bad value for type long : \xaced0005737200156f72672e71756172747a2e4a6f62446174614d61709fb083e8bfa9b0cb020000787200266f72672e71756172747a2e7574696c732e537472696e674b65794469727479466c61674d61708208e8c3fbc55d280200015a0013616c6c6f77735472616e7369656e74446174617872001d6f72672e71756172747a2e7574696c732e4469727479466c61674d617013e62ead28760ace0200025a000564697274794c00036d617074000f4c6a6176612f7574696c2f4d61703b787001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000174000774696d656f7574740001357800 [See nested exception: org.postgresql.util.PSQLException: Bad value for type long : \xaced0005737200156f72672e71756172747a2e4a6f62446174614d61709fb083e8bfa9b0cb020000787200266f72672e71756172747a2e7574696c732e537472696e674b65794469727479466c61674d61708208e8c3fbc55d280200015a0013616c6c6f77735472616e7369656e74446174617872001d6f72672e71756172747a2e7574696c732e4469727479466c61674d617013e62ead28760ace0200025a000564697274794c00036d617074000f4c6a6176612f7574696c2f4d61703b787001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000174000774696d656f7574740001357800]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1488)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:608)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
        at com.example.spring.task.quartz.QuartzExampleJobMain.main(QuartzExampleJobMain.java:16)
    Caused by: org.quartz.JobPersistenceException: Couldn't store trigger 'DEFAULT.cronTrigger' for 'DEFAULT.jobDetail' job:Bad value for type long : \xaced0005737200156f72672e71756172747a2e4a6f62446174614d61709fb083e8bfa9b0cb020000787200266f72672e71756172747a2e7574696c732e537472696e674b65794469727479466c61674d61708208e8c3fbc55d280200015a0013616c6c6f77735472616e7369656e74446174617872001d6f72672e71756172747a2e7574696c732e4469727479466c61674d617013e62ead28760ace0200025a000564697274794c00036d617074000f4c6a6176612f7574696c2f4d61703b787001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000174000774696d656f7574740001357800 [See nested exception: org.postgresql.util.PSQLException: Bad value for type long : \xaced0005737200156f72672e71756172747a2e4a6f62446174614d61709fb083e8bfa9b0cb020000787200266f72672e71756172747a2e7574696c732e537472696e674b65794469727479466c61674d61708208e8c3fbc55d280200015a0013616c6c6f77735472616e7369656e74446174617872001d6f72672e71756172747a2e7574696c732e4469727479466c61674d617013e62ead28760ace0200025a000564697274794c00036d617074000f4c6a6176612f7574696c2f4d61703b787001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000174000774696d656f7574740001357800]
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1212)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport$4.execute(JobStoreSupport.java:1149)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport$45.execute(JobStoreSupport.java:3726)
        at org.quartz.impl.jdbcjobstore.JobStoreCMT.executeInLock(JobStoreCMT.java:245)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInLock(JobStoreSupport.java:3722)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1145)
        at org.quartz.core.QuartzScheduler.scheduleJob(QuartzScheduler.java:886)
        at org.quartz.impl.StdScheduler.scheduleJob(StdScheduler.java:259)
        at org.springframework.scheduling.quartz.SchedulerAccessor.addTriggerToScheduler(SchedulerAccessor.java:371)
        at org.springframework.scheduling.quartz.SchedulerAccessor.registerJobsAndTriggers(SchedulerAccessor.java:303)
        at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:511)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1547)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1485)
        ... 12 more
    Caused by: org.postgresql.util.PSQLException: Bad value for type long : \xaced0005737200156f72672e71756172747a2e4a6f62446174614d61709fb083e8bfa9b0cb020000787200266f72672e71756172747a2e7574696c732e537472696e674b65794469727479466c61674d61708208e8c3fbc55d280200015a0013616c6c6f77735472616e7369656e74446174617872001d6f72672e71756172747a2e7574696c732e4469727479466c61674d617013e62ead28760ace0200025a000564697274794c00036d617074000f4c6a6176612f7574696c2f4d61703b787001737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c7708000000100000000174000774696d656f7574740001357800
        at org.postgresql.jdbc2.AbstractJdbc2ResultSet.toLong(AbstractJdbc2ResultSet.java:2971)
        at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getLong(AbstractJdbc2ResultSet.java:2163)
        at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getBlob(AbstractJdbc2ResultSet.java:378)
        at org.postgresql.jdbc2.AbstractJdbc2ResultSet.getBlob(AbstractJdbc2ResultSet.java:366)
        at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.getObjectFromBlob(StdJDBCDelegate.java:3145)
        at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:881)
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1194)
        ... 24 more

1 个答案:

答案 0 :(得分:7)

似乎Quartz需要知道它正在与哪种类型的数据库进行通信,以便它可以使用正确的策略来读取blob,这是我通过org.quartz.jobStore.driverDelegateClass属性设置的。

设置org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate解决了问题。

<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="schedulerName" value="example-scheduler"></property>
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transactionManager"></property>
        <property name="quartzProperties">
            <map>
                <entry key="org.quartz.scheduler.skipUpdateCheck" value="true" />
                <entry key="org.quartz.jobStore.driverDelegateClass" value="org.quartz.impl.jdbcjobstore.PostgreSQLDelegate" />
            </map>
        </property>
        <property name="triggers">
            <list>
                <ref bean="cronTrigger" />
                <ref bean="simpleTrigger" />
            </list>
        </property>
    </bean>