Reputation: 65
this is my quartz config:
@Bean
public SchedulerFactoryBean startQuartz(DataSource dataSource, PlatformTransactionManager annotationDrivenTransactionManager,
CronTriggerFactoryBean remoteProjectTrigger, ApplicationContext applicationContext) throws IOException {
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setDataSource(dataSource);
schedulerFactoryBean.setTransactionManager(annotationDrivenTransactionManager);
schedulerFactoryBean.setOverwriteExistingJobs(false);
schedulerFactoryBean.setQuartzProperties(quartzProperties());
schedulerFactoryBean.setTriggers(remoteProjectTrigger.getObject());
schedulerFactoryBean.setApplicationContext(applicationContext);
return schedulerFactoryBean;
}
@Bean(name = "detailFactoryBean")
public MethodInvokingJobDetailFactoryBean detailFactoryBean(){
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean ();
bean.setTargetBeanName("quartzRemoteProject");
bean.setTargetMethod ("run");
bean.setConcurrent (false);
return bean;
}
@Bean
public CronTriggerFactoryBean remoteProjectTrigger(MethodInvokingJobDetailFactoryBean detailFactoryBean){
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean ();
trigger.setJobDetail (detailFactoryBean.getObject ());
trigger.setCronExpression ("0/5 * * ? * *");
return trigger;
}
@Bean("quartzRemoteProject")
public QuartzRemoteProject quartzRemoteProject(){
return new QuartzRemoteProject();
}
public Properties quartzProperties() throws IOException {
Properties prop = new Properties();
prop.put("quartz.scheduler.instanceName", "ServerScheduler");
prop.put("org.quartz.scheduler.instanceId", "AUTO");
prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
prop.put("org.quartz.scheduler.instanceId", "CLUSTERED");
prop.put("org.quartz.scheduler.jobFactory.class", "org.quartz.simpl.SimpleJobFactory");
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
prop.put("org.quartz.jobStore.isClustered", "true");
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
prop.put("org.quartz.threadPool.threadCount", "5");
return prop;
}
this config will got an exception
org.quartz.SchedulerException: Job threw an unhandled exception.
at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-2.2.3.jar:na]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [quartz-2.2.3.jar:na]
Caused by: java.lang.NullPointerException: null
at org.springframework.scheduling.quartz.JobMethodInvocationFailedException.<init>(JobMethodInvocationFailedException.java:40) ~[spring-context-support-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:271) ~[spring-context-support-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75) ~[spring-context-support-4.3.6.RELEASE.jar:4.3.6.RELEASE]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.2.3.jar:na]
... 1 common frames omitted
i find the problem is in MethodInvokingJobDetailFactoryBean.class's inner class MethodInvokingJob
context.setResult(this.methodInvoker.invoke());
the methodInvoker
is null;
when remove the
schedulerFactoryBean.setDataSource(dataSource);
schedulerFactoryBean.setTransactionManager(annotationDrivenTransactionManager);
schedulerFactoryBean.setQuartzProperties(quartzProperties());
this config will work. any one can hlep:)
Upvotes: 0
Views: 1155
Reputation: 65
it's because class MethodInvokingJobDetailFactoryBean cannot be serialized to database,
spring-context-support
did not provide the serialized version,It is suppose throw an SerializationException
instead of NullPointerException
,i don't figure out this.
but only solve this this problem,I find two ways.
1、overwrite MethodInvokingJobDetailFactoryBean
serializable version,you can find a sample in
https://jira.spring.io/browse/SPR-3797
,but for the latest quartz version(2.2.3),you may do some update work.then change the config MethodInvokingJobDetailFactoryBean to BeanInvokingJobDetailFactoryBean like follow
@Bean(name = "jobDetailFactoryBean")
public BeanInvokingJobDetailFactoryBean detailFactoryBean(){
BeanInvokingJobDetailFactoryBean bean = new BeanInvokingJobDetailFactoryBean ();
bean.setTargetBean("quartzRemoteProject");
bean.setTargetMethod ("run");
bean.setDurable(true);
bean.setShouldRecover(true);
bean.setConcurrent (false);
return bean;
}
2、write yourself QuartzJobBean
, like this
@Log4j
@NoArgsConstructor
public class MyDetailQuartzJobBean extends QuartzJobBean {
private String targetObject;
private String targetMethod;
private ApplicationContext ctx;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
Object bean = ctx.getBean(targetObject);
Method m = bean.getClass().getMethod(targetMethod);
m.invoke(bean, null);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.ctx = applicationContext;
}
public void setTargetObject(String targetObject) {
this.targetObject = targetObject;
}
public void setTargetMethod(String targetMethod) {
this.targetMethod = targetMethod;
}
}
I use lombok
annotation.
then use this class replace the MethodInvokingJobDetailFactoryBean
,config like this
@Bean
public JobDetailFactoryBean jobDetailFactoryBean(){
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setJobClass(MyDetailQuartzJobBean.class);
Map map=new HashMap<>();
map.put("targetObject","quartzRemoteProject");
map.put("targetMethod","run");
jobDetailFactoryBean.setJobDataAsMap(map);
jobDetailFactoryBean.setDurability(true);
return jobDeta
}
ps:the second solution you must add quartz-jobs
otherwise cannot find JobDetailFactoryBean
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>
Upvotes: 0