问题:
quartz启用数据库管理模式,启动时报异常【java.io.NotSerializableException: Unable to serialize JobDataMap for insertion into database because the value of property 'jobLauncher' is not serializable: org.springframework.batch.core.launch.support.SimpleJobLauncher】
原因:
quartz使用数据库管理模式,需要将配置信息进行序列化,保存到数据库,而spring的SimpleJobLauncher是不支持序列化的,对应的配置文件为
<bean id="policyJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.my.quartz.JobLauncherDetails" />
<property name="group" value="quartz-batch" />
<property name="durability" value="true" />
<property name="requestsRecovery" value="false" />
<property name="description" value="测试job" />
<property name="jobDataAsMap">
<map>
<entry key="jobName" value="policyJob" />
<entry key="param1" value="jason" />
<entry key="param2" value="test" />
<entry key="jobLocator" value-ref="jobRegistry" />
<entry key="jobLauncher" value-ref="jobLauncher" />
</map>
</property>
</bean>
解决:
在spring的SchedulerFactoryBean类的源码里,有这样一段注释,大意是 当使用持久化的job,将jobdetail保存到数据库中,不要将spring管理的bean或是ApplicationContext的引用配置到JobDataMap中,而是通过schedulerContextAsMap参数将其配置到SchedulerContext(也就是Scheduler的上下文)
/**
* Register objects in the Scheduler context via a given Map.
* These objects will be available to any Job that runs in this Scheduler.
* <p>Note: When using persistent Jobs whose JobDetail will be kept in the
* database, do not put Spring-managed beans or an ApplicationContext
* reference into the JobDataMap but rather into the SchedulerContext.
* @param schedulerContextAsMap Map with String keys and any objects as
* values (for example Spring-managed beans)
* @see JobDetailBean#setJobDataAsMap
*/
public void setSchedulerContextAsMap(Map<String, ?> schedulerContextAsMap) {
this.schedulerContextMap = schedulerContextAsMap;
}
正确的配置形式应该是
<bean autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
<property name="schedulerContextAsMap">
<map>
<entry key="jobLocator" value-ref="jobRegistry" />
<entry key="jobLauncher" value-ref="jobLauncher" />
</map>
</property>
</bean>