<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>timer &#8211; Pauls Blog</title>
	<atom:link href="https://sterl.org/tag/timer/feed/" rel="self" type="application/rss+xml" />
	<link>https://sterl.org</link>
	<description></description>
	<lastBuildDate>Mon, 09 Jun 2025 13:08:19 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
	<item>
		<title>Quartz integration in Spring</title>
		<link>https://sterl.org/2022/07/quartz-integration-in-spring/</link>
					<comments>https://sterl.org/2022/07/quartz-integration-in-spring/#comments</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Fri, 01 Jul 2022 19:50:50 +0000</pubDate>
				<category><![CDATA[Quartz]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[quartz-scheduler]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[timer]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=802</guid>

					<description><![CDATA[Why Quartz? motivation Spring comes already with an own timer and this is fine if we have very simple requirements and we don&#8217;t really care about state or on which pod the timer is actually running. To be more precise the timer/ job is running in each of our spring containers independently. Lets be honest,&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Why Quartz? <span class="badge badge-pill badge-primary">motivation</span></h2>



<p>Spring comes already with an own <a rel="noreferrer noopener" href="https://spring.io/guides/gs/scheduling-tasks/" target="_blank">timer</a> and this is fine if we have very simple requirements and we don&#8217;t really care about state or on which pod the timer is actually running. To be more precise the timer/ job is running in each of our spring containers independently.</p>



<p>Lets be honest, this is usually never really the case and so it is common to invite <a rel="noreferrer noopener" href="https://github.com/lukas-krecan/ShedLock" target="_blank">ShedLock</a> to the party. Are we done then?</p>



<p>Usually no, honestly we want in the most cases just a bit more:</p>



<ul class="wp-block-list">
<li>Run jobs in the cluster on different nodes simultaneous</li>



<li>Have a kind of state management </li>



<li>The ability to provide some kind of configuration to each run</li>



<li>Have some kind of way for easy retries etc.</li>
</ul>



<p>Hey why don&#8217;t use Spring Batch then? </p>



<p>Because to have just a timer and not really a batch-job it is somehow the wrong tool. Furthermore Spring-Batch is build with a different goal in mind, where we start a container with one job inside to process mass of data. Quartz is more a timer, which we want to use to trigger either smaller task in our application or run kind of repeating small task and are more concerned to orchestrate and Monitor them.</p>



<ul class="wp-block-list">
<li>Spring Batch = Batch Framework to handle large datasets which should be processed, usually in an own container / pod for the duration of the Job</li>



<li>Quartz = Timer which also supports a JDBC/ REDIS store for smaller timer jobs which should run in our app cluster</li>
</ul>



<h2 class="wp-block-heading">Steps for the integration</h2>



<ul class="wp-block-list">
<li>Setup the DB</li>



<li>Configure <a rel="noreferrer noopener" aria-label="Quartz Scheduler (öffnet in neuem Tab)" href="http://www.quartz-scheduler.org" target="_blank">Quartz Scheduler</a></li>



<li>Configure CDI Job Factory</li>



<li>Register our timers</li>



<li>Set a thread priority for our job</li>
</ul>



<p>Setup the DB</p>



<p>Overall quartz comes with <a rel="noreferrer noopener" href="https://github.com/quartz-scheduler/quartz/tree/master/quartz-core/src/main/resources/org/quartz/impl/jdbcjobstore" target="_blank">SQL scripts and liquibase scripts</a> you may just include. <a href="https://sterl.org/2019/09/quartz-scheduler-integration-in-java-jee/#ipt_kb_toc_378_16">Read here</a>. For unit test we can just simply use the build in feature:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;yaml&quot;,&quot;mime&quot;:&quot;text/x-yaml&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;YAML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;yaml&quot;}">spring:
  quartz:
    jdbc:
      initialize-schema: always</pre></div>



<h3 class="wp-block-heading">Configure Quartz Scheduler</h3>



<p>We will use the CMT Store here, for more details because of the why <a href="https://sterl.org/2019/09/quartz-scheduler-integration-in-java-jee/#ipt_kb_toc_378_3">please read the following tutorial</a>.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;xml&quot;,&quot;mime&quot;:&quot;application/xml&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;XML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;xml&quot;}">		&lt;dependency&gt;
			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
			&lt;artifactId&gt;spring-boot-starter-quartz&lt;/artifactId&gt;
		&lt;/dependency&gt;
</pre></div>



<p>After adding the dependency we have to configure Quartz, in this example we set the thread count to 2, adjust this value based on your needs. The following configuration will usually create a <code>LocalDataSourceJobStore</code> which is an <code>JobStoreCMT</code>.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;yaml&quot;,&quot;mime&quot;:&quot;text/x-yaml&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;YAML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;yaml&quot;}">spring:
  quartz:
    wait-for-jobs-to-complete-on-shutdown: false
    job-store-type: jdbc
    overwrite-existing-jobs: true
    jdbc:
      initialize-schema: always
    properties:
      org.quartz.jobStore.isClustered: true
      org.quartz.scheduler.instanceId: AUTO
      org.quartz.scheduler.skipUpdateCheck: true
      org.quartz.threadPool.threadCount: 2
  
  datasource:
    url: jdbc:h2:file:./quartz-db
    username: sa
    password: 
