<?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>Tutorials &#8211; Pauls Blog</title>
	<atom:link href="https://sterl.org/category/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>https://sterl.org</link>
	<description></description>
	<lastBuildDate>Thu, 26 Sep 2024 08:30:37 +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>Run Eclipse/STS on Windows WSL</title>
		<link>https://sterl.org/2024/09/run-eclipse-sts-on-windows-wsl/</link>
					<comments>https://sterl.org/2024/09/run-eclipse-sts-on-windows-wsl/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Thu, 26 Sep 2024 08:01:01 +0000</pubDate>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[App Defender]]></category>
		<category><![CDATA[AppLocker]]></category>
		<category><![CDATA[ASR Block]]></category>
		<category><![CDATA[ASR Block Exception]]></category>
		<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Spring STS]]></category>
		<category><![CDATA[VcXsrv]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[WSL]]></category>
		<category><![CDATA[x11]]></category>
		<category><![CDATA[Xlaunch]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=1052</guid>

					<description><![CDATA[Problem In some companies, App Defender/AppLocker makes the entire Windows OS practically unusable. EXEs are blocked, and the virus scan slows any build to a crawl. Nevertheless, we still need to work, and WSL is often the only feasible solution. But how can we start, for example, Eclipse or any other application in WSL that&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>In some companies, App Defender/AppLocker makes the entire Windows OS practically unusable. EXEs are blocked, and the virus scan slows any build to a crawl. Nevertheless, we still need to work, and WSL is often the only feasible solution. But how can we start, for example, Eclipse or any other application in WSL that requires a screen?</p>



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



<p>We might wither build on x11 (steps 4 and 5) or use the build in <strong>WSLg</strong> which should run out of the box:</p>



<ol class="wp-block-list">
<li>Install eclipse or STS in Linux</li>



<li>Export the DISPLAY env variable export <code>DISPLAY=:0</code></li>



<li>Run <strong>eclipse </strong>or any other application in Linux</li>



<li>(optional) Install x11 in Linux <code>sudo apt install x11-xserver-utils</code></li>



<li>(optional) Install <a href="https://sourceforge.net/projects/vcxsrv/">VcXsrv </a>on windows</li>
</ol>



<h2 class="wp-block-heading">Install eclipse or Spring STS in Linux</h2>



<p>We might either install eclipse with <code>sudo</code> apt install eclipse or as many other of us choose to install a different IDE here an example for spring sts (update the URL as needed to the current version):</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;shell&quot;,&quot;mime&quot;:&quot;text/x-sh&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;bash&quot;,&quot;language&quot;:&quot;Shell&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;shell&quot;}">wget https://cdn.spring.io/spring-tools/release/STS4/4.25.0.RELEASE/dist/e4.33/spring-tool-suite-4-4.25.0.RELEASE-e4.33.0-linux.gtk.x86_64.tar.gz
tar -xvf spring-tool-suite-4-4.25.0.RELEASE-e4.33.0-linux.gtk.x86_64.tar.gz
rm -rf spring-tool*
ln -s sts-4.25.0.RELEASE/SpringToolSuite4 sts</pre></div>



<h2 class="wp-block-heading">Export the DISPLAY env variable</h2>



<p>In order to find our windows screen we have to define the DISPLAY destination with the same named environment variable. The simplest way is to extend the .profile that it is automatically exported on each shell start (or .zprofile if zsh is used).</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;shell&quot;,&quot;mime&quot;:&quot;text/x-sh&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;.profile&quot;,&quot;language&quot;:&quot;Shell&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;shell&quot;}">export DISPLAY=:0</pre></div>



<h2 class="wp-block-heading">Run <strong>eclipse </strong>or any other application</h2>



<p>Now we can either start eclipse using <code>./eclipse</code> or the spring STS using <code>./sts</code>. </p>



<p>In case of any issues the x11 app might help you e.g. using xeyes:</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;shell&quot;,&quot;mime&quot;:&quot;text/x-sh&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;Shell&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;shell&quot;}">sudo apt install x11-apps
xeyes</pre></div>



<h2 class="wp-block-heading">Install x11 in Linux</h2>



<p>x11 tools on Linux are responsible to send the screen information from our Linux system to windows and on the other hand receive mouse and keyboard commands. In ubuntu the tools can be installed by using:</p>



<p><code>sudo apt install x11-xserver-utils</code></p>



