Spring Quartz 远程调度程序
Spring Quartz remote scheduler
我使用 spring 启动了石英服务器实例(如 article),效果很好。
但是当我尝试使用 quartz 客户端启动另一个应用程序并连接到 quartz 服务器时,出现错误,请帮助我做错了什么。
服务器配置:
@Configuration
public class ServerConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean(ApplicationContext applicationContext) {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
schedulerFactory.setSchedulerListeners(...);
schedulerFactory.setJobFactory(...);
schedulerFactory.setTriggers(...);
return schedulerFactory;
}
...
}
客户端配置:
@Configuration
public class ClientConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
return schedulerFactory;
}
...
}
服务器quartz.properties:
org.quartz.scheduler.instanceName=myScheduler
org.quartz.scheduler.rmi.export=true
org.quartz.scheduler.rmi.createRegistry=true
org.quartz.scheduler.rmi.registryHost=localhost
org.quartz.scheduler.rmi.registryPort=1099
org.quartz.scheduler.rmi.serverPort=1100
客户quartz.properties:
org.quartz.scheduler.instanceName=myScheduler
org.quartz.scheduler.rmi.proxy=true
org.quartz.scheduler.rmi.registryHost=localhost
org.quartz.scheduler.rmi.registryPort=1099
服务器日志:
[2019-09-03] [10:07:26.171] INFO SchedulerFactoryBean:538 - Loading Quartz config from [class path resource [quartz.properties]]
[2019-09-03] [10:07:26.229] INFO StdSchedulerFactory:1208 - Using default implementation for ThreadExecutor
[2019-09-03] [10:07:26.272] INFO SchedulerSignalerImpl:61 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[2019-09-03] [10:07:26.273] INFO QuartzScheduler:229 - Quartz Scheduler v.2.3.0 created.
[2019-09-03] [10:07:26.277] INFO RAMJobStore:155 - RAMJobStore initialized.
[2019-09-03] [10:07:26.338] INFO QuartzScheduler:421 - Scheduler bound to RMI registry under name 'schedulerFactoryBean_$_NON_CLUSTERED'
[2019-09-03] [10:07:26.343] INFO QuartzScheduler:294 - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - access via RMI.
...
[2019-09-03] [10:07:26.344] INFO StdSchedulerFactory:1362 - Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance.
[2019-09-03] [10:07:26.345] INFO StdSchedulerFactory:1366 - Quartz scheduler version: 2.3.0
...
[2019-09-03] [10:07:29.12] INFO SchedulerFactoryBean:684 - Starting Quartz Scheduler now
[2019-09-03] [10:07:29.13] INFO QuartzScheduler:547 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED started.
客户端日志:
[2019-09-03] [10:11:53.255] INFO SchedulerFactoryBean:538 - Loading Quartz config from [class path resource [quartz.properties]]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactoryBean' defined in class path resource [com/mypackage/ClientConfig.class]: Invocation of init method failed; nested exception is org.quartz.SchedulerException: Operation not supported for remote schedulers.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:742)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:73)
... 3 more
Caused by: org.quartz.SchedulerException: Operation not supported for remote schedulers.
at org.quartz.impl.RemoteScheduler.getListenerManager(RemoteScheduler.java:913)
at org.springframework.scheduling.quartz.SchedulerAccessor.registerListeners(SchedulerAccessor.java:340)
at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:476)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627)
... 13 more
如您所见,错误是:
org.quartz.SchedulerException: Operation not supported for remote schedulers.
并在 bean 初始化时发生。怎么了?
客户端启动失败后,服务器在日志中显示:
[2019-09-03] [10:11:53.462] INFO QuartzScheduler:666 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED shutting down.
[2019-09-03] [10:11:53.462] INFO QuartzScheduler:585 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED paused.
[2019-09-03] [10:11:53.871] INFO QuartzScheduler:447 - Scheduler un-bound from name 'schedulerFactoryBean_$_NON_CLUSTERED' in RMI registry
[2019-09-03] [10:11:53.872] INFO QuartzScheduler:740 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED shutdown complete.
我有 Spring - 4.3.20,Quartz - 2.3.0
更新:
我看到 registerListeners()
调用 SchedulerFactoryBean
:
@Override
public void afterPropertiesSet() throws Exception {
...
try {
registerListeners();
registerJobsAndTriggers();
}
catch (Exception ex) {
try {
this.scheduler.shutdown(true);
}
catch (Exception ex2) {
logger.debug("Scheduler shutdown exception after registration failure", ex2);
}
throw ex;
}
}
在 registerListeners()
中我们调用 getScheduler().getListenerManager()
失败并出现 Operation not supported for remote schedulers
异常。如何避免为 RemoteScheduler 调用 registerListeners()
?
最后我按照以下方式让它工作:
我拒绝在客户端上使用 Spring 的 SchedulerFactoryBean
,而是直接从 quartz 库中创建 StdSchedulerFactory
的实例(然后它正确创建 RemoteScheduler
) 的实例:new StdSchedulerFactory()
。它正确连接到服务器石英实例。
由于我无法从 SchedulerFactoryBean
获得 StdSchedulerFactory
的实例,所以我只是将两者都传递给需要的 bean。所以在客户端应用程序上 SchedulerFactoryBean
为空,在服务器应用程序上 StdSchedulerFactory
为空。
两家工厂的工作计划部分是相同的,因为我对他们所做的只是获取计划程序:
private Scheduler getScheduler() throws SchedulerException {
if (schedulerFactoryBean != null) return schedulerFactoryBean.getScheduler();
if (schedulerFactory != null) return schedulerFactory.getScheduler();
else return null;
}
然后...
Scheduler scheduler = getScheduler();
if (scheduler != null) {
scheduler.scheduleJob(job, trigger);
}
我使用 spring 启动了石英服务器实例(如 article),效果很好。 但是当我尝试使用 quartz 客户端启动另一个应用程序并连接到 quartz 服务器时,出现错误,请帮助我做错了什么。
服务器配置:
@Configuration
public class ServerConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean(ApplicationContext applicationContext) {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
schedulerFactory.setSchedulerListeners(...);
schedulerFactory.setJobFactory(...);
schedulerFactory.setTriggers(...);
return schedulerFactory;
}
...
}
客户端配置:
@Configuration
public class ClientConfig {
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean();
schedulerFactory.setConfigLocation(new ClassPathResource("quartz.properties"));
return schedulerFactory;
}
...
}
服务器quartz.properties:
org.quartz.scheduler.instanceName=myScheduler
org.quartz.scheduler.rmi.export=true
org.quartz.scheduler.rmi.createRegistry=true
org.quartz.scheduler.rmi.registryHost=localhost
org.quartz.scheduler.rmi.registryPort=1099
org.quartz.scheduler.rmi.serverPort=1100
客户quartz.properties:
org.quartz.scheduler.instanceName=myScheduler
org.quartz.scheduler.rmi.proxy=true
org.quartz.scheduler.rmi.registryHost=localhost
org.quartz.scheduler.rmi.registryPort=1099
服务器日志:
[2019-09-03] [10:07:26.171] INFO SchedulerFactoryBean:538 - Loading Quartz config from [class path resource [quartz.properties]]
[2019-09-03] [10:07:26.229] INFO StdSchedulerFactory:1208 - Using default implementation for ThreadExecutor
[2019-09-03] [10:07:26.272] INFO SchedulerSignalerImpl:61 - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
[2019-09-03] [10:07:26.273] INFO QuartzScheduler:229 - Quartz Scheduler v.2.3.0 created.
[2019-09-03] [10:07:26.277] INFO RAMJobStore:155 - RAMJobStore initialized.
[2019-09-03] [10:07:26.338] INFO QuartzScheduler:421 - Scheduler bound to RMI registry under name 'schedulerFactoryBean_$_NON_CLUSTERED'
[2019-09-03] [10:07:26.343] INFO QuartzScheduler:294 - Scheduler meta-data: Quartz Scheduler (v2.3.0) 'schedulerFactoryBean' with instanceId 'NON_CLUSTERED'
Scheduler class: 'org.quartz.core.QuartzScheduler' - access via RMI.
...
[2019-09-03] [10:07:26.344] INFO StdSchedulerFactory:1362 - Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance.
[2019-09-03] [10:07:26.345] INFO StdSchedulerFactory:1366 - Quartz scheduler version: 2.3.0
...
[2019-09-03] [10:07:29.12] INFO SchedulerFactoryBean:684 - Starting Quartz Scheduler now
[2019-09-03] [10:07:29.13] INFO QuartzScheduler:547 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED started.
客户端日志:
[2019-09-03] [10:11:53.255] INFO SchedulerFactoryBean:538 - Loading Quartz config from [class path resource [quartz.properties]]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactoryBean' defined in class path resource [com/mypackage/ClientConfig.class]: Invocation of init method failed; nested exception is org.quartz.SchedulerException: Operation not supported for remote schedulers.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1631)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:481)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:312)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:742)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:73)
... 3 more
Caused by: org.quartz.SchedulerException: Operation not supported for remote schedulers.
at org.quartz.impl.RemoteScheduler.getListenerManager(RemoteScheduler.java:913)
at org.springframework.scheduling.quartz.SchedulerAccessor.registerListeners(SchedulerAccessor.java:340)
at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:476)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627)
... 13 more
如您所见,错误是:
org.quartz.SchedulerException: Operation not supported for remote schedulers.
并在 bean 初始化时发生。怎么了?
客户端启动失败后,服务器在日志中显示:
[2019-09-03] [10:11:53.462] INFO QuartzScheduler:666 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED shutting down.
[2019-09-03] [10:11:53.462] INFO QuartzScheduler:585 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED paused.
[2019-09-03] [10:11:53.871] INFO QuartzScheduler:447 - Scheduler un-bound from name 'schedulerFactoryBean_$_NON_CLUSTERED' in RMI registry
[2019-09-03] [10:11:53.872] INFO QuartzScheduler:740 - Scheduler schedulerFactoryBean_$_NON_CLUSTERED shutdown complete.
我有 Spring - 4.3.20,Quartz - 2.3.0
更新:
我看到 registerListeners()
调用 SchedulerFactoryBean
:
@Override
public void afterPropertiesSet() throws Exception {
...
try {
registerListeners();
registerJobsAndTriggers();
}
catch (Exception ex) {
try {
this.scheduler.shutdown(true);
}
catch (Exception ex2) {
logger.debug("Scheduler shutdown exception after registration failure", ex2);
}
throw ex;
}
}
在 registerListeners()
中我们调用 getScheduler().getListenerManager()
失败并出现 Operation not supported for remote schedulers
异常。如何避免为 RemoteScheduler 调用 registerListeners()
?
最后我按照以下方式让它工作:
我拒绝在客户端上使用 Spring 的
SchedulerFactoryBean
,而是直接从 quartz 库中创建StdSchedulerFactory
的实例(然后它正确创建RemoteScheduler
) 的实例:new StdSchedulerFactory()
。它正确连接到服务器石英实例。由于我无法从
SchedulerFactoryBean
获得StdSchedulerFactory
的实例,所以我只是将两者都传递给需要的 bean。所以在客户端应用程序上SchedulerFactoryBean
为空,在服务器应用程序上StdSchedulerFactory
为空。两家工厂的工作计划部分是相同的,因为我对他们所做的只是获取计划程序:
private Scheduler getScheduler() throws SchedulerException {
if (schedulerFactoryBean != null) return schedulerFactoryBean.getScheduler();
if (schedulerFactory != null) return schedulerFactory.getScheduler();
else return null;
}
然后...
Scheduler scheduler = getScheduler();
if (scheduler != null) {
scheduler.scheduleJob(job, trigger);
}