</pre></div>



<div class="bs-callout bs-callout-info"><strong>Note:</strong>
We init the DB just with quartz itself. But quartz contains in the core a liquibase and a SQL file which you may include into your DB update process.
</div>



<p>Yes thats basically it, we will discuss details in further deep dives, but for now lets gets a job running.</p>



<h3 class="wp-block-heading">Create a timer Job</h3>



<p>To setup a timer we have to:</p>



<ol class="wp-block-list">
<li><span style="color: initial; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Oxygen-Sans, Ubuntu, Cantarell, &quot;Helvetica Neue&quot;, sans-serif;">Add a job class</span></li>



<li>Configure the timer</li>
</ol>



<h4 class="wp-block-heading">Add a Spring configuration</h4>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">// runs only one of these jobs in out cluster
// note we have no spring annotation here, but it contains spring beans
@DisallowConcurrentExecution 
public class QuatzTimerJob implements Job {
	// we can use spring beans, yes we cam
    @Autowired YourService yourService;
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
		yourService.doSomething();
    }

}</pre></div>



<h4 class="wp-block-heading">Configure the timer</h4>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Configuration
public class QuartzTimerConfiguration {
	// this registers our job itself
    @Bean
    public JobDetailFactoryBean quatzTimerJob() {
        final var jobDetailFactory = new JobDetailFactoryBean();
        jobDetailFactory.setJobClass(QuatzTimerJob.class);
        jobDetailFactory.setDescription(&quot;Simple timer like @Scheduled - but already like with ShedLock&quot;);
        jobDetailFactory.setDurability(true);
        return jobDetailFactory;
    }
    // here we add the timer, in this case every 30s, with a lower priority as normal for the job
    @Bean
    public SimpleTriggerFactoryBean trigger(JobDetail quatzTimerJob) {
        final var trigger = new SimpleTriggerFactoryBean();
        trigger.setJobDetail(quatzTimerJob);
        trigger.setRepeatInterval(30_000);
        trigger.setPriority(Thread.NORM_PRIORITY - 1);
        trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
        return trigger;
    }
}</pre></div>



<h3 class="wp-block-heading">Trigger a job</h3>



<p>In difference to a normal Spring timer we may now fire triggers for Quartz Jobs, even add data to the triggers itself, at let Quartz handle the heavy work for us. Handy if we want QUEUE some work, or just distribute the load in our cluster to all available nodes. For this we have to:</p>



<ol class="wp-block-list">
<li>Create a job instance we want to execute</li>



<li>Configure the job &#8211; but now without any default trigger</li>



<li>Create somewhere in our code the triggers, usually with some payload data</li>
</ol>



<h4 class="wp-block-heading">Create a job</h4>



