Spring Framework Connecting JVM with each other - java

I have 4 servers and JVM is installed on them. I wrote a java service that Quartz calls this services every 10 minutes. But in 4 servers, every 10 minutes 4 calls are done. This sitiuation creates race condition. I want only one service on 4 JVM.
How can I do that with Spring Framework?

This is actually pretty easy to set up with Quartz. Spring itself cannot help you much here since it is unaware of the other JVMs that are running. Quartz on the other hand has the concept of a clustered scheduler.
Basically you need to set up a single database that all the 4 JVMs can share. This will be used as a scheduler for all 4 instances. When a job is scheduled, it is run by only one of the instances using the clustered scheduler.
Taken from the Quartz website wiki for clustering (
http://www.opensymphony.com/quartz/wikidocs/ConfigJDBCJobStoreClustering.html), this is an example configuration on how to set up the clustered scheduler. You can also set these properties directly from spring if you are configuring your scheduler that way.
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = myDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.driver = oracle.jdbc.driver.OracleDriver
org.quartz.dataSource.myDS.URL = jdbc:oracle:thin:#polarbear:1521:dev
org.quartz.dataSource.myDS.user = quartz
org.quartz.dataSource.myDS.password = quartz
org.quartz.dataSource.myDS.maxConnections = 5
org.quartz.dataSource.myDS.validationQuery=select 0 from dual

Your question isn't very clear, so let me see if I'm understanding you: you have 4 servers, each running Quartz inside a VM, and each server has the same quartz job scheduled to run every 10 minutes, using a cron expression. Every 10 minutes, all 4 servers kick off the same job, creating your race condition as they all try to do the same thing at the same time.
This isn't really a job for Spring. However, Quartz does have clustering ability, where you configure a job to run only a single server in the cluster. It uses a shared database to coordinate which servers run which job, and makes sure they don't all do it together.
The docs have some info on this here, but in the usual opensymphony.com style they're pretty sparse and unhelpful.

What I do in our web application is for each job to be wrapped in a class that takes out a global lock across your cluster (I use memcached, as I don't really care if the task gets run too often), and only runs the task if it got the lock. It can then release the lock when the task completes (don't forget to do this in a finally).
One advantage of wrapping each job rather than changing the scheduler is that you can have some jobs that run on all the machines, and some that only run on one.

Related

Quartz scheduler executes multiple times concurrently on a scheduled time

I have used quartz scheduler in my spring boot application . I am using java programmatic scheduling not a spring based annotated one. Here's the snippet
Scheduler scheduler =
StdSchedulerFactory.getDefaultScheduler();
JobDetail jobDetail = newJob(ExPJob.class) .build();
CronScheduleBuilder cronSchedule =
cronSchedule (mycronExpression)
.withMisfireHandlingInstructionDoNothing();
I am shutting down this as bellow
#PreDestroy
Public void shutdownSch(){
Scheduler scheduler =
StdSchedulerFactory.getDefaultScheduler();
scheduler.shutdown();
}
Whats my problem ?
-- if I do a re/deployment for my app.war, In Weblogic thread pool does not get killed, and after scheduler starts,
It creates another thread pool it seems.
For Example : if I schedule a cron Job at 4 PM lot of jobs are firing at the same time. I have tried to find the PID in Linux box I'm not getting any regd this zombie threads.
What are the solutions tried ? --
I am able to kill jobs successfully via jobkeys
scheduler.deletejob(jobKey) .
So why issue still persists ?
-- I have done a series of deployments without the above mentioned job killing code before.
So, I suspect those jobs/threads are already running inside JVM. I tried a weblogic restart via console through MWare folks. But still no luck. Kindly pour your thoughts.

Quartz scheduler locks database when it fails to connect

I'm using Quartz 2.2.2 in clustering mode and Spring 4.2.
I'm facing an issue with Quartz because he locks the DB when it is not able to connect to the DB.
When I say the DB is locked, I mean the DB will locked the profile which is trying to connect with the wrong password for instance. Quartz will try to connect while he's failing, and the DB will lock the profile for safety.
I would like to know if it is possible to limit the connection attempts of Quartz when it fails ?
Quartz.properties :
#============================================================================
# Configure Main Scheduler Properties
#============================================================================
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.scheduler.instanceId = AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 1
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = quartzDS
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.quartzDS.jndiURL=java:/comp/env/jdbc/E760
Do you have any idea ? I took a look to the quartz's doc' but I did not find something to help me.
There is a similar post to this one there :
Quartz Scheduler locks the database user
But I would like to know if there is/are another way to solve it.
Thanks a lot.

Quartz + Spring : Configure jobs to run on specific time using JobStore

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.

JNDI issue with Websphere 6 UserTrasaction and Quartz Scheduler

I have my Web Application running on WebSphere 6.0 and also there are some Quartz Scheduler Tasks. If I do the lookup like that in hibernate.cfg.xml:
<property name="jta.UserTransaction">java:comp/UserTransaction</property>
It works fine with my Web Application, but any threads initiated by Quartz Timers fail to access the DB using that lookup string. But if I use
<property name="jta.UserTransaction">jta/usertransaction</property>
Then it is the opposite. I will get quartz timers working but I can't do the lookup inside my Web Application.
Is there any way to make them both work with same hibernate configuration?
EDT: here is my quartz.properties file. By the way Quartz Version is 1.5.2.
org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = one
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 4
org.quartz.jobStore.misfireThreshold = 5000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
I don't know if this is relevant to you but I recently had a similar problem. My issue was remote and local access and altering my design a bit and adding the interface names to my #Local & #Remote annotations worked for me.
I think you miss the transaction management in your quartz.properties.
Something like this:
org.quartz.scheduler.userTransactionURL=jta/usertransaction
org.quartz.scheduler.wrapJobExecutionInUserTransaction=true
The idea is to tell Quartz to wrap the job execution in a transaction and where to get it.

Quartz persistent job scheduler implementation in java using oracle read only access

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

Categories