Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quartz & Spring - Clustered but NOT Persistent?

In my Spring application I'm using the SchedulerFactoryBean to integrate with Quartz. We're going to have clustered Tomcat instances, and thus I want to have a clustered Quartz environment, so that the same jobs don't run at the same time on different web servers.

To do this, my app-context.xml is as follows:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="cronTrigger"/>
            <ref bean="simpleTrigger" />
        </list>
    </property>
    <property name="dataSource" ref="dataSource"/>
    <property name="overwriteExistingJobs" value="true"/>
    <!-- found in applicationContext-data.xml -->
    <property name="applicationContextSchedulerContextKey" value="applicationContext"/>
    <property name="quartzProperties">
        <props>
            <prop key="org.quartz.scheduler.instanceName">SomeBatchScheduler</prop>
            <prop key="org.quartz.scheduler.instanceId">AUTO</prop>
            <prop key="org.quartz.jobStore.misfireThreshold">60000</prop>
            <!--<prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop>-->
            <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
            <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
            <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
            <prop key="org.quartz.jobStore.isClustered">true</prop>
            <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
            <prop key="org.quartz.threadPool.threadCount">25</prop>
            <prop key="org.quartz.threadPool.threadPriority">5</prop>
        </props>
    </property>
</bean>

Everything works well, except that when I attempt to remove or change a trigger, then restart my app, the old triggers are still persisted in the DB, and still run. I don't want this, I just want them to be deleted when the app stops (or is restarted). I set the value of the overwriteExistingJobs property to be true, since I thought that's what it did.

Any ideas? All I want to use the DB for is clustering, not any sort of persistence beyond that.

like image 799
Jason Fotinatos Avatar asked Jul 21 '10 15:07

Jason Fotinatos


People also ask

What is quartz used for?

Since antiquity, varieties of quartz have been the most commonly used minerals in the making of jewelry and hardstone carvings, especially in Eurasia. Quartz is the mineral defining the value of 7 on the Mohs scale of hardness, a qualitative scratch method for determining the hardness of a material to abrasion.

Is quartz a rock or stone?

Quartz is a major component of many types of rock. Quartz is abundant in certain igneous rocks. It forms the clear to grey or even white lumpy blobs in granite and comprise most of silicate-rich or felsic igneous rocks. It is absent or rare in more primitive basic or silica-poor igneous rocks such as basalt.

What is special about quartz?

The answer is quite simple… durability and abundance. Quartz is the fourth strongest material on earth after diamond, sapphire, and topaz. When combined with high-quality resins and formed into surfacing slabs, it lasts a lifetime, is completely hygienic, and is resistant to impact, scratching and scorching.

Is quartz more expensive?

In general, quartz is the more expensive material, although some overlap in pricing exists. This guide will help you get a better idea of cost and other factors you should consider before purchasing granite or quartz for your home.


2 Answers

I have done research on the topic and that's a well-known bug in Quartz, I found a few posts on their forum. To solve this problem I created a bean that deletes all the records in the Quartz table. You can call this bean before your Quartz bean is loaded (add a "depends-on" on your Scheduler bean), when your spring context is being destroyed (make sure the DB connection pool is still opened), or manually through some form of UI. There's also a bug on job groups, don't be surprised. My first fix was to create a customer Quartz jar with the fix but it got pretty hard to upgrade whenever they released a new version (I was using 1.4 or 1.5 at the time - don't really remember).

like image 119
Felipe Oliveira Avatar answered Sep 26 '22 15:09

Felipe Oliveira


I ran into a similar problem with clustered quartz 2. I wasn't running camel, but it's the same problem.

1) There's no way I've seen to delete the jobs in a clustered environment by simply removing the jobs/triggers from the spring context xml.

2) Because the database stores the job/trigger information, rolling deployments across servers become problematic if you're adding or modifying jobs. Servers can start running jobs before the job implementation can be deployed to the app server, unless you take down all servers prior to deploying your changes.

To solve this, I came up with a pretty simple solution. As part of our build process, we were already capturing and storing a unique build version + number w/in the build artifact (using gradle variable substitution). To solve this problem, we simply made the scheduler's name include the unique build version+number. This results in the latest set of jobs+triggers being added to the db under the new scheduler's name, and once the rolling deploy is done, all servers are running w/ the new name. This solves the delete problem and also solves the rolling deployment problem. If all of the extra scheduler names becomes an issue in the db, something could be written to clean them up if needed.

like image 32
angrycrab Avatar answered Sep 26 '22 15:09

angrycrab