<p>Very simple thing here, just getting one value from the job context and calling out service.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">public class TriggeredJob implements Job {

    @Autowired YourService yourService;
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        long count = context.getMergedJobDataMap().getLong(&quot;count&quot;));
        yourService.doSomething(count);
    }

}</pre></div>



<h4 class="wp-block-heading">Configure the job</h4>



<p>The only special thing here is that we request a recovery on a different node, should this node for some reason die during the execution of the job.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Configuration
public class QuartzJobConfiguration {
    @Bean
    public JobDetailFactoryBean createStoreItemsJob() {
        final var jobDetailFactory = new JobDetailFactoryBean();
        jobDetailFactory.setJobClass(CreateStoreItemsJob.class);
        jobDetailFactory.setDescription(&quot;Job we directly trigger if we want to run it&quot;);
        jobDetailFactory.setDurability(true);
        jobDetailFactory.setRequestsRecovery(true);
        return jobDetailFactory;
    }
}</pre></div>



<h4 class="wp-block-heading">Trigger the job</h4>



<div class="bs-callout bs-callout-info"><strong>Note:</strong>
The usage of <code>@Transactional</code>, this is by purpose, to ensure the trigger gets removed if we happen to rollback the transaction. If it is missing, quartz will silently create an own one.
</div>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">    @Autowired Scheduler scheduler;
    @Autowired JobDetail createStoreItemsJob;

    @Transactional
    public void triggerStoreItemCreation() throws SchedulerException {
        Trigger t = TriggerBuilder.newTrigger()
            .forJob(createStoreItemsJob)
            .startNow() // run on this node if possible, means we have threads
            .usingJobData(&quot;count&quot;, count)
            .build();
        
        scheduler.scheduleJob(t);
    }</pre></div>



<h2 class="wp-block-heading">Testing it</h2>



<p>You may wonder why we used a file DB in this configuration. Only with a DB which contains the trigger data after a restart you may play around and also kill the running Spring application. After a restart the jobs are triggered again.</p>



<h2 class="wp-block-heading">Alternatives</h2>



<p>We could also go for a command queue using e.g. JMS. This aproach would require  additional infrastructure in form of a persistent broker. Which could be easy in the cloud but rather difficult if you have to operate and maintain it on your own. In the end a data store which have to join our DB transactions in case ACID is an issue and it always is.</p>



<h2 class="wp-block-heading">Links</h2>



<ul class="wp-block-list">
<li><a href="https://github.com/sterlp/training/tree/master/spring-quartz">https://github.com/sterlp/training/tree/master/spring-quartz</a></li>



<li><a href="https://spring.getdocs.org/en-US/spring-boot-docs/boot-features/boot-features-quartz.html">https://spring.getdocs.org/en-US/spring-boot-docs/boot-features/boot-features-quartz.html</a></li>



