<?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>Java &#8211; Pauls Blog</title>
	<atom:link href="https://sterl.org/category/java/feed/" rel="self" type="application/rss+xml" />
	<link>https://sterl.org</link>
	<description></description>
	<lastBuildDate>Tue, 30 Dec 2025 15:18:26 +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>A Bounded, Thread-Safe In-Memory Store for Java</title>
		<link>https://sterl.org/2025/12/java-simple-bound-memory-store/</link>
					<comments>https://sterl.org/2025/12/java-simple-bound-memory-store/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Tue, 30 Dec 2025 14:55:43 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[java test]]></category>
		<category><![CDATA[memory store]]></category>
		<category><![CDATA[Test]]></category>
		<category><![CDATA[Unit Test]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=1149</guid>

					<description><![CDATA[Problem In test scenarios or lightweight application components, there is a need for a simple, thread-safe, in-memory data store that can temporarily hold a limited number of objects. The store should be easy to use, avoid external dependencies (e.g., databases), support generation and use of unique identifiers as keys, and automatically evict the oldest entries&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>In test scenarios or lightweight application components, there is a need for a simple, thread-safe, in-memory data store that can temporarily hold a limited number of objects. The store should be easy to use, avoid external dependencies (e.g., databases), support generation and use of unique identifiers as keys, and automatically evict the oldest entries when a predefined capacity is exceeded. This enables predictable memory usage while providing fast access to recently stored data.</p>



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



<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;}">import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MemoryStore&lt;T&gt; {

    private final Lock lock = new ReentrantLock();
    private final int maxElements;

    private final Map&lt;String, T&gt; data = new LinkedHashMap&lt;&gt;() {
        // called during put and ensures the map doesn't grow
        @Override
        protected boolean removeEldestEntry(Map.Entry&lt;String, T&gt; eldest) {
            return size() &gt; maxElements;
        }
    };

    public MemoryStore(int maxElements) {
        if (maxElements &lt; 1) {
            throw new IllegalArgumentException(&quot;maxElements must be &gt; 1&quot;);
        }
        this.maxElements = maxElements;
    }
    
    public void store(T value) {
        this.store(UUID.randomUUID().toString(), value);
    }

    public void store(String key, T value) {
        lock.lock();
        try {
            data.put(key, value);
        } finally {
            lock.unlock();
        }
    }

    public T get(String key) {
        lock.lock();
        try {
            return data.get(key);
        } finally {
            lock.unlock();
        }
    }
    
    public int size() {
        lock.lock();
        try {
            return data.size();
        } finally {
            lock.unlock();
        }
    }
    
    public LinkedHashMap&lt;String, T&gt; data() {
        lock.lock();
        try {
            return new LinkedHashMap&lt;&gt;(this.data);
        } finally {
            lock.unlock();
        }
    }
}</pre></div>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2025/12/java-simple-bound-memory-store/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Spring Persistent Tasks</title>
		<link>https://sterl.org/2025/04/spring-persistent-tasks/</link>
					<comments>https://sterl.org/2025/04/spring-persistent-tasks/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Sun, 20 Apr 2025 07:16:43 +0000</pubDate>
				<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[dashboard]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Inbound Pattern]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Outbound Pattern]]></category>
		<category><![CDATA[Quartz]]></category>
		<category><![CDATA[quartz daschboard]]></category>
		<category><![CDATA[scheduled]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[task ui]]></category>
		<category><![CDATA[task-scheduling]]></category>
		<category><![CDATA[Transaction]]></category>
		<category><![CDATA[trigger]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=1116</guid>

					<description><![CDATA[A simple task management framework designed to queue and execute asynchronous tasks with support for database persistence and a user-friendly interface. It can be used to implement scheduling patterns or outbound patterns. Focus is the usage with spring boot and JPA. https://github.com/sterlp/spring-persistent-tasks Key Features]]></description>
										<content:encoded><![CDATA[
<p>A simple task management framework designed to queue and execute asynchronous tasks with support for database persistence and a user-friendly interface. It can be used to implement scheduling patterns or outbound patterns.</p>



<p>Focus is the usage with spring boot and JPA.</p>



<p><a href="https://github.com/sterlp/spring-persistent-tasks">https://github.com/sterlp/spring-persistent-tasks</a></p>



<h2 class="wp-block-heading">Key Features</h2>



<ol class="wp-block-list">
<li><strong>JPA-Powered Persistence</strong>&nbsp;&#8211; Automatically persists tasks to your database</li>



<li><strong>Spring Boot Auto-Configuration</strong>&nbsp;&#8211; Simple setup with @EnableSpringPersistentTasks</li>



<li><strong>Clustering Support</strong>&nbsp;&#8211; Built-in lock management for distributed environments</li>



<li><strong>Type-Safe Tasks</strong>&nbsp;&#8211; Generic task definitions with state objects</li>



<li><strong>Retry Mechanisms</strong>&nbsp;&#8211; Automatic retry policies for failed executions</li>



<li><strong>Transactional Integration</strong>&nbsp;&#8211; Works with Spring&#8217;s transaction management</li>



<li><strong>Queue Management</strong> &#8211; Intelligent task queuing and prioritization</li>



<li><strong>Different DB Supports</strong> 
<ul class="wp-block-list">
<li>MsSQL</li>



<li>MariaDB</li>



<li>Postgres</li>
</ul>
</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2025/04/spring-persistent-tasks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>React &#038; Spring Boot</title>
		<link>https://sterl.org/2024/12/react-spring-boot/</link>
					<comments>https://sterl.org/2024/12/react-spring-boot/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Wed, 11 Dec 2024 18:36:41 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[TypeScript]]></category>
		<category><![CDATA[ReactJs]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[vite]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=1095</guid>

					<description><![CDATA[Problem We want to combine Spring Boot with a simple React frontend. Use the React development features but also be able to use the Spring IDE. In the end, everything should be built using Maven and nicely packed into a JAR, just like any other Microservice. Let’s get started. Multi-Module project First we create a&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>We want to combine Spring Boot with a simple React frontend. Use the React development features but also be able to use the Spring IDE. In the end, everything should be built using Maven and nicely packed into a JAR, just like any other Microservice. Let’s get started.</p>



<h2 class="wp-block-heading">Multi-Module project</h2>



<p>First we create a spring project here <code>backend</code> folder and a react project in the <code>frontend</code> folder. The root pom should help us to build both projects in one run:</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://sterl.org/wp-content/uploads/2024/12/image.png"><img fetchpriority="high" decoding="async" width="294" height="211" src="https://sterl.org/wp-content/uploads/2024/12/image.png" alt="" class="wp-image-1096"/></a></figure></div>


<h3 class="wp-block-heading">Root pom.xml</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;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;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

    &lt;groupId&gt;org.foo.bar&lt;/groupId&gt;
    &lt;artifactId&gt;project-root&lt;/artifactId&gt;
    &lt;version&gt;0.1.0-SNAPSHOT&lt;/version&gt;
    &lt;packaging&gt;pom&lt;/packaging&gt;

    &lt;properties&gt;
        &lt;java.version&gt;21&lt;/java.version&gt;
        &lt;maven.compiler.source&gt;${java.version}&lt;/maven.compiler.source&gt;
        &lt;maven.compiler.target&gt;${java.version}&lt;/maven.compiler.target&gt;
        &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
        &lt;project.reporting.outputEncoding&gt;UTF-8&lt;/project.reporting.outputEncoding&gt;
    &lt;/properties&gt;

    &lt;modules&gt;
        &lt;module&gt;frontend&lt;/module&gt;
        &lt;module&gt;backend&lt;/module&gt;
    &lt;/modules&gt;

  	&lt;!-- feel free to use spring as root instead of this --&gt;
    &lt;dependencyManagement&gt;
        &lt;dependencies&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
                &lt;version&gt;3.3.6&lt;/version&gt;
                &lt;type&gt;pom&lt;/type&gt;
                &lt;scope&gt;import&lt;/scope&gt;
            &lt;/dependency&gt;
        &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;
&lt;/project&gt;</pre></div>



<h3 class="wp-block-heading">Backend pom.xml</h3>



<p>This is straight forward the generated pom from spring with just the dependency to the <code>frontend </code>project.</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;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;parent&gt;
        &lt;groupId&gt;org.foo.bar&lt;/groupId&gt;
        &lt;artifactId&gt;project-root&lt;/artifactId&gt;
        &lt;version&gt;0.1.0-SNAPSHOT&lt;/version&gt;
        &lt;relativePath&gt;../pom.xml&lt;/relativePath&gt;
    &lt;/parent&gt;

    &lt;artifactId&gt;project-backend&lt;/artifactId&gt;

    &lt;dependencies&gt;
      	&lt;!-- thats the important part --&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.foo.bar&lt;/groupId&gt;
            &lt;artifactId&gt;project-frontend&lt;/artifactId&gt;
            &lt;version&gt;${project.version}&lt;/version&gt;
        &lt;/dependency&gt;
      	&lt;!-- thats the important part end --&gt;
      
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;/dependency&gt;  
        &lt;dependency&gt;
            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
            &lt;artifactId&gt;lombok&lt;/artifactId&gt;
            &lt;optional&gt;true&lt;/optional&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;

&lt;/project&gt;</pre></div>



<h3 class="wp-block-heading">Frontend pom.xml</h3>



<p>Now we have todo more stuff:</p>



<ol class="wp-block-list">
<li>Ensure the <code>dist</code> result is added to the JAR</li>



<li>Generate during the <code>generate-resources</code> phase also the content for the <code>dist</code> folder</li>



<li>Ensure that during a <code>mvn clean</code> all gets deleted</li>
</ol>



<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;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;parent&gt;
        &lt;groupId&gt;org.foo.bar&lt;/groupId&gt;
        &lt;artifactId&gt;project-root&lt;/artifactId&gt;
        &lt;version&gt;0.1.0-SNAPSHOT&lt;/version&gt;
        &lt;relativePath&gt;../pom.xml&lt;/relativePath&gt;
    &lt;/parent&gt;

    &lt;artifactId&gt;project-frontend&lt;/artifactId&gt;
    
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
            &lt;scope&gt;provided&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
    
    &lt;build&gt;
        &lt;!-- Ensure the dist result is added to the JAR --&gt;
        &lt;resources&gt;
            &lt;resource&gt;
                &lt;directory&gt;dist&lt;/directory&gt;
            &lt;/resource&gt;
        &lt;/resources&gt;

        &lt;plugins&gt;
          	&lt;!--
                Generate during the generate-resources phase 
                also the content for the dist folder 
            --&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
                &lt;artifactId&gt;exec-maven-plugin&lt;/artifactId&gt;
                &lt;version&gt;3.5.0&lt;/version&gt;
                &lt;executions&gt;
                    &lt;execution&gt;
                        &lt;id&gt;npm install&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;exec&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;phase&gt;generate-resources&lt;/phase&gt;
                        &lt;configuration&gt;
                            &lt;executable&gt;npm&lt;/executable&gt;
                            &lt;arguments&gt;
                                &lt;argument&gt;install&lt;/argument&gt;
                                &lt;argument&gt;--prefer-offline&lt;/argument&gt;
                                &lt;argument&gt;--no-audit&lt;/argument&gt;
                                &lt;argument&gt;--progress=false&lt;/argument&gt;
                            &lt;/arguments&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;

                    &lt;execution&gt;
                        &lt;id&gt;npm build&lt;/id&gt;
                        &lt;goals&gt;
                            &lt;goal&gt;exec&lt;/goal&gt;
                        &lt;/goals&gt;
                        &lt;phase&gt;generate-resources&lt;/phase&gt;
                        &lt;configuration&gt;
                            &lt;executable&gt;npm&lt;/executable&gt;
                            &lt;arguments&gt;
                                &lt;argument&gt;run&lt;/argument&gt;
                                &lt;argument&gt;build&lt;/argument&gt;
                            &lt;/arguments&gt;
                        &lt;/configuration&gt;
                    &lt;/execution&gt;
                &lt;/executions&gt;
            &lt;/plugin&gt;
            &lt;!-- Ensure that during a mvn clean all gets deleted --&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-clean-plugin&lt;/artifactId&gt;
                &lt;version&gt;3.4.0&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;filesets&gt;
                        &lt;fileset&gt;
                            &lt;directory&gt;node_modules&lt;/directory&gt;
                        &lt;/fileset&gt;
                        &lt;fileset&gt;
                            &lt;directory&gt;dist&lt;/directory&gt;
                        &lt;/fileset&gt;
                    &lt;/filesets&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;

&lt;/project&gt;</pre></div>



<h3 class="wp-block-heading">Ensure the result in the dist folder is compatible to Spring</h3>



<p>Spring will pick up automatically any static resources which are placed in the <code>static</code> folder. Here is an example for <a rel="noreferrer noopener" href="https://vite.dev/guide/" target="_blank">vite</a> to do so in the <code>vite.config.js</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;javascript&quot;,&quot;mime&quot;:&quot;application/json&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;JSON&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;json&quot;}">export default defineConfig({
  plugins: [react()],
  build: {
    outDir: './dist/static',
    emptyOutDir: true, // also necessary
  }
})</pre></div>



<h2 class="wp-block-heading">Going beyond</h2>



<p>Sometime it is useful to host the UI in a sub path lets say <code>my-ui</code>, so the url would be <mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color"><strong>http://localhost:8080/my-ui</strong></mark></p>



<p>For that we have to adjust the <code>vite.config.js</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;javascript&quot;,&quot;mime&quot;:&quot;application/json&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;JSON&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;json&quot;}">export default defineConfig({
  plugins: [react()],
  base: 'my-ui',
  build: {
    outDir: './dist/static/my-ui',
    emptyOutDir: true,
  }
})</pre></div>



<p>Now it would also be helpful if we don&#8217;t have to directly type the <code>index.html</code> but tell Spring always to re-route.</p>



<p>For that we have to add a Spring Configuration Class:</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;}">package org.foo.bar;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyFrontedConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController(&quot;/my-ui&quot;).setViewName(&quot;/my-ui/index.html&quot;);
        registry.addRedirectViewController(&quot;/my-ui/&quot;, &quot;/my-ui&quot;);
    }
}
</pre></div>



