My codebase currently uses a crontab-like quartz.properties file to define a series of jobs in our Spring web app. Our quartz config currently looks like:
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.jmx.export=true
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=20
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.misfireThreshold=6000000
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.dataSource=dataSourceConnectionProvider
I've recently become enamored of Spring's #scheduled annotation and would really like to take advantage of it. There are plenty of instances where we have some job bean that essentially wraps a single method of a service -- the annotations seem like they'd remove a lot of boilerplate and more our code more legible as a result.
However, I can't figure out how I could get the same guarantees from Spring's scheduling that we do from vanilla quartz right now. That is, setting isClustered=true and the job store implementation to use a backing database enables us to guarantee that our jobs run once per cluster without doing something unpleasant like declaring a master node and checking hostnames -- which isn't even a good guarantee for us, since we have a variable number of nodes. Nonetheless, it seems like it should be possible -- Spring's scheduling is obviously very aware of Quartz, and I have to imagine that there's a way to implement a TaskScheduler that would provide these guarantees.
Related
What are pros and cons of implementing a custom scope vs using a dedicated child container for an independent job execution?
I'm implementing a complex business functionality that needs a couple of dedicated beans. So far I managed fine to create objects with custom factories or object providers in prototype scope per execution and keep others stateless as singleton beans, but as complexity rises, I want to get a better container support for my job executions.
I did a project some time ago, where I implemented a custom scope. We used a thread scope that's inherited by child threads, so we only needed to ensure that the job was executed in it's own thread graph.
My last project used spring batch for batch job execution. In the spring batch docs I read the recommendation to use a child container per job, once thing's are starting to get complex. Additionally, it provides JobScope and StepScope.
I would be really interested in performance statistics and complexity experience?
I am trying to use Quartz with Quarkus.
In the guide: https://quarkus.io/guides/quartz
They create an application scoped TaskBean, that creates a job instance, that when executed
does nothing but persisting an empty Task entity.
This IMHO doesn't look very clean and doesn't help much either a far as I understand it.
I am rather trying to follow a more default setup of Quartz - so I have create a "classical" Job that is supposed to do the work - and I added this to the scheduler. All working fine. Now I just need to inject a service into this job, something similar to:
http://vijaykiran.com/2013/01/a-quick-way-to-integrate-seam3-cdi-and-quartz-jobs/
Has anyone here possibly done this for Quarkus before?
At this point, Quarkus does not support injection into Quartz Jobs - based on my request a patch is on the way. In the meantime, you can directly retrieve an instance from Arc like this: Arc.container().instance(YourClass.class).get();
I'm trying to determine all the things I need to consider when deploying jobs to a clustered environment.
I'm not concerned about parallel processing or other scaling things at the moment; I'm more interested in how I make everything act as if it was running on a single server.
So for I've determined that triggering a job should be done via messaging.
The thing that's throwing me for a loop right now is how to utilize something like the Spring Batch Admin UI (even if it's a hand rolled solution) in a clustered deployment. Getting the job information from a JobExplorer seems like one of the keys.
Is Will Schipp's spring-batch-cluster project the answer, or is there a more agreed upon community answer?
Or do I not even need to worry because the JobRepository will be pulling from a shared database?
Or do I need to publish job execution info to a message queue to update the separate Job Repositories?
Are there other things I should be concerned about, like the jobIncrementers?
BTW, if it wasn't clear that I'm a total noob to Spring batch, let it now be known :-)
Spring XD (http://projects.spring.io/spring-xd/) provides a distributed runtime for deploying clusters of containers for batch jobs. It manages the job repository as well as provides way to deploy, start, restart, etc the jobs on the cluster. It addresses fault tolerance (if a node goes down, the job is redeployed for example) as well as many other necessary features that are needed to maintain a clustered Spring Batch environment.
I'm adding the answer that I think we're going to roll with unless someone comments on why it's dumb.
If Spring Batch is configured to use a shared database for all the DAOs that the JobExplorer will use, then running is a cluster isn't much of a concern.
We plan on using Quarts jobs to create JobRequest messages which will be put on a queue. The first server to get to the message will actually kick off the Spring Batch job.
Monitoring running jobs will not be an issue because the JobExplorer gets all of it's information from the database and it doesn't look like it's caching information, so we won't run into cluster issues there either.
So to directly answer the questions...
Is Will Schipp's spring-batch-cluster project the answer, or is there a more agreed upon community answer?
There is some cool stuff in there, but it seems like over-kill when just getting started. I'm not sure if there is "community" agreed upon answer.
Or do I not even need to worry because the JobRepository will be pulling from a shared database?
This seems correct. If using a shared database, all of the nodes in the cluster can read and write all the job information. You just need a way to ensure a timer job isn't getting triggered more than once. Quartz already has a cluster solution.
Or do I need to publish job execution info to a message queue to update the separate Job Repositories?
Again, this shouldn't be needed because the execution info is written to the database.
Are there other things I should be concerned about, like the jobIncrementers?
It doesn't seem like this is a concern. When using the JDBC DAO implementations, it uses a database sequence to increment values.
Examples of using Quartz within Seam 2 are shown with both JobStoreTX, JobStoreCMT and RAMJobStore.
Our project needs to persist jobs so we can do clustering, but I can't get JobStoreCMT to execute jobs. What is the difference between JobStoreCMT and JobStoreTX specifically for Seam?
Is it OK to use JobStoreTX in preference, just because it seams easier, or have I missed something crucial?
From the documentation for JobStoreCMT:
JobStoreCMT is meant to be used in an application-server environment that provides container-managed-transactions. No commit / rollback will be1 handled by this class.
If you need commit / rollback, use JobStoreTX instead.
and JobStoreTX:
JobStoreTX is meant to be used in a standalone environment. Both commit and rollback will be handled by this class.
If you need a JobStore class to use within an application-server environment, use JobStoreCMT instead.
So the answer to the question of which to use boils down to whether or not you want creation of triggers/etc to be a part of a larger transaction within your application, or if it should be standalone.
I want to be able to :
define different jobs and triggers.
modify the expirations dates and intervals on demand
pause or cancel an execution (trigger)
the jobs would be ejbs or call ejbs and i would want to manage everything from the website (the user will have to define the executions)
So i looked at the timerservice, timerobjects, timer and timerhandle. But i think it can't answer to all my needs
Quartz, on the other hand, allows me to do every thing that i want, but i haven't the slightest clue on how to integrate this into my jboss.
I read that quartz uses its own threadpool, and i don't know how to handle all this.
I use Jboss Seam in my project, but the seam/quartz integration is very limited (or the documentation is) and not 100% safe (seen on their forum : 'run forever' tasks end after only a few weeks)
If someone managed to integrate a good scheduler into his application server (jboss is a plus) and could give me directions, advices, or even code snippets, i would be thrilled.
Thanks in advance.
I have some experience integrating Quartz into a Weblogic (no jboss experience, sorry) application server. Quartz has a built in listener class that will be called upon server startup (per J2EE specs) that automatically configure the Quartz scheduler. Then in another startup class you can retrieve that scheduler, add jobs and begin serving those jobs.
You generally don't need to worry about the threadpool, Quartz can handle all this itself if you want it too. It gets its information from a properties files on startup that you can define or use the default one that comes with quartz. I have been using the default because it works for my purposes.
As far as defining jobs, you create your job classes and call your ejbs from there. It is rather very simple.
For your reading pleasure:
All Quartz documentation
Quartz JavaDoc
Cookbook containing lots of code snippets
Hope that's enough to get you started!
Great news! JBoss has a built-in scheduler already.
Since the EJB 2.0 specification included running stateless session beans and MDBs at scheduled intervals, all application servers have included this capability for some time now.
Here is an example of configuring JBoss to run a class using its built-in scheduler:
http://www.jboss.org/community/wiki/Scheduler
The best part about JBoss' implementation is that it is based on the MBean specification, which means that you can create/update/delete scheduled tasks at runtime.
Ok, i am sorry, i found in the sources of Jboss Seam just what i needed :
QuartzDispatcher to create QuartzTriggerHandle wich fires seam event at specified time and date and is manually pausable, resumable and stoppable. I use an #observer on the method i wanted to execute.
It's simple, and it works so far.
As pointed out by Poindexter, the Quartz documentation has nice starting points: Tutorial for Developing with Quartz, Examples of Usage, Cook Book (Quick How-Tos in the form of code examples), etc.
The What Is Quartz article is really good too (even if a bit old now).
For integration with JBoss, maybe have a look at How to configure a Quartz service on JBoss Wiki.