I'm trying out Quartz scheduler and managed to get it to work with Spring using Maven.
What I need to do is configure Quartz to store the jobs so that for a scheduled time it may execute the job. As far as I know there are two types of triggers in Quartz, Simple and Cron. And I also found out that there is something called JobStore in Quartz. I got it configured to some extent.
Could someone please give me a good reference/references on how to setup Quartz, JobStore? Big help, thank you.
You can have a look at these links
Quartz JobStore with Spring Framework
http://trimplement.com/using-spring-and-quartz-with-jobstore-properties/
If you still cant figure it out then let me know
Just to give you another option, have you try task scheduling of Spring?. Nowadays I change all my old Quartz jobs for this and is easier to configure and you can use the annotations.
http://spring.io/blog/2010/01/05/task-scheduling-simplifications-in-spring-3-0/
You will usually create a Scheduler from a factory class. Quartz can be setup in several ways.
By using the org.quartz.impl.StdSchedulerFactory.getDefaultScheduler(). This will load the quartz.properties file in the Quartz distribution if you have not provided your own.
By specifying your configuration as Key-Value pairs in a quartz.properties file and loading it in org.quartz.impl.StdSchedulerFactory(java.lang.String fileName).getScheduler().
By specifying your configuration in a java.util.Properties as Key-Value pairs and loading it in org.quartz.impl.StdSchedulerFactory(java.util.Properties props).getScheduler().
By using the spring-context-support jar from the Spring Framework and using a higher level abstraction such as org.springframework.scheduling.quartz.SchedulerFactoryBean.
etc.
Quartz will start triggering jobs only when the org.quartz.Scheduler#start() has been invoked. Until this method is called the Scheduler will be in Standby mode.
The Scheduler can be destroyed to release threads by calling org.quartz.Scheduler#shutdown().
Example of Bootstrapping Quartz with Spring
#org.springframework.context.annotation.Configuration
public class QuartzExample {
...
#org.springframework.context.annotation.Bean
public org.springframework.scheduling.quartz.SchedulerFactoryBean schedulerFactory() {
org.springframework.scheduling.quartz.SchedulerFactoryBean factoryBean = new org.springframework.scheduling.quartz.SchedulerFactoryBean();
return factoryBean;
}
}
The bean definition above is enough to perform the following configuration:-
JobFactory - The default is Spring’s org.springframework.scheduling.quartz.AdaptableJobFactory, which supports java.lang.Runnable objects as well as standard Quartz org.quartz.Job instances.
ThreadPool - Default is a Quartz org.quartz.simpl.SimpleThreadPool with a pool size of 10. This is configured through the corresponding Quartz properties.
SchedulerFactory - The default used here is the org.quartz.impl.StdSchedulerFactory, reading in the standard quartz.properties from quartz.jar.
JobStore - The default used is org.quartz.simpl.RAMJobStore which does not support persistence and is not clustered.
Life-Cycle - The org.springframework.scheduling.quartz.SchedulerFactoryBean implements org.springframework.context.SmartLifecycle and org.springframework.beans.factory.DisposableBean which means the life-cycle of the scheduler is managed by the Spring container. The org.quartz.Scheduler#start() is called in the start() implementation of SmartLifecycle after initialization and the org.quartz.Scheduler#shutdown() is called in the destroy() implementation of DisposableBean at application teardown.
You can override the startup behaviour by setting org.springframework.scheduling.quartz.SchedulerFactoryBean().setAutoStartup(false). With this setting you have to manually start the scheduler.
All these default settings can be overridden by the calling the various setter methods on org.springframework.scheduling.quartz.SchedulerFactoryBean.
I have provided a full working example on Github. If you are interested in an example that saves the jobs in a database checkout the HSQLDB branch of the same repository.
Related
We are using Quartz Scheduler in our Spring Boot Application.
There is a scenario for which we want to disable it.
We have tried using #ConditionalOnProperty(name = Constant.QUARTZ_ENABLED) option on our class.
We have defined quartz.enabled = false property in application.properties file.
However when we run on Tomcat server locally on Spring Tool Suite it is working as expected (meaning it is not invoking the quartz scheduler).
But when same code is deployed on Weblogic, the scheduler is still running.
Should we try putting #ConditionalOnProperty(name = Constant.QUARTZ_ENABLED) annotation at method level. specifically the method where trigger is used?
We have gone through the options mentioned on various forums but still not reached the solution.
Is there any way we can
1. Stop the scheduler from starting
Or
2. Stop the Job from getting triggered
Thanks in advance.
Annotated spring beans in my spring-cloud application are being created twice. I assume this is because they get constructed into the bootstrap context and then into a child application context.
For me this is undesirable because some are annotated with #Scheduled to perform periodic refreshes of the data that they provide from a backend data source and this is happening twice in quick succession once for each context.
If it's not otherwise harmful then can I disable all of the application beans from being created in the bootstrap context? If not then can I detect in code when I'm running in the bootstrap context? I use entirely annotation-based beans with component scanning enabled on the Camden SR4 release.
OK I solved this myself. It was down to two different issues in the code and nothing to do with multiple contexts.
Firstly my long held assumption that an #PostConstruct method is only ever called once was false. Moving my one-off bean initialisation code to an implementation of ApplicationListener<ApplicationReadyEvent> solved that one.
Secondly I got bit by multiple initialisation of a bean with an #Scheduled annotation causes the scheduler to run multiple times. To be fair, this behaviour is noted in the documentation. This was easily solved by moving the scheduled task creation to a regular java ScheduledExecutorService set up in the ApplicationReadyEvent implementation.
Here is scenario,
I am working on one web application,where I am using java, spring, oracle. My requirement is schedule some job where user should specify execution time by some UI and job should be persistent once schedule even if server restarted or application redeployed.
From last few days I am going through lots of stackoverflow post regarding quartz persistence scheduler, but here is tricky part I can not execute any update or insert statement from my java code, I am only allowed to do all db stuff in plsql procedure and call that procedure from java code.
So, the problem is I can't go for quartz persistence implementation directly.It will very great full if anyone tell me right approach to deal with it.
in short how I can implement my own table structure and plsql procedure to make job persistence,which I can load once on application/server start and also allow user to update trigger time and other parameters.
Thanks
What you are looking is for the Quartz JdbcJobStore which stores the jobs and track their execution. Please read the following:
For configuring the JdbcJobStore read this (TX) or this (CMT)
For configuring the data sources read this
#Gan, If you want, you can customize quartz persistance by overriding JobStoreCMT class of Quartz and using that as your job store class in quartz.properties as value for property org.quartz.jobStore.class.
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = <package>.CustomJobStoreCMT
In my application I have 2 beans which have methods annotated with #Scheduled annotation. Sometimes I need to schedule both the methods, and sometimes I need to schedule either one of them, based on the input arguments to the application. How can I disable the #Scheduled method after it has been loaded? I am using Spring 3.1 .
i would suggest instead of using #Schedule you should use TaskScheduler to schedule your job based on user input, this way you will have more control over execution, different implementation is provided by spring refer to javadoc and scheduling doc
You can inject ThreadPoolTaskScheduler into your application and call
taskScheduler.getScheduledExecutor().shutdown();
But remember, this is a hack. So I suggest using TaskScheduler directly without #Scheduled annotations.
I have a Spring Web application with an applicationContext.xml loaded through a ContextLoaderListener in an XmlWebApplicationContext. The application context has a Quartz scheduler (defined with a SchedulerFactoryBean like here) but has no trigger nor job details.
During loading of this main application context, I load some "plug-in" JARs containing their own pluginApplicationContext.xml file.
Each pluginApplicationContext.xml is loaded in a GenericXmlApplicationContext as a child of the main XmlWebApplicationContext.
Those plug-ins may contain Quartz jobs (QuartzJobBean) which are scheduled within the scheduler discussed above. Scheduling have to be done programmatically through the Quartz API but this is fine for me. When the job is triggered, it is well instanciated by Quartz and, because it extends the QuartzJobBean, I'm able to get the current ApplicationContext through setApplicationContext.
The problem here is that I get the XmlWebApplicationContext instead of the GenericXmlApplicationContext from which the job have been scheduled. Thus, I cannot call getBean to retrieve the beans defined within the plugin.
I well understand why all of this happen. But I cannot find a clean and reusable solution to handle it. I've already had a look at OSGi but we're implementing this plug-in system on an existing application, not creating a new one from scratch and migrating the whole application to OSGi would be too much work to do. Do you know how OSGi and other plug-in frameworks deal with this kind of situation?
Thanks a lot for your help
I am not sure I get all those spring problems but I've done these things with OSGi.
What people often do not realize is that you can embed OSGi in your existing application without making any changes to the existing code. Richard Hall describes it here http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html (the API is 100% standardized).
Having a framework, you can then run your plugins in the framework. You will have to make sure the framework exports all the application packages (see the org.osgi.framework.system.packages.extra launch property). Plugins and application can then communicate through services.
I've never used Quartz but I've some experience with scheduling. I register a Runnable service with cron like properties:
#Component(properties="cron=1 * * * *")
public void SomeImpl implements Runnable {
public void run() {
...
}
}
You will then need to make a bundle that calls that service according to its cron specification).
I agree osgi is a good approach, but maybe you can simply crate one huge application context (to rule them all)? Instead of manually starting new child application context based on pluginApplicationContext.xml file simply add:
<import resource="classpath:/pluginApplicationContext.xml"/>
And this will find all plugins and merge their beans into a single application context. From architecture point of view this is a worse approach, but it will work if you discover all plugins at startup time.