<p>This step is not need anymore on a newer WSL as by default windows support UI apps in the WSL using WSLg.</p>



<p>If x11 is used the DISPLAY variable has to be adjusted to point to the Windows Host machine.</p>



<h2 class="wp-block-heading">Install <a href="https://sourceforge.net/projects/vcxsrv/">VcXsrv </a>on windows</h2>



<p>In order to receive the screen information from Linux in Windows and to display the application started in Linux we need an x11 client here too. First we have to install <a href="https://sourceforge.net/projects/vcxsrv/">VcXsrv</a> and start it using <strong>XLaunch</strong> which will prompt us of the settings:</p>



<ol class="wp-block-list">
<li><strong>Multiple windows</strong> in the display settings, which allows us to start more than one app</li>



<li><strong>Start no client which</strong> of course requires us to start the app in Linux manually later on</li>
</ol>



<p>Everything else may stay in the default settings.</p>



<p>This step is not need anymore on a newer WSL as by default windows support UI apps in the WSL using WSLg.</p>



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



<ul class="wp-block-list">
<li><a href="https://github.com/microsoft/wslg">https://github.com/microsoft/wslg</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2024/09/run-eclipse-sts-on-windows-wsl/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Transaktionsmanagement mit Spring, JPA, Hibernate</title>
		<link>https://sterl.org/2024/08/transaktionsmanagement-mit-spring-jpa-hibernate/</link>
					<comments>https://sterl.org/2024/08/transaktionsmanagement-mit-spring-jpa-hibernate/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Sat, 31 Aug 2024 15:02:17 +0000</pubDate>
				<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[YouTube]]></category>
		<category><![CDATA[@Transactional]]></category>
		<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[DB]]></category>
		<category><![CDATA[Grundlagen]]></category>
		<category><![CDATA[Grundlagen Datenbanken]]></category>
		<category><![CDATA[Grundlagen Transaktionen]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Mandatory]]></category>
		<category><![CDATA[Read only transaction]]></category>
		<category><![CDATA[Required]]></category>
		<category><![CDATA[Spring Data]]></category>
		<category><![CDATA[Spring TransactionTemplate]]></category>
		<category><![CDATA[Transaction Timeout]]></category>
		<category><![CDATA[Transactions]]></category>
		<category><![CDATA[TransactionTemplate]]></category>
		<category><![CDATA[Transkationen]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=1032</guid>

					<description><![CDATA[Lerne die Grundlagen des Transaktionsmanagements in modernen Datenbanken kennen, und erfahre, wie du mit Spring Boot, Spring Data, JPA und Hibernate effektiv arbeitest. In diesem Tutorial starten wir mit den Grundlagen der Datenbanktransaktionen in deiner Anwendung: &#8211; Transaktionen starten: Dieses Video ist perfekt für Entwickler, die ihre Fähigkeiten in Spring Framework erweitern und transaktionssichere Anwendungen&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Lerne die Grundlagen des Transaktionsmanagements in modernen Datenbanken kennen, und erfahre, wie du mit Spring Boot, Spring Data, JPA und Hibernate effektiv arbeitest.</p>



<p>In diesem Tutorial starten wir mit den Grundlagen der Datenbanktransaktionen in deiner Anwendung: &#8211; Transaktionen starten: </p>



<ul class="wp-block-list">
<li><strong>Transaktion starten</strong>: Verstehe, wie Du Transaktionen in Spring Boot richtig initialisierst.</li>



<li><strong>Rollback-Strategien:</strong> Erlerne die wichtigsten Methoden, um Transaktionen bei Fehlern sicher zurückzusetzen. </li>



<li><strong>Annotations</strong>: Setze Annotations gezielt ein, um Transaktionen zu steuern. </li>



<li><strong>Programmatische Transaktionen</strong>: Implementiere Transaktionen programmatisch und gewinne maximale Kontrolle. </li>



<li><strong>Read Only</strong>: Transaktionen für GET Operationen </li>



<li><strong>Timeouts</strong>: Wie stelle ich bei einer Transaktion einen Timeout ein, was muss ich beachten?</li>
</ul>



<p>Dieses Video ist perfekt für Entwickler, die ihre Fähigkeiten in Spring Framework erweitern und transaktionssichere Anwendungen erstellen möchten.</p>



<ul class="wp-block-list">
<li><a href="https://github.com/sterlp/youtube/commit/24f1d4e1576be803ec32142ffb84f438dcd30623">Git Commit</a></li>



<li><a href="https://github.com/sterlp/youtube/tree/main/db-grundlagen">Git Projekt</a></li>
</ul>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Transaktionsmanagement | Datenbanken | Spring Boot &amp; Data, JPA &amp; Hibernate | @Transactional" width="640" height="360" src="https://www.youtube.com/embed/9cY73uCj5wA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2024/08/transaktionsmanagement-mit-spring-jpa-hibernate/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Microservices Event- &#124; Command- &#124; Data-Bus &#124; Event Driven</title>
		<link>https://sterl.org/2023/10/microservices-event-command-data-bus-event-driven/</link>
					<comments>https://sterl.org/2023/10/microservices-event-command-data-bus-event-driven/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Fri, 13 Oct 2023 08:02:30 +0000</pubDate>
				<category><![CDATA[Pattern & Best Practice]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[YouTube]]></category>
		<category><![CDATA[Command Bus]]></category>
		<category><![CDATA[Data Bus]]></category>
		<category><![CDATA[Event Bus]]></category>
		<category><![CDATA[Event Driven]]></category>
		<category><![CDATA[Microservices]]></category>
		<category><![CDATA[software architektur]]></category>
		<category><![CDATA[training]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=977</guid>

					<description><![CDATA[Was kann schon schief gehen? Ereignisgesteuerte (Event Driven) Architekturen dienen keinem Selbstzweck. Häufig soll sie Problemen vorbeugen und uns helfen eine stabile Service Architektur zu entwickeln. Abseits vom &#8222;Happy Case&#8220;, was kann den wie und wo schief gehen; wie kann uns diese Architektur helfen? Wir schauen uns drei typische Lösungsmethoden an:]]></description>
										<content:encoded><![CDATA[
<p>Was kann schon schief gehen?</p>



<p>Ereignisgesteuerte (Event Driven) Architekturen dienen keinem Selbstzweck. Häufig soll sie Problemen vorbeugen und uns helfen eine stabile Service Architektur zu entwickeln. Abseits vom &#8222;Happy Case&#8220;, was kann den wie und wo schief gehen; wie kann uns diese Architektur helfen?</p>



<p>Wir schauen uns drei typische Lösungsmethoden an:</p>



<ol class="wp-block-list">
<li>Event Bus </li>



<li>Command Bus</li>



<li>Data Bus</li>
</ol>



<figure class="wp-block-embed is-type-wp-embed is-provider-pauls-blog wp-block-embed-pauls-blog"><div class="wp-block-embed__wrapper">
<blockquote class="wp-embedded-content" data-secret="UXukIktPzo"><a href="https://sterl.org/2023/10/useful-links-for-event-driven-architectures/">Useful links for Event Driven Architectures</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted"  title="&#8222;Useful links for Event Driven Architectures&#8220; &#8212; Pauls Blog" src="https://sterl.org/2023/10/useful-links-for-event-driven-architectures/embed/#?secret=t04w2nAzky#?secret=UXukIktPzo" data-secret="UXukIktPzo" width="600" height="338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
</div></figure>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Microservices Event- | Command- | Data-Bus | Event Driven | Was kann schon schief gehen?" width="640" height="360" src="https://www.youtube.com/embed/fJCAhTeZv7I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2023/10/microservices-event-command-data-bus-event-driven/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Useful links for Documentation and Architecture</title>
		<link>https://sterl.org/2023/10/useful-links-for-documentation-and-architecture/</link>
					<comments>https://sterl.org/2023/10/useful-links-for-documentation-and-architecture/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Thu, 05 Oct 2023 09:33:49 +0000</pubDate>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Documentation]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=968</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[
<ul class="wp-block-list">
<li><a href="https://c4model.com/">https://c4model.com/</a></li>



<li><a href="https://backstage.io/">https://backstage.io/</a></li>



<li><a href="https://www.archunit.org/">https://www.archunit.org/</a></li>



<li><a href="https://docs.spring.io/spring-modulith/docs/current/reference/html/">Spring Boot Monolith</a></li>



<li><a href="https://www.asyncapi.com/">https://www.asyncapi.com/</a></li>



<li><a href="https://www.openapis.org/">https://www.openapis.org/</a></li>



<li><a href="https://www.eventcatalog.dev/" target="_blank" rel="noreferrer noopener">https://www.eventcatalog.dev/</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2023/10/useful-links-for-documentation-and-architecture/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Useful links for Event Driven Architectures</title>
		<link>https://sterl.org/2023/10/useful-links-for-event-driven-architectures/</link>
					<comments>https://sterl.org/2023/10/useful-links-for-event-driven-architectures/#comments</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Thu, 05 Oct 2023 09:29:20 +0000</pubDate>
				<category><![CDATA[Tools]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[asyncapi]]></category>
		<category><![CDATA[cloudevents]]></category>
		<category><![CDATA[Documentation]]></category>
		<category><![CDATA[Event Driven]]></category>
		<category><![CDATA[eventcatalog]]></category>
		<category><![CDATA[OpenAPI]]></category>
		<category><![CDATA[Swagger]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=965</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[
<ul class="wp-block-list">
<li><a href="https://cloudevents.io/">https://cloudevents.io/</a></li>



<li><a href="https://www.eventcatalog.dev/">https://www.eventcatalog.dev/</a></li>



<li><a href="https://www.asyncapi.com/">https://www.asyncapi.com/</a></li>



<li><a href="https://github.com/confluentinc/schema-registry">https://github.com/confluentinc/schema-registry</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2023/10/useful-links-for-event-driven-architectures/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Datenbanken &#124; Transaktionen &#124; Locks &#124; Isolationslevel</title>
		<link>https://sterl.org/2023/10/datenbanken-transaktionen-locks-isolationslevel/</link>
					<comments>https://sterl.org/2023/10/datenbanken-transaktionen-locks-isolationslevel/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Tue, 03 Oct 2023 09:12:50 +0000</pubDate>
				<category><![CDATA[Pattern & Best Practice]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[YouTube]]></category>
		<category><![CDATA[ACID]]></category>
		<category><![CDATA[Datenbanken]]></category>
		<category><![CDATA[Isolationslevel]]></category>
		<category><![CDATA[Locks]]></category>
		<category><![CDATA[Transaktionen]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=962</guid>

					<description><![CDATA[Als Basis für weiterführende Videos zum Thema Event Driven Architekturen, oder Eventual Consistency wollen wir uns zusammen Datenbanken und Transaktionen anschauen. Hier geht es darum ein Grundverständnis für Basiskonzepte zu schaffen wie:]]></description>
										<content:encoded><![CDATA[
<p>Als Basis für weiterführende Videos zum Thema Event Driven Architekturen, oder Eventual Consistency wollen wir uns zusammen Datenbanken und Transaktionen anschauen. Hier geht es darum ein Grundverständnis für Basiskonzepte zu schaffen wie:</p>



<ul class="wp-block-list">
<li>Transaktionen</li>



<li>ACID </li>



<li>Isolationslevel</li>



<li>Locks</li>
</ul>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Datenbanken Grundlagen | Transaktionen | Locks | Isolationslevel | praktisch erklärt | transactions" width="640" height="360" src="https://www.youtube.com/embed/F8Hdrb62-4c?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2023/10/datenbanken-transaktionen-locks-isolationslevel/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Datenbank&#124; Transaktionen &#124; Isolationlevel &#124; Locks &#124; Hibernate &#124; JPA &#124; Spring Boot</title>
		<link>https://sterl.org/2023/10/datenbank-transaktionen-isolationlevel-locks-hibernate-jpa-spring-boot/</link>
					<comments>https://sterl.org/2023/10/datenbank-transaktionen-isolationlevel-locks-hibernate-jpa-spring-boot/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Mon, 02 Oct 2023 11:40:50 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[YouTube]]></category>
		<category><![CDATA[DB Locks]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Isolationlevel]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Transaktionen]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=958</guid>

					<description><![CDATA[Um weiterführende Konzepte besser nachvollziehen zu können, wollen wir uns in den Grundlagen Datenbanken mit Spring Boot, Isolation Level (Isolationsgrad) und Locks beschäftigen.]]></description>
										<content:encoded><![CDATA[
<p>Um weiterführende Konzepte besser nachvollziehen zu können, wollen wir uns in den Grundlagen Datenbanken mit Spring Boot, Isolation Level (Isolationsgrad) und Locks beschäftigen.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Datenbanken Grundlagen | Transaktionen | Isolation Level | Locks | Hibernate | JPA | Spring Boot" width="640" height="360" src="https://www.youtube.com/embed/6ytlI4Sshjc?start=604&#038;feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2023/10/datenbank-transaktionen-isolationlevel-locks-hibernate-jpa-spring-boot/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Datenbank Timeouts &#124; Locks &#124; Isonaltionlevel &#124; Transaktionen</title>
		<link>https://sterl.org/2023/10/datenbank-timeouts-locks-isonaltionlevel-transaktionen/</link>
					<comments>https://sterl.org/2023/10/datenbank-timeouts-locks-isonaltionlevel-transaktionen/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Mon, 02 Oct 2023 11:15:27 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Pattern & Best Practice]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[YouTube]]></category>
		<category><![CDATA[Datenbanken]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Isonaltionlevel]]></category>
		<category><![CDATA[Lock]]></category>
		<category><![CDATA[Locks]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Timeouts]]></category>
		<category><![CDATA[Transaktionen]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=955</guid>

					<description><![CDATA[Häufig vergessen, oder nur teilweise gemacht. Timeouts tragen einen wesentlichen Bestandteil zur Stabilität und dem Ressourcenmanagement von Software bei. Insbesondere bei Microservices sollten diese immer richtig eingestellt sein. Timeouts spielen auch eine wesentliche Rolle in Bezug auf Transaktionen, Locks und Isolationslevel. Sollte man zudem den Zugriff auf die Datenbank auch Dritten gewähren, also nicht nur&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Häufig vergessen, oder nur teilweise gemacht. Timeouts tragen einen wesentlichen Bestandteil zur Stabilität und dem Ressourcenmanagement von Software bei. Insbesondere bei Microservices sollten diese immer richtig eingestellt sein. Timeouts spielen auch eine wesentliche Rolle in Bezug auf Transaktionen, Locks und Isolationslevel. Sollte man zudem den Zugriff auf die Datenbank auch Dritten gewähren, also nicht nur den Services selbst, dann sind diese umso wichtiger, für alle Clients, die auf die Datenbank zugreifen.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Datenbanken Grundlagen | Timeouts | Locks | Isonaltionlevel | DB | als Architekt | Microservices" width="640" height="360" src="https://www.youtube.com/embed/cW_k_VtOVmQ?start=217&#038;feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2023/10/datenbank-timeouts-locks-isonaltionlevel-transaktionen/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Quartz triggers, jobs, groups and more</title>
		<link>https://sterl.org/2022/07/quartz-triggers-jobs-groups-and-more/</link>
					<comments>https://sterl.org/2022/07/quartz-triggers-jobs-groups-and-more/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Sun, 03 Jul 2022 12:38:53 +0000</pubDate>
				<category><![CDATA[Quartz]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=822</guid>

					<description><![CDATA[If you are looking for a: Setup Quartz in JEE Setup Quartz in Spring Source Code to this page Trigger and Job names During the configuration we may select for each job and each trigger a name and a group. The last values gives us a way to cluster. The first one is in interesting.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>If you are looking for a:</p>



<ul class="wp-block-list"><li><a href="https://sterl.org/2019/09/quartz-scheduler-integration-in-java-jee/">Setup Quartz in JEE</a></li><li><a href="https://sterl.org/2022/07/quartz-integration-in-spring/">Setup Quartz in Spring</a></li><li><a href="https://github.com/sterlp/training/tree/master/spring-quartz" target="_blank" rel="noreferrer noopener">Source Code to this page</a></li></ul>



<h2 class="wp-block-heading">Trigger and Job names</h2>



<p>During the configuration we may select for each job and each trigger a name and a group. The last values gives us a way to cluster. The first one is in interesting.</p>



<h3 class="wp-block-heading">Job names</h3>



<p>Setting manually a job names makes the code refactoring save. By default the spring quartz integration uses the bean name. Which is good for the start, but in case that we refactor the code and rename the bean we have to keep in mind to delete the old job in the quartz tables. As so it is usually saver to define a name, which we keep stable:</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;}">@Bean
    public JobDetailFactoryBean retryJob() {
        final var jobDetailFactory = new JobDetailFactoryBean();
        jobDetailFactory.setJobClass(RetryJob.class);
        // static name, we may of course also define a constant
        jobDetailFactory.setName(&quot;RETRY-JOB&quot;);
        jobDetailFactory.setDurability(true);
        return jobDetailFactory;
    }</pre></div>



<p>If we now change the class name or packe structure it will get updated as soon we deploy the new version instead added to the job list.</p>



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



<p>The combination of a trigger name and trigger group has to be unique. Which gives us a very simple way to verify if a particular job was already scheduled or not. E.g. if we want to schedule a timer to notify a user that he has to change his password in 30 days we could just:</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 TriggerKey notifyUser(String user) throws SchedulerException {
        TriggerKey key = new TriggerKey(user, NotifyUserJob.ID);
        var t = TriggerBuilder.newTrigger()
                .forJob(JobKey.jobKey(NotifyUserJob.ID))
                .startAt(Date.from(Instant.now().plusMillis(1_000 * 60 * 60 * 24 * 30)))
                .usingJobData(&quot;user&quot;, user)
                .withIdentity(key)
                .build();
        scheduler.scheduleJob(t);
        return t.getKey();
    }</pre></div>



<p>Now we get a <code>ObjectAlreadyExistsException</code> if we trigger it again and we can easily delete the trigger if the user changes the password before it would trigger. We may also <a href="http://www.quartz-scheduler.org/documentation/quartz-2.3.0/cookbook/UpdateTrigger.html" target="_blank" rel="noreferrer noopener">update it</a>.</p>



<h2 class="wp-block-heading">Retry Triggers</h2>



<p>A very common case is not only too trigger a task but also have a way to implement a kind of retry. With quartz this is pretty straight forward. In general we have to possibilities:</p>



<ol class="wp-block-list"><li>Trigger immediately </li><li>Queue a new Trigger to run the same job with a delay</li></ol>



<div class="bs-callout bs-callout-info"><strong>Note:</strong>
If we want to retry a job we need usually two transactions. One in which we rollback all changes, the business transaction and one more in which we update the job data and the intent to retry the job; the job transaction which we want to commit.
</div>



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



<p>In the most simple way we can just catch any exception and re-trigger the job again. Any change to the <code>JobData</code> will be stored in an own transaction into the quartz tables. Which gives us a simple way to store intermediate results or just a retry counter; separately of our main application transaction and DB changes, which can rollback in peace.</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 RetryJob extends QuartzJobBean {

    @Autowired private YourService yourService;
    
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        Integer retryCount = (Integer)context.getMergedJobDataMap().getOrDefault(&quot;retryCount&quot;, 1);
        try {
            yourService.doStuff();
        } catch (Exception e) {
            if (retryCount &gt;= 3) {
                throw e;
            } else {
                // don't use the getMergedJobDataMap of spring, it will not be updated
                context.getTrigger().getJobDataMap().put(&quot;retryCount&quot;, retryCount + 1);
                throw new JobExecutionException(&quot;yourService.doStuff failed  &quot; 
                        + retryCount + &quot; times. Will retry. &quot; + e.getMessage(), 
                        true);
            }
        }
    }
}</pre></div>



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



<p>Usually we want to wait a bit before we retry, which is just updating the trigger:</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;}">    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        Integer retryCount = (Integer)context.getMergedJobDataMap().getOrDefault(&quot;retryCount&quot;, 1);
        try {
            yourService.doStuff();
        } catch (Exception e) {
            if (retryCount &gt; 3) {
                throw e;
            } else {
                // we have to use the trgger data, as we repalce the trigger now
                context.getTrigger().getJobDataMap().put(&quot;retryCount&quot;, retryCount + 1);
                
                final var tb = context.getTrigger().getTriggerBuilder();
                tb.startAt(Date.from(Instant.now().plusSeconds(retryCount * 10)));
                scheduler.rescheduleJob(context.getTrigger().getKey(), tb.build());
            }
        }
    }</pre></div>



<p><a href="https://github.com/sterlp/training/blob/master/spring-quartz/src/main/java/org/sterl/training/springquartz/example/jobs/RetryJob.java">Example on Git</a>.</p>



<h2 class="wp-block-heading">Delete all job triggers</h2>



<p>If we want to cancel all triggers for a job we can just list and delete them:</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;}">List&lt;? extends Trigger&gt; triggers = scheduler.getTriggersOfJob(xyzJob.getKey());
scheduler.unscheduleJobs(triggers.stream().map(t -&gt; t.getKey()).toList());</pre></div>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2022/07/quartz-triggers-jobs-groups-and-more/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<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>
	</channel>
</rss>