<li><a href="http://www.quartz-scheduler.org/documentation/quartz-2.3.0/cookbook/">http://www.quartz-scheduler.org/documentation/quartz-2.3.0/cookbook/</a></li>
</ul>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2022/07/quartz-integration-in-spring/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Disable @Scheduled timers for test in Spring</title>
		<link>https://sterl.org/2022/05/disable-scheduled-timers-for-test-in-spring/</link>
					<comments>https://sterl.org/2022/05/disable-scheduled-timers-for-test-in-spring/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Mon, 02 May 2022 09:18:37 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[@Scheduled]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[timer]]></category>
		<category><![CDATA[Unit Test]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=770</guid>

					<description><![CDATA[Problem As soon we have timers in our project they may cause issues in our integration tests, as they start running in the most undesirable situation. E.g. during the trigger a specific function which would usually be triggered by the timer. Solution 1 If we want to disable the timers even the construction of the&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>As soon we have timers in our project they may cause issues in our integration tests, as they start running in the most undesirable situation. E.g. during the trigger a specific function which would usually be triggered by the timer.</p>



<h2 class="wp-block-heading">Solution 1</h2>



<p>If we want to disable the timers even the construction of the beans we have to tell spring not event to lead the beans. To achieve that we require first some configuration. As we might have more than one timer it is easier to work with an own meta annotaton</p>



<h3 class="wp-block-heading">Own Meta annotation</h3>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Java&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@ConditionalOnProperty(name = &quot;my-project.timers-enabled&quot;, 
                       havingValue = &quot;true&quot;, 
                       matchIfMissing = true)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
public @interface TimersEnabled {

}</pre></div>



<h3 class="wp-block-heading">Use the annotation</h3>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;Java&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@TimersEnabled
@Component
@RequiredArgsConstructor
public class MyTimer {
    
    private final MyService service;

    @Scheduled(fixedDelay = 30, timeUnit = TimeUnit.SECONDS)
    void scheduledMethod() {
        service.doStuff();
    }
}</pre></div>



<h3 class="wp-block-heading">Disable the timers</h3>



<p>e.g. in the <code>application.yml</code> of your test resources:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;yaml&quot;,&quot;mime&quot;:&quot;text/x-yaml&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;YAML&quot;,&quot;language&quot;:&quot;YAML&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;yaml&quot;}">my-project:
  timers-enabled: false</pre></div>



<p>The timers will be disabled for any value other then <code>true</code>. </p>



<h2 class="wp-block-heading">Solution 2</h2>



<p>In the easiest scenario if it is a in memory Spring test we can just mock the <code>ScheduledExecutorService</code> and so stop any <code>@Scheduled</code> job executions.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">    @MockBean
    private ScheduledExecutorService schedulerService;</pre></div>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2022/05/disable-scheduled-timers-for-test-in-spring/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Quartz integration in JEE</title>
		<link>https://sterl.org/2019/09/quartz-scheduler-integration-in-java-jee/</link>
					<comments>https://sterl.org/2019/09/quartz-scheduler-integration-in-java-jee/#comments</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Sat, 21 Sep 2019 12:24:10 +0000</pubDate>
				<category><![CDATA[Quartz]]></category>
		<category><![CDATA[CDI]]></category>
		<category><![CDATA[container]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[EJB]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[Job]]></category>
		<category><![CDATA[payara]]></category>
		<category><![CDATA[quartz-scheduler]]></category>
		<category><![CDATA[scheduler]]></category>
		<category><![CDATA[timer]]></category>
		<category><![CDATA[Wildfly]]></category>
		<guid isPermaLink="false">http://sterl.org/?p=378</guid>

					<description><![CDATA[Nowadays everybody talks about cloud and Microservices. The JEE container isn't that sexy anymore. With microprofile.io the JEE world started to move into the direction of a more lightweight structure. We should also mention docker and friends which changed the way we deploy and run applications now. ]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Why Quartz? <span class="badge badge-pill badge-primary">motivation</span></h2>



<p>Nowadays everybody talks about cloud and Microservices. The JEE container isn&#8217;t that sexy anymore. With <a rel="noreferrer noopener" aria-label="microprofile.io (öffnet in neuem Tab)" href="https://microprofile.io" target="_blank">microprofile.io</a> the JEE world started to move into the direction of a more lightweight structure. We should also mention docker and friends which changed the way we deploy and run applications now. </p>



<p>Long story short we have to keep in mind that the JEE timer depends on the admin server. Clustered timer just won&#8217;t really work anymore. Not to mention that the normal timers in JEE are pretty limited in their feature set. Even simple <em>job triggers</em> aren&#8217;t possible out of the box.</p>



<p><a href="https://github.com/sterlp/jee-quartz-integration">Bring me to the code.</a></p>



<h2 class="wp-block-heading">Steps for the integration</h2>



<ol class="wp-block-list"><li>Configure <a rel="noreferrer noopener" aria-label="Quartz Scheduler (öffnet in neuem Tab)" href="http://www.quartz-scheduler.org" target="_blank">Quartz Scheduler</a></li><li>Configure CDI Job Factory</li><li>Register our timers</li></ol>



<div class="bs-callout bs-callout-info">
<strong>Note:</strong> If you are already using Deltaspike you might want to use directly the <a href="https://deltaspike.apache.org/documentation/scheduler.html">scheduler integration</a> provided by it.
</div>



<h2 class="wp-block-heading">Configure Quartz Scheduler</h2>



<h3 class="wp-block-heading">Select the right job store</h3>



<p>In general, we have several ways of integration, going through the documentation we will see, that we have to choose between:</p>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" aria-label="JobStoreCMT (öffnet in neuem Tab)" href="http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html#configuration-of-jdbc-jobstorecmt-jdbc-with-jta-container-managed-transactions" target="_blank">JobStoreCMT</a></li><li><a href="http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html#configuration-of-terracottajobstore-clustering-without-a-database" target="_blank" rel="noreferrer noopener" aria-label="TerracottaJobStore (öffnet in neuem Tab)">TerracottaJobStore</a></li></ul>



<p>We will focus for now on a job store using a normal database. We cannot really choose the <a rel="noreferrer noopener" aria-label="JobStoreTX  (öffnet in neuem Tab)" href="http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html#configuration-of-jdbc-jobstoretx-store-jobs-and-triggers-in-a-database-via-jdbc" target="_blank">JobStoreTX </a>as it wouldn&#8217;t join our transaction creating new triggers etc. Means if we accept during a REST call a command on our server, for which we also want to create a quartz trigger which does later on the heavy lifting, we would lose the ability to rollback the trigger and the modification of our data in one logical step. We might end up reverting all changes on the data, but still creating the trigger which e.g. won&#8217;t find the entities we created or modified for it.</p>



<p>For unit testing the <a rel="noreferrer noopener" aria-label="RamJobStore  (öffnet in neuem Tab)" href="http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html#configuration-of-ramjobstore-store-jobs-and-triggers-in-memory" target="_blank">RamJobStore </a>is sufficient. Luckily the default, if we don&#8217;t specify anything we will get it anyway.</p>



<h3 class="wp-block-heading">Configure JobStoreCMT</h3>



<p>The  CMT job store requires two DB connection pools. One will join our application transaction, means we can just simply provide the application data source.</p>



<p>The second connection pool has to be standalone, which means it shouldn&#8217;t join the transaction of the first pool. We can now either create a pool and disable the connection:</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="760" height="159" src="http://sterl.org/wp-content/uploads/2019/09/non-transactional-connection-payara.png" alt="" class="wp-image-484" srcset="https://sterl.org/wp-content/uploads/2019/09/non-transactional-connection-payara.png 760w, https://sterl.org/wp-content/uploads/2019/09/non-transactional-connection-payara-300x63.png 300w" sizes="(max-width: 760px) 100vw, 760px" /><figcaption>JDBC Connection Pool non-transactional</figcaption></figure>



<p>or create a non-container managed pool. Which wouldn&#8217;t be that nice but possible.</p>



<h4 class="wp-block-heading">ConnectionProvider</h4>



<p>Nevertheless, we have to bridge the JEE world to the Quartz world using a small class implementing the <code>ConnectionProvider</code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: java; title: ; notranslate">
@AllArgsConstructor
public class SimpleConnectionProvider implements ConnectionProvider {
    @NonNull
    private final DataSource dataSource;
    @Override
    public Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    @Override
    public void shutdown() {
    }
    @Override
    public void initialize() {
    }
}
</pre></div>


<h4 class="wp-block-heading">ThreadPool</h4>



<p>Quartz comes with its own code to manage threads. Like with the database connection we have also to tell quartz to use the managed executor service here. Furthermore, quartz allows to limit the threads.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">public class SimpleQuartzJeeThreadPool implements ThreadPool {
    private static final Logger LOG = LoggerFactory.getLogger(SimpleQuartzJeeThreadPool.class);

    private final ManagedExecutorService executorService;
    private final List&lt;WeakReference&lt;Future&lt;?&gt;&gt;&gt; tasks = Collections.synchronizedList(new ArrayList&lt;&gt;());
    /** the max pool size, could also be the max size of the custom executor services created */
    private final int poolSize;
    private boolean shutdown = false;

    public SimpleQuartzJeeThreadPool(ManagedExecutorService executorService, int poolSize) {
        this.executorService = executorService;
        this.poolSize = poolSize;
        Objects.requireNonNull(this.executorService, &quot;ManagedExecutorService cannot be null.&quot;);
    }
 
    @Override
    public boolean runInThread(Runnable runnable) {
        if (shutdown) return false;
        try {
            tasks.add(new WeakReference&lt;&gt;(executorService.submit(runnable)));
            return true;
        } catch (RejectedExecutionException e) {
            LOG.info(&quot;runInThread was rejected, the pool capacitiy is exceeded! {}&quot;, e.getMessage());
            return false;
        }
    }

    @Override
    public int blockForAvailableThreads() {
        if (shutdown) return -1;
        try {
            // check if we have a thread available again and block for quartz // and purge
            this.executorService.submit(this::purge).get();

            return poolSize - tasks.size();
        } catch (Exception e) {
            LOG.warn(&quot;blockForAvailableThreads failed to pruge queue!&quot;, e);
            return poolSize - tasks.size();
        }
    }
  
    /**
     * Removes all monitored jobs and returns the removed count.
     * @return the removed jobn count
     */
    public int purge() {
        int removed = 0;
        if (!tasks.isEmpty()) {   
            List&lt;WeakReference&lt;Future&lt;?&gt;&gt;&gt; doneJobs = tasks.stream().filter(e -&gt; e.isEnqueued() || e.get() == null || e.get().isDone())
                    .collect(Collectors.toList());

            removed = doneJobs.size();
            this.tasks.removeAll(doneJobs);
            doneJobs.clear();
        }
        return removed;
    }

    @Override
    public void initialize() {
    }
    @Override
    public void shutdown(boolean waitForJobsToComplete) {
        this.shutdown = true;
    }
    @Override
    public int getPoolSize() {
        return poolSize;
    }
    @Override
    public void setInstanceId(String schedInstId) {
    }
    @Override
    public void setInstanceName(String schedName) {
    }
}</pre></div>



<div class="bs-callout bs-callout-info"><strong>Note:</strong>
The executor created for quartz shouldn&#8217;t have any queue capacity, as quartz manages the queue.
</div>



<h4 class="wp-block-heading">Put it together</h4>



<p>Which leads us to the following configuration</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@Startup
@Singleton
public class TimerConfiguration {
    // this data source should be non transactional in the container
    private static final String QUARTZ_DS = &quot;jdbc/quartz-datasource&quot;;
    @Resource(lookup = QUARTZ_DS)
    private DataSource quartzDataSource;
    // the default application datasource
    private static final String APP_DS = &quot;jdbc/app-datasource&quot;;
    @Resource(lookup = APP_DS)
    private DataSource appDataSource;
    
    @Inject InjectionJobFactory jobFactory;
	// executor service for our jobs to quartz
    @Resource(name = &quot;concurrent/quartz-executor&quot;)
    private ManagedExecutorService executorService;

    private Scheduler scheduler;
    
    @PostConstruct
    public void start() {
        try {
            // Get scheduler and start it
            final DirectSchedulerFactory schedulerFactory = DirectSchedulerFactory.getInstance();
			// provide the datasources            
            DBConnectionManager.getInstance()
                    .addConnectionProvider(APP_DS, new SimpleConnectionProvider(appDataSource));
            DBConnectionManager.getInstance()
                    .addConnectionProvider(QUARTZ_DS, new SimpleConnectionProvider(quartzDataSource));
            
            JobStoreCMT jobStore = new JobStoreCMT();
            jobStore.setInstanceName(&quot;quartz-job-example-store&quot;);
            jobStore.setDataSource(APP_DS);
            jobStore.setNonManagedTXDataSource(QUARTZ_DS);
            // use the JEE executor service
            jobStore.setThreadExecutor(new ThreadExecutor() {
                @Override
                public void execute(Thread thread) {
                    executorService.execute(thread);
                }
                @Override
                public void initialize() {
                }
            });
            jobStore.setIsClustered(true);
            jobStore.setDriverDelegateClass(&quot;org.quartz.impl.jdbcjobstore.PostgreSQLDelegate&quot;);
            // note: the id matters as it defines if the times is seens as an own node ...
            schedulerFactory.createScheduler(&quot;JEE-QUARTZ&quot;, &quot;JEE-QUARTZ-ID&quot;, new SimpleQuartzJeeThreadPool(executorService, 20), jobStore);
            
            scheduler = schedulerFactory.getScheduler(&quot;JEE-QUARTZ&quot;);

            // Use the CDI managed job factory
            scheduler.setJobFactory(jobFactory);

            // Start scheduler
            scheduler.start();

        } catch (Exception e) {
            throw new RuntimeException(&quot;Failed to configure and start quartz.&quot;, e);
        }
    }</pre></div>



<div class="bs-callout bs-callout-info"><strong>Note:</strong>
The scheduler provides a way to set the ID of a quartz timer. If the ID is the same between two nodes they will not balance the load between each other. Make sure each node has an own ID.
</div>



<h2 class="wp-block-heading">Configure CDI Job Factory</h2>



<p>The default behavior of  Quartz would be to create a new instance of the class we register as a job. In most cases, this is not what we want. Usually, we want to use our CDI beans or JEE EJBs, for the spring guys the spring beans. As so we have to tell Quartz somehow how to find our beans.</p>



<h3 class="wp-block-heading">Injection JobFactory</h3>



<p>The easiest and most clean way is to provide an adapter to our CDI world. We just inject all classes which implement the Job interface, using it to find the right one based on the job detail we define during the job registration.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">@ApplicationScoped
public class InjectionJobFactory implements JobFactory {    
    @Inject @Any
    private Instance&lt;Job&gt; jobs;
    
    @Override
    public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
        final Class&lt;? extends Job&gt; clazz = bundle.getJobDetail().getJobClass();
        final Instance&lt;? extends Job&gt; bean = jobs.select(clazz);
        if (bean.isUnsatisfied()) throw new SchedulerException(&quot;No job bean of type &quot; + clazz + &quot; found.&quot;);
        return bean.get();
    }
}</pre></div>



<div class="bs-callout bs-callout-info"><strong>Note:</strong>
Of course we could use additional vaules to do fruther filtering e.g. based on annotations.
</div>



<h2 class="wp-block-heading">Register our timers</h2>



<p>Quartz provides us the Job interface our timer have to implement. As soon this is done we can register a timer:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">// Create a QuarzJob to run
JobDetail jeeJob = JobBuilder.newJob(CdiTimer.class)
        .withIdentity(CdiTimer.class.getSimpleName())
        .build();

// Create a Trigger to trigger the job every five minutes 
Trigger trigger = TriggerBuilder.newTrigger()
                 // run every 10 seconds
                 .withSchedule(CronScheduleBuilder.cronSchedule(&quot;0/10 * * * * ?&quot;))
                 .forJob(jeeJob)			
                 .build();

// Register Job and Trigger with the scheduler
scheduler.scheduleJob(jeeJob, trigger);</pre></div>



<h3 class="wp-block-heading">CDI Timer</h3>



<p>Using CDI beans as timers is just straight forward, add the interface, ensure they are annotated as application scoped, done.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">import org.quartz.Job;
import javax.enterprise.context.ApplicationScoped;
// our simple CDI timer bean
@ApplicationScoped // timer don't have a scope or web request ...
public class CdiTimer implements Job {

    @Override
    public void execute(JobExecutionContext context) {
        // the CDI timer code
    }   
}</pre></div>



<h3 class="wp-block-heading">EJBs as timer beans</h3>



<p>EJBs are a bit different. As soon as we add the interface you might encounter the problem that <code>@Inject</code> doesn&#8217;t work. Well long story short just tell JEE that it just a <a rel="noreferrer noopener" aria-label="local bean (öffnet in neuem Tab)" href="https://docs.oracle.com/javaee/7/api/javax/ejb/LocalBean.html" target="_blank">local bean</a> with <code>@LocalBean</code> and all will be good:</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import org.quartz.Job;
// tells JEE to not mess around because we use an interface, this is not a remote EJB!
@LocalBean 
@Stateless
public class EjbTimer implements Job {

    @Override
    public void execute(JobExecutionContext context) {
        // the EJB timer code
    }
}</pre></div>



<h2 class="wp-block-heading">Links</h2>



<ul class="wp-block-list"><li><a href="http://www.quartz-scheduler.org/">Quartz</a></li><li><a href="https://deltaspike.apache.org/documentation/scheduler.html">Deltaspike Quartz</a></li><li><a rel="noreferrer noopener" aria-label="Spring Quartz datasource integratrion (öffnet in neuem Tab)" href="https://github.com/spring-projects/spring-framework/blob/master/spring-context-support/src/main/java/org/springframework/scheduling/quartz/LocalDataSourceJobStore.java" target="_blank">Spring Quartz datasource integration</a></li><li><a href="https://spring.io/projects/spring-cloud-task">Spring Cloud Task</a></li></ul>



<h2 class="wp-block-heading">Sidenotes</h2>



<p>Not enough? Well here some other side notes.</p>



<h3 class="wp-block-heading">Manage dependant Scope Beans</h3>



<p>Just for completeness but not as a recommendation, it is possible to use also not annotated CDI beans as Timer beans. Of course, we have to handle than its lifecycle and destroy them after they have beans used. In the <a rel="noreferrer noopener" aria-label="JBoss Documentation (öffnet in neuem Tab)" href="https://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#_enhanced_version_of_javax_enterprise_inject_instance" target="_blank">JBoss Documentation</a>, we are pointed to a <code>WeldInstance</code> class, which allows us to check the scope and later also to destroy the bean.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">// important is the usage of the WeldInstance instead of Instance
@Inject @Any
WeldInstance Job jobs;

// which would allow us to add the destroy code after the timer was used
// problem of course is to find the correct point in Quartz to postion this part
if (Dependent.class.equals(handler.getBean().getScope()) {
    // Destroy only dependent CDI beans
    handler.destroy();
}</pre></div>



<h3 class="wp-block-heading">Creating the Quartz tables</h3>



<p>Quartz provides two ways to set up the tables out of the box:</p>



<ol class="wp-block-list"><li>SQL to be used e.g. with <a rel="noreferrer noopener" aria-label="flyway (öffnet in neuem Tab)" href="https://flywaydb.org/" target="_blank">flyway</a></li><li>XML to be used with <a href="https://www.liquibase.org/" target="_blank" rel="noreferrer noopener" aria-label="liquibase (öffnet in neuem Tab)">liquibase</a></li></ol>



<p>The second one has the charm that it works also in tests out of the box, as liquibase supports multiple DBs.</p>



<p>As so we can copy the <a rel="noreferrer noopener" aria-label="liquibase.quartz.init.xml (öffnet in neuem Tab)" href="https://github.com/quartz-scheduler/quartz/blob/master/quartz-core/src/main/resources/org/quartz/impl/jdbcjobstore/liquibase.quartz.init.xml" target="_blank">liquibase.quartz.init.xml</a> into our <code>src/main/resources</code> and execute the following code before the initialization of quartz.</p>



<div class="wp-block-codemirror-blocks-code-block code-block"><pre class="CodeMirror" data-setting="{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Java&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;java&quot;}">try (Connection c = dataSource.getConnection()) {
    Liquibase l = new Liquibase(
            &quot;/liquibase.quartz.init.xml&quot;, 
            new ClassLoaderResourceAccessor(getClass().getClassLoader()),
            DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(c)));
    l.update(&quot;QUARTZ-SCHEMA&quot;);
} catch (Exception e) {
    throw new RuntimeException(&quot;Failed to init quartz schema.&quot;, e);
}</pre></div>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2019/09/quartz-scheduler-integration-in-java-jee/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
	</channel>
</rss>