<h2 class="wp-block-heading">Add cache control to static react assets</h2>



<p>In the end int would also be nice that the generated static resources are cached by the client e.g. for a year. We will extend the <code>MyFrontedConfig</code> class with:</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
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(&quot;/my-ui/assets/**&quot;) 
                .addResourceLocations(&quot;classpath:/static/my-ui/assets/&quot;) 
                .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
    }</pre></div>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2024/12/react-spring-boot/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>Java Jobs and Trigger Frameworks</title>
		<link>https://sterl.org/2024/05/java-jobs-and-trigger-frameworks/</link>
					<comments>https://sterl.org/2024/05/java-jobs-and-trigger-frameworks/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Mon, 06 May 2024 07:45:53 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=1026</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[
<ul class="wp-block-list">
<li><a href="https://www.quartz-scheduler.org/">Quartz</a></li>



<li><a href="https://github.com/kagkarlsson/db-scheduler">db-scheduler</a></li>



<li><a href="https://github.com/jobrunr/jobrunr">jobrunr</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2024/05/java-jobs-and-trigger-frameworks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Setup Spring Boot Azure OAuth2 with CORS</title>
		<link>https://sterl.org/2024/02/setup-spring-boot-azure-oauth2-with-cors/</link>
					<comments>https://sterl.org/2024/02/setup-spring-boot-azure-oauth2-with-cors/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Thu, 01 Feb 2024 09:03:03 +0000</pubDate>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[CORS error]]></category>
		<category><![CDATA[oauth2Login]]></category>
		<category><![CDATA[OAuth2UserService]]></category>
		<category><![CDATA[strict-origin-when-cross-origin]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=993</guid>

					<description><![CDATA[What is needed Setup an Azure AAD Application First we need an Azure AAD application which gives us the access to our AD users. The important part are the client id and the tenant id here: Add the web URIs which are allowed to use the OAuth2 login In the next step we have to&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">What is needed</h2>



<ol class="wp-block-list">
<li>Setup an Azure AAD Application</li>



<li>Add the web URIs which are allowed to use the OAuth2 login</li>



<li>Add a client secret for your application</li>



<li>Add API Permission to read the profile</li>



<li>Add needed Azure dependencies</li>



<li>Setup Spring OAuth config</li>



<li>Adjust the CORS settings in Spring to ensure token refreshes</li>



<li>Configure spring security</li>
</ol>



<h2 class="wp-block-heading">Setup an Azure AAD Application</h2>



<p>First we need an Azure AAD application which gives us the access to our AD users. The important part are the client id and the tenant id here:</p>



<figure class="wp-block-image size-full is-resized"><a href="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application.png"><img decoding="async" width="810" height="243" src="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application.png" alt="" class="wp-image-1004" style="aspect-ratio:3.3333333333333335;width:840px;height:auto" srcset="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application.png 810w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-300x90.png 300w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-768x230.png 768w" sizes="(max-width: 810px) 100vw, 810px" /></a></figure>



<h2 class="wp-block-heading">Add the web URIs which are allowed to use the OAuth2 login</h2>



<p>In the next step we have to allow &#8222;applications&#8220; based on their &#8222;DNS&#8220; name to access and login through this AAD. Ensure to remember the yellow part, which is later needed in the configutation.</p>



<p>The URLs are basically the one you whitelist for a login. If you setup the &#8222;test&#8220; AAD application you may want also add sometimes the localhost for testing. Ensure to remove it again later on.</p>



<figure class="wp-block-image size-large"><a href="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-autthentication.png"><img loading="lazy" decoding="async" width="1024" height="493" src="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-autthentication-1024x493.png" alt="" class="wp-image-1006" srcset="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-autthentication-1024x493.png 1024w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-autthentication-300x144.png 300w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-autthentication-768x369.png 768w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-autthentication.png 1368w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<h2 class="wp-block-heading">Add a client secret for your application</h2>



<p>Next we have to create a secret for our application, we only require later the value of it. Please make sure you provide a new one after the expiration period.</p>



<p>You can have multiple secrets for multiple apps here.</p>



<figure class="wp-block-image size-large"><a href="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-secret.png"><img loading="lazy" decoding="async" width="1024" height="317" src="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-secret-1024x317.png" alt="" class="wp-image-1009" srcset="https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-secret-1024x317.png 1024w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-secret-300x93.png 300w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-secret-768x238.png 768w, https://sterl.org/wp-content/uploads/2024/02/azure-aad-application-secret.png 1439w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>



<h2 class="wp-block-heading">Setup Spring OAuth config</h2>



<p>In this configuration we have to enter all the collected data <strong>azure-dev</strong> as name is here the suffix provided in the authentication section of the Azure AAD application. You can choose what ever name you like.</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:
  security:
    oauth2:
      client:
        provider:
          azure:
            issuer-uri: https://login.microsoftonline.com/&lt;Directory (tenant) ID&gt;/v2.0
            user-name-attribute: name
        registration:
          azure-dev:
            provider: azure
            client-id: &lt;Application (client) ID&gt;
            client-secret: &lt;the secret value you created for your app&gt;
            client-authentication-method: client_secret_post
            scope:
              - openid
              - email
              - profile</pre></div>



<h2 class="wp-block-heading">Spring Security</h2>



<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
  SecurityFilterChain filterChain(HttpSecurity http, OptionalYourUserService userService) throws Exception {
    // @formatter:off
    http
      .authorizeHttpRequests(authorizeHttpRequests -&gt;
        authorizeHttpRequests
          // public URLs
          .requestMatchers(antMatcher(&quot;/actuator/health/readiness&quot;)).permitAll()
          // secure actuator
          .requestMatchers(antMatcher(&quot;/actuator/**&quot;)).hasRole(UserGroup.ADMIN)
          // app urls
          .requestMatchers(&quot;/api/**&quot;).authenticated()
          // default; recommended to use .authenticated()
          .anyRequest().permitAll()
      ).headers(headers -&gt; headers.frameOptions(FrameOptionsConfig::sameOrigin))
      .oauth2Login( oauth2 -&gt; oauth2
          .userInfoEndpoint(userInfo -&gt; userInfo
            .oidcUserService(oidcUserService(userService)))
      )
      .headers(headers -&gt; headers.frameOptions(FrameOptionsConfig::sameOrigin));
    // @formatter:on
    return http.build();
  }

  private OAuth2UserService&lt;OidcUserRequest, OidcUser&gt; oidcUserService(
    OptionalYourUserService userService) {
    return userRequest -&gt; {
      var oidcUser = new OidcUserService().loadUser(userRequest); // Delegate to the default
                                                                  // implementation
      
      // add any custom user service integration here, if required.

      return oidcUser;
    };
  }</pre></div>



<h2 class="wp-block-heading">Add CORS Config</h2>



<p>To avoid any <code>CORS error</code> / <code>strict-origin-when-cross-origin</code> in your application we have to whitelist the OAuth2 provider for any redirect, in this example login.microsoft:</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
  protected CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList(&quot;https://login.microsoftonline.com/**&quot;));
    configuration.addAllowedHeader(&quot;*&quot;);
    configuration.addAllowedMethod(&quot;*&quot;);
    configuration.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration(&quot;/**&quot;, configuration);
    return source;
  }</pre></div>



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



<ul class="wp-block-list">
<li>https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/spring-boot-starter-for-azure-active-directory-developer-guide</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2024/02/setup-spring-boot-azure-oauth2-with-cors/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>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>JPA Model testing with Hibernate Statistics</title>
		<link>https://sterl.org/2021/08/jpa-model-testing-with-hibernate-statistics/</link>
					<comments>https://sterl.org/2021/08/jpa-model-testing-with-hibernate-statistics/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Sun, 01 Aug 2021 11:25:00 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JPA]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Testing]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Unit Test]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=925</guid>

					<description><![CDATA[Problem Often we write JPA Entity classes an have to ensure in a larger team that refactoring doesn&#8217;t create performance problems or logical errors in the entity model usual problems are: In your test]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>Often we write JPA Entity classes an have to ensure in a larger team that refactoring doesn&#8217;t create performance problems or logical errors in the entity model usual problems are:</p>



<ul class="wp-block-list">
<li>Missing fetch joins in Queries
<ul class="wp-block-list">
<li>Which leads to slow fetch joins</li>
</ul>
</li>



<li>Wrong direction of Entity relations 
<ul class="wp-block-list">
<li>which leads to updates after inserts</li>



<li>or even to deletes and reinserts of data</li>
</ul>
</li>



<li>Wrong transaction boundaries
<ul class="wp-block-list">
<li>Which leads to multiple transactions for one logical business operation</li>
</ul>
</li>
</ul>



<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;}">@Component
public class HibernateAsserts {
  private final Statistics statistics;

  public HibernateAsserts(EntityManager entityManager) {
    try (Session session = entityManager.unwrap(org.hibernate.Session.class)) {
      @SuppressWarnings(&quot;resource&quot;)
      SessionFactory factory = session.getSessionFactory();
      factory.getStatistics().setStatisticsEnabled(true);
      statistics = factory.getStatistics();
    }
  }
  
  public HibernateAsserts assertTrxCount(int expected) {
    long value = statistics.getTransactionCount();
    if (value != expected) {
      logSummary();
      fail(&quot;Expected &quot; + expected + &quot; TransactionCount, but found &quot; + value);
    }
    return this;
  }
  
  public HibernateAsserts assertInsertCount(int expected) {
    long value = statistics.getEntityInsertCount();
    if (value != expected) {
      logSummary();
      fail(&quot;Expected &quot; + expected + &quot; EntityInsertCount, but found &quot; + value);
    }
    return this;
  }

  public void reset() {
    statistics.clear();
  }

  public void logSummary() {
    statistics.logSummary();
  }
}</pre></div>



<h2 class="wp-block-heading">In your test</h2>



<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;}">@SpringBootTest
class MyTestClassTest {

  @Autowired private SubjectUnderTest subject;
  @Autowired private HibernateAsserts hibernateAsserts;
  
  @Test
  void textMyBusinessMethod() {
    // GIVEN
    // custom data setup for the test

    // WHEN
    hibernateAsserts.reset(); // ensure the setup is not in the stats
    subject.runBusinessMethod();
    
    // THEN
    // any business asserts
    hibernateAsserts
      .assertTrxCount(1)
      .assertInsertCount(1);
  }
}</pre></div>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2021/08/jpa-model-testing-with-hibernate-statistics/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Aspects with Annotations</title>
		<link>https://sterl.org/2021/05/aspects-with-annotations/</link>
					<comments>https://sterl.org/2021/05/aspects-with-annotations/#respond</comments>
		
		<dc:creator><![CDATA[Paul Sterl]]></dc:creator>
		<pubDate>Mon, 24 May 2021 09:28:46 +0000</pubDate>
				<category><![CDATA[AOP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[aspect]]></category>
		<guid isPermaLink="false">https://sterl.org/?p=655</guid>

					<description><![CDATA[Problem Define a pointcut for annotated methods. The most example are based only on @within or @annotation which has the downside that the aspect is added to all methods and the check of the annotation is executed during runtime. Solution Git Repository https://github.com/sterlp/training/tree/master/aspect Links https://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#aop-pointcuts-designators]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Problem</h2>



<p>Define a pointcut for annotated methods. The most example are based only on <code>@within</code> or <code>@annotation</code> which has the downside that the aspect is added to all methods and the check of the annotation is executed during runtime. </p>



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



<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;}">@Aspect
@Component
public class MethodAspect {
    /**
     * This ensures that the aspect is only woven into methods with the annotation.
     * Otherwise all methods are woven!
     */
    @Pointcut(&quot;execution(@MethodAnnotation * * (..))&quot;)
    private void isAnnotated() {};
    /**
     * (optional) Limit package scan to our project only
     */
    @Pointcut(&quot;execution(* your.project.package..*(..))&quot;)
    private void isInPackage() {};

    @Around(&quot;isAnnotated() &amp;&amp; isInPackage() &amp;&amp; @annotation(annotation)&quot;)
    public Object logExecutionTime(ProceedingJoinPoint joinPoint, 
                                   MethodAnnotation annotation) throws Throwable {
        return joinPoint.proceed();
    }
}</pre></div>



<h2 class="wp-block-heading">Git Repository</h2>



<p><a href="https://github.com/sterlp/training/tree/master/aspect">https://github.com/sterlp/training/tree/master/aspect</a></p>



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



<ul class="wp-block-list"><li><a href="https://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html">https://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html</a></li><li><a href="https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#aop-pointcuts-designators">https://docs.spring.io/spring-framework/docs/5.3.x/reference/html/core.html#aop-pointcuts-designators</a></li></ul>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://sterl.org/2021/05/aspects-with-annotations/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
