<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: araf</title>
    <description>The latest articles on DEV Community by araf (@haraf).</description>
    <link>https://dev.to/haraf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2841337%2F618790c8-298e-46ea-832b-d1a17297df44.png</url>
      <title>DEV Community: araf</title>
      <link>https://dev.to/haraf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/haraf"/>
    <language>en</language>
    <item>
      <title>AI Coding Agents 2025: GitHub Copilot vs Rovo Dev vs Cursor vs Claude vs Gemini vs Codeium</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Mon, 22 Dec 2025 09:49:18 +0000</pubDate>
      <link>https://dev.to/haraf/ai-coding-agents-2025-github-copilot-vs-rovo-dev-vs-cursor-vs-claude-vs-gemini-vs-codeium-5ham</link>
      <guid>https://dev.to/haraf/ai-coding-agents-2025-github-copilot-vs-rovo-dev-vs-cursor-vs-claude-vs-gemini-vs-codeium-5ham</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Autocomplete is dead. Context, refactoring, and agentic workflows are the new battleground.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I tested &lt;strong&gt;GitHub Copilot, Rovo Dev, Cursor, Anthropic Claude, Google Gemini Code Assist, and Codeium&lt;/strong&gt; in real dev workflows: Java, TypeScript, backend APIs, refactoring, debugging.&lt;/p&gt;

&lt;p&gt;Here’s a &lt;strong&gt;developer-focused, side-by-side comparison&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Quick Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Strengths&lt;/th&gt;
&lt;th&gt;Limitations&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams &amp;amp; general devs&lt;/td&gt;
&lt;td&gt;IDE support, autocomplete, GitHub integration&lt;/td&gt;
&lt;td&gt;Paid, small free tier&lt;/td&gt;
&lt;td&gt;~$10/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rovo Dev&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Terminal-centric &amp;amp; enterprise&lt;/td&gt;
&lt;td&gt;CLI automation, Jira/Bitbucket integration&lt;/td&gt;
&lt;td&gt;Newer, niche&lt;/td&gt;
&lt;td&gt;Enterprise pricing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cursor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Power users&lt;/td&gt;
&lt;td&gt;Multi-file refactors, deep repo understanding&lt;/td&gt;
&lt;td&gt;VS Code–centric&lt;/td&gt;
&lt;td&gt;~$20/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Claude&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complex reasoning&lt;/td&gt;
&lt;td&gt;Architecture &amp;amp; logic understanding&lt;/td&gt;
&lt;td&gt;Weak IDE integration&lt;/td&gt;
&lt;td&gt;~$20+/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gemini Code Assist&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free tier &amp;amp; cloud devs&lt;/td&gt;
&lt;td&gt;Large context, free tier&lt;/td&gt;
&lt;td&gt;Less polished&lt;/td&gt;
&lt;td&gt;Free/$19+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Codeium&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Budget developers&lt;/td&gt;
&lt;td&gt;Free, basic autocomplete&lt;/td&gt;
&lt;td&gt;Weak deep context&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ GitHub Copilot — All-Rounder
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckljlj8jh7f1zs83f927.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fckljlj8jh7f1zs83f927.png" alt="Copilot" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Works in VS Code, JetBrains, Neovim; strong autocomplete; GitHub PR/chat integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Paid; context window smaller than others&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Production dev, team workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧑‍💻 Rovo Dev — Terminal &amp;amp; Enterprise
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Fzsv3d0ugroxu%2F1Pf96MnmCiSKhbh78CIdVS%2F9a3aff6b155c49ed98c1fc9b93199f04%2Fscreenshot_RovoDevCLI_commands" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Fzsv3d0ugroxu%2F1Pf96MnmCiSKhbh78CIdVS%2F9a3aff6b155c49ed98c1fc9b93199f04%2Fscreenshot_RovoDevCLI_commands" alt="Rovo Dev" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Automates tasks in CLI; deep Jira/Bitbucket/Confluence integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Niche, CLI-focused; enterprise pricing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Teams using Atlassian tools&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Cursor — Deep Codebase
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hs1pveq2i00hq5b2btf.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2hs1pveq2i00hq5b2btf.webp" alt="Cursor" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Multi-file refactors; deep context understanding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; VS Code fork; some CI integrations weaker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Senior devs, large repos&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤖 Claude — Complex Reasoning
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4j7kw04qfic0asdhrbe3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4j7kw04qfic0asdhrbe3.png" alt="Claude" width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Architecture, reasoning, explanations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; IDE integration weaker&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Designing complex systems, logic review&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🆓 Gemini Code Assist — Free &amp;amp; Generous
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkviz8c3xyhej5c3zsni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkviz8c3xyhej5c3zsni.png" alt="Gemini" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Free tier, large context, CLI support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Less polished suggestions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Hobbyists, learners, free experimentation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💸 Codeium — Free Basic Help
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodesandbox.io%2Fdocs%2F_next%2Fimage%3Fq%3D75%26url%3D%252Fdocs%252F_next%252Fstatic%252Fmedia%252Fcodeium-example.398d0c32.png%26w%3D3840" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodesandbox.io%2Fdocs%2F_next%2Fimage%3Fq%3D75%26url%3D%252Fdocs%252F_next%252Fstatic%252Fmedia%252Fcodeium-example.398d0c32.png%26w%3D3840" alt="Codeium" width="2560" height="1440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Free forever, basic autocomplete, IDE plugin support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Weak for deep context or multi-file logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Students, beginners, free users&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Verdict
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Balanced &amp;amp; mainstream:&lt;/strong&gt; GitHub Copilot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep VS Code refactoring:&lt;/strong&gt; Cursor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex reasoning:&lt;/strong&gt; Claude&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best free tier:&lt;/strong&gt; Gemini&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free basics:&lt;/strong&gt; Codeium&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise automation:&lt;/strong&gt; Rovo Dev&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Most serious devs in 2025 use &lt;strong&gt;2+ agents&lt;/strong&gt;: Copilot/Cursor for coding, Claude/Gemini for reasoning, Rovo Dev for enterprise workflow.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📌 Strategy
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Try &lt;strong&gt;Codeium + Gemini&lt;/strong&gt; to test AI in your flow.&lt;/li&gt;
&lt;li&gt;Evaluate &lt;strong&gt;Copilot or Cursor&lt;/strong&gt; on real projects.&lt;/li&gt;
&lt;li&gt;Enterprise teams: Copilot for GitHub, Rovo Dev for Jira/Bitbucket automation.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://www.digitalapplied.com/blog/gemini-vs-github-copilot-vs-cursor-comparison" rel="noopener noreferrer"&gt;DigitalApplied&lt;/a&gt; | &lt;a href="https://www.theverge.com/news/808032/github-ai-agent-hq-coding-openai-anthropic" rel="noopener noreferrer"&gt;The Verge&lt;/a&gt; | &lt;a href="https://www.atlassian.com/blog/announcements/rovo-dev-command-line-interface" rel="noopener noreferrer"&gt;Atlassian Rovo&lt;/a&gt;&lt;/p&gt;




</description>
      <category>vibecoding</category>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🚀 Upgrading Your Legacy Java 8 + Spring Boot 2.1 Project to Java 17 (Without Breaking Everything)</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Thu, 11 Dec 2025 03:21:33 +0000</pubDate>
      <link>https://dev.to/haraf/upgrading-your-legacy-java-8-spring-boot-21-project-to-java-17-without-breaking-everything-n85</link>
      <guid>https://dev.to/haraf/upgrading-your-legacy-java-8-spring-boot-21-project-to-java-17-without-breaking-everything-n85</guid>
      <description>&lt;p&gt;Upgrading a large Java 8 + Spring Boot 2.1 codebase to Java 17 feels scary.&lt;br&gt;
Modules, removed APIs, dependency conflicts, Jakarta migration — a lot can break.&lt;/p&gt;

&lt;p&gt;This guide gives you a safe, production-tested path to upgrade without downtime.&lt;/p&gt;


&lt;h2&gt;
  
  
  ✅ Why Upgrade to Java 17?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LTS until 2029&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Long-term support &amp;amp; security updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;40–60% faster JVM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Better GC (G1/ZGC), faster execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Modern language features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;var, records, sealed classes, switch expressions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Better memory usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reduced heap footprint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;More secure&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Stronger TLS, crypto, JVM rules&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  🧭 Safe Upgrade Path (The Only Path That Won’t Break Everything)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Phase 1 → Java 8 → Java 11&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 2 → Spring Boot 2.1 → 2.7&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 3 → Java 11 → Java 17&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phase 4 → Spring Boot 2.7 → 3.x (Jakarta)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🔹 Phase 1 — Upgrade Java 8 → Java 11
&lt;/h2&gt;

&lt;p&gt;Update &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;java.version&amp;gt;&lt;/span&gt;11&lt;span class="nt"&gt;&amp;lt;/java.version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix removed Java EE modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;javax.xml.bind&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;jaxb-api&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.3.1&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check incompatible libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn dependency:tree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔹 Phase 2 — Upgrade Spring Boot 2.1 → 2.7
&lt;/h2&gt;

&lt;p&gt;Update Boot version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;parent&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-parent&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.7.18&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/parent&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things to fix before Spring Boot 3:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;strong&gt;Springfox&lt;/strong&gt; with &lt;strong&gt;springdoc-openapi&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Move to &lt;strong&gt;new constructor-binding&lt;/strong&gt; style for &lt;code&gt;@ConfigurationProperties&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clean deprecated security config&lt;/li&gt;
&lt;li&gt;Start migrating from &lt;code&gt;RestTemplate&lt;/code&gt; → &lt;code&gt;WebClient&lt;/code&gt; (optional)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔹 Phase 3 — Upgrade Java 11 → Java 17
&lt;/h2&gt;

&lt;p&gt;Update in &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;java.version&amp;gt;&lt;/span&gt;17&lt;span class="nt"&gt;&amp;lt;/java.version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common fixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reflection warnings (&lt;code&gt;--add-opens&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Replace any legacy HTTP clients&lt;/li&gt;
&lt;li&gt;Ensure all dependencies support Java 17&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔹 Phase 4 — Upgrade Spring Boot 2.7 → 3.x (Jakarta Mandatory)
&lt;/h2&gt;

&lt;p&gt;Spring Boot 3 uses &lt;strong&gt;Jakarta EE 9+&lt;/strong&gt;.&lt;br&gt;
All &lt;code&gt;javax.*&lt;/code&gt; packages are now &lt;code&gt;jakarta.*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jakarta.servlet.http.HttpServletRequest&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update Boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;parent&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-parent&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.3.4&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/parent&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Required Migrations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Javax → Jakarta
&lt;/h3&gt;

&lt;p&gt;Run to find:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grep -R "javax" src/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Spring Security Rewrite
&lt;/h3&gt;

&lt;p&gt;Old:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorizeRequests&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;anyRequest&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;authenticated&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorizeHttpRequests&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;requestMatchers&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/**"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;authenticated&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Hibernate/JPA
&lt;/h3&gt;

&lt;p&gt;Replace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;javax.persistence&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;jakarta.persistence&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Swagger Migration
&lt;/h3&gt;

&lt;p&gt;Remove Springfox and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springdoc&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;springdoc-openapi-starter-webmvc-ui&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;2.6.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Testing Strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add JDK 17 to CI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup JDK&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-java@v3&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;distribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temurin'&lt;/span&gt;
    &lt;span class="na"&gt;java-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;17'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run full integration tests
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Controllers&lt;/li&gt;
&lt;li&gt;WebClient/Feign&lt;/li&gt;
&lt;li&gt;Kafka/RabbitMQ&lt;/li&gt;
&lt;li&gt;Flyway/Liquibase&lt;/li&gt;
&lt;li&gt;Full database workflows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧰 Common Issues &amp;amp; Fixes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ClassNotFound: javax.*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Replace with &lt;strong&gt;jakarta&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spring Security not working&lt;/td&gt;
&lt;td&gt;Rewrite security config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swagger UI not loading&lt;/td&gt;
&lt;td&gt;Use &lt;strong&gt;springdoc-openapi&lt;/strong&gt;, not Springfox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reflection warnings&lt;/td&gt;
&lt;td&gt;Temporary: &lt;code&gt;--add-opens&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🏁 Final Upgrade Checklist
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Java Upgrade
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Java 8 → 11&lt;/li&gt;
&lt;li&gt;[ ] Fix removed Java EE modules&lt;/li&gt;
&lt;li&gt;[ ] Java 11 → 17&lt;/li&gt;
&lt;li&gt;[ ] Update CI pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Spring Boot Upgrade
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Upgrade 2.1 → 2.7&lt;/li&gt;
&lt;li&gt;[ ] Remove deprecated Spring APIs&lt;/li&gt;
&lt;li&gt;[ ] Upgrade 2.7 → 3.x&lt;/li&gt;
&lt;li&gt;[ ] Migrate javax → jakarta&lt;/li&gt;
&lt;li&gt;[ ] Update Spring Security&lt;/li&gt;
&lt;li&gt;[ ] Replace Springfox → springdoc&lt;/li&gt;
&lt;li&gt;[ ] Update Hibernate/JPA&lt;/li&gt;
&lt;li&gt;[ ] Run full integration tests&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎉 Conclusion
&lt;/h2&gt;

&lt;p&gt;Upgrading Java 8 + Spring Boot 2.1 directly to Java 17 + Spring Boot 3.x is risky.&lt;br&gt;
But using the safe 4-phase approach prevents almost all breaking changes:&lt;/p&gt;

&lt;p&gt;1️⃣ Java 8 → 11&lt;br&gt;
2️⃣ Spring Boot 2.1 → 2.7&lt;br&gt;
3️⃣ Java 11 → 17&lt;br&gt;
4️⃣ Spring Boot 2.7 → 3.x (Jakarta)&lt;/p&gt;

&lt;p&gt;Follow the checklist, fix deprecated APIs early, and test thoroughly — and your upgrade will be smooth.&lt;/p&gt;




</description>
      <category>java</category>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mastering Spring AOP: Real-World Use Case and Practical Code Samples</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Thu, 30 Oct 2025 05:37:41 +0000</pubDate>
      <link>https://dev.to/haraf/mastering-spring-aop-real-world-use-case-and-practical-code-samples-5859</link>
      <guid>https://dev.to/haraf/mastering-spring-aop-real-world-use-case-and-practical-code-samples-5859</guid>
      <description>&lt;p&gt;&lt;strong&gt;Spring AOP (Aspect-Oriented Programming)&lt;/strong&gt; is one of the most underrated yet powerful features in the Spring ecosystem. It helps you &lt;strong&gt;modularize cross-cutting concerns&lt;/strong&gt; such as logging, security, transactions, and performance monitoring — without cluttering your business logic.&lt;/p&gt;

&lt;p&gt;In this post, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What AOP really is (without the academic jargon)&lt;/li&gt;
&lt;li&gt;Real-world use cases&lt;/li&gt;
&lt;li&gt;A practical Spring Boot example&lt;/li&gt;
&lt;li&gt;How to apply AOP effectively in production-grade applications&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What is AOP (Aspect-Oriented Programming)?
&lt;/h2&gt;

&lt;p&gt;In simple terms — &lt;strong&gt;AOP lets you inject logic around existing methods without modifying them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of it as saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Before any method in my service layer executes, log who called it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of repeating the same code in every method, you define it once as an &lt;strong&gt;Aspect&lt;/strong&gt;, and Spring automatically applies it wherever needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Key AOP Concepts
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A module that encapsulates cross-cutting logic (e.g., LoggingAspect)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Join Point&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A point during execution (like a method call) where an aspect can be applied&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Advice&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The actual code to run (e.g., before/after method execution)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pointcut&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Expression that defines where the advice should be applied&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Weaving&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The process of linking aspects with target objects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🔍 Real-World Use Case: Logging API Calls
&lt;/h2&gt;

&lt;p&gt;Let’s build a &lt;strong&gt;logging aspect&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs every REST controller method call&lt;/li&gt;
&lt;li&gt;Prints method name, arguments, and execution time&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧩 Project Setup
&lt;/h3&gt;

&lt;p&gt;Add this dependency to your &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springframework.boot&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;spring-boot-starter-aop&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it — Spring AOP is ready to roll!&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚙️ Step 1: Create a Sample REST Controller
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/users"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/{id}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathVariable&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;InterruptedException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Thread&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sleep&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Simulate a delay&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"User with ID: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@PostMapping&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Created user: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧠 Step 2: Define a Logging Aspect
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Aspect&lt;/span&gt;
&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="nd"&gt;@Slf4j&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggingAspect&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Pointcut&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"execution(* com.example.demo..*Controller.*(..))"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;controllerMethods&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;

    &lt;span class="nd"&gt;@Around&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"controllerMethods()"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;logExecutionDetails&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProceedingJoinPoint&lt;/span&gt; &lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSignature&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;toShortString&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getArgs&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"➡️ Entering: {} with arguments {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

        &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;joinPoint&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;proceed&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;startTime&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"⬅️ Exiting: {} executed in {} ms"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ⚡ Output Example
&lt;/h3&gt;

&lt;p&gt;When you hit &lt;code&gt;/api/users/1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➡️ Entering: UserController.getUser(..) with arguments [1]
⬅️ Exiting: UserController.getUser(..) executed in 205 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat, right? You didn’t modify a single controller — yet logging is applied across all of them.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Other Practical AOP Use Cases
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Validate API tokens or check roles before method execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance Metrics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Record method execution time for Prometheus or New Relic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Transaction Auditing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Track database changes automatically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Exception Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Catch and log exceptions from service layers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Intercept method calls to apply caching dynamically&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧭 Pro Tips for Production
&lt;/h2&gt;

&lt;p&gt;✅ Keep pointcut expressions &lt;strong&gt;specific&lt;/strong&gt; — avoid &lt;code&gt;execution(* *.*(..))&lt;/code&gt; globally.&lt;br&gt;
✅ Use &lt;strong&gt;annotations&lt;/strong&gt; for flexible targeting, e.g., &lt;code&gt;@Loggable&lt;/code&gt;.&lt;br&gt;
✅ Combine with &lt;strong&gt;Spring Boot Actuator&lt;/strong&gt; for performance insights.&lt;br&gt;
✅ Prefer &lt;strong&gt;&lt;code&gt;@Around&lt;/code&gt;&lt;/strong&gt; advice — it gives full control of before/after logic.&lt;br&gt;
✅ Don’t abuse AOP — keep your core logic clear and simple.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧩 Bonus: Annotation-Driven Logging
&lt;/h2&gt;

&lt;p&gt;Let’s make it even cleaner by introducing a custom annotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Target&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ElementType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;METHOD&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Retention&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RetentionPolicy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;RUNTIME&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nd"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;Loggable&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then mark your methods like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/{id}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Loggable&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathVariable&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"User with ID: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the aspect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Pointcut&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"@annotation(com.example.demo.aop.Loggable)"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;loggableMethods&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now only methods annotated with &lt;code&gt;@Loggable&lt;/code&gt; will be intercepted.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧾 Summary
&lt;/h2&gt;

&lt;p&gt;Spring AOP is not just a fancy buzzword — it’s a &lt;strong&gt;practical engineering tool&lt;/strong&gt; that keeps your code &lt;strong&gt;clean, modular, and maintainable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use AOP to handle cross-cutting concerns elegantly&lt;/li&gt;
&lt;li&gt;Keep aspects focused and reusable&lt;/li&gt;
&lt;li&gt;Embrace annotation-based customization&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💬 What’s Next?
&lt;/h3&gt;

&lt;p&gt;In upcoming posts, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a &lt;strong&gt;performance profiler&lt;/strong&gt; with AOP&lt;/li&gt;
&lt;li&gt;Combining &lt;strong&gt;AOP + Spring Events&lt;/strong&gt; for advanced observability&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;If you found this post useful, don’t forget to ❤️ like, 🧠 save, and 🔁 share it!&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Follow me for more deep-dive Spring Boot articles every week.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>java</category>
    </item>
    <item>
      <title>🐢 Why Your JPA Transaction Slowed Down After Adding 'flush()' and 'clear()' (And How to Fix It)</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Wed, 29 Oct 2025 05:46:02 +0000</pubDate>
      <link>https://dev.to/haraf/why-your-jpa-transaction-slows-down-after-adding-flush-and-clear-and-how-to-fix-it-2506</link>
      <guid>https://dev.to/haraf/why-your-jpa-transaction-slows-down-after-adding-flush-and-clear-and-how-to-fix-it-2506</guid>
      <description>&lt;p&gt;Have you ever added &lt;code&gt;entityManager.flush()&lt;/code&gt; and &lt;code&gt;entityManager.clear()&lt;/code&gt; inside a Spring Boot JPA transaction to make deletes and inserts “reflect immediately” — only to see your performance tank?&lt;/p&gt;

&lt;p&gt;You're not alone.&lt;br&gt;
This is one of those subtle Hibernate behaviors that bites even experienced developers.&lt;/p&gt;

&lt;p&gt;Let’s unpack &lt;em&gt;why&lt;/em&gt; it happens, and what to do instead.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧩 The Real-World Scenario
&lt;/h2&gt;

&lt;p&gt;You have a Spring Boot service method like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;refreshData&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;myRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deleteByType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;newRecords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fetchNewData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;myRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newRecords&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You added &lt;code&gt;flush()&lt;/code&gt; and &lt;code&gt;clear()&lt;/code&gt; because deletes weren’t visible before inserts — and it “fixed” the logic.&lt;/p&gt;

&lt;p&gt;But now, your transaction runs 3× slower, the DB CPU spikes, and Hibernate logs show hundreds of SQL statements being executed one by one.&lt;/p&gt;

&lt;p&gt;What’s going on?&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Understanding &lt;code&gt;flush()&lt;/code&gt; and &lt;code&gt;clear()&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔹 &lt;code&gt;flush()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Tells JPA:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Send all pending SQL statements to the database &lt;strong&gt;now&lt;/strong&gt;.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Normally, Hibernate batches and optimizes SQL statements until transaction commit.&lt;br&gt;
When you call &lt;code&gt;flush()&lt;/code&gt;, it &lt;strong&gt;forces immediate execution&lt;/strong&gt; — breaking batching and hitting the database right away.&lt;/p&gt;
&lt;h3&gt;
  
  
  🔹 &lt;code&gt;clear()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Tells JPA:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Forget everything you know about the current persistence context.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This detaches &lt;em&gt;all&lt;/em&gt; managed entities.&lt;br&gt;
Hibernate now has to re-fetch them from the database if you reference them again, and you lose the in-memory first-level cache.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚠️ Why It Becomes Slow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;flush()&lt;/code&gt; executes pending SQL immediately&lt;/td&gt;
&lt;td&gt;Hibernate loses batching and optimization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;clear()&lt;/code&gt; wipes first-level cache&lt;/td&gt;
&lt;td&gt;Every next entity access triggers a new &lt;code&gt;SELECT&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same-table deletes + inserts&lt;/td&gt;
&lt;td&gt;DB locks and index contention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large transaction scope&lt;/td&gt;
&lt;td&gt;Hibernate keeps snapshots for dirty checking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cascades or orphan removal&lt;/td&gt;
&lt;td&gt;Extra SQLs during flush&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short — you gain “visibility” but lose performance and batching efficiency.&lt;/p&gt;


&lt;h2&gt;
  
  
  💡 Smarter Alternatives
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ✅ 1. Use Bulk Deletes Instead of Entity Deletes
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Modifying&lt;/span&gt;
&lt;span class="nd"&gt;@Query&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DELETE FROM MyEntity e WHERE e.type = :type"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;deleteByType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Param&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"type"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Bulk deletes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run a single SQL &lt;code&gt;DELETE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Don’t load entities into memory&lt;/li&gt;
&lt;li&gt;Don’t trigger cascade or dirty checking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perfect for refreshing data tables.&lt;/p&gt;


&lt;h3&gt;
  
  
  ✅ 2. Split the Transaction Logically
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;refreshData&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;myRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deleteByType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;insertNewRecordsInNewTx&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;propagation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Propagation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;REQUIRES_NEW&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;insertNewRecordsInNewTx&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;myRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;saveAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetchNewData&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, the delete commits before the insert starts — no need to manually &lt;code&gt;flush()&lt;/code&gt; or &lt;code&gt;clear()&lt;/code&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  ✅ 3. Use Batching for Inserts
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;application.properties&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;spring.jpa.properties.hibernate.jdbc.batch_size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;50&lt;/span&gt;
&lt;span class="py"&gt;spring.jpa.properties.hibernate.order_inserts&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;spring.jpa.properties.hibernate.order_updates&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;newRecords&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;persist&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll get &lt;strong&gt;massive performance gains&lt;/strong&gt; for large datasets.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ 4. Avoid &lt;code&gt;clear()&lt;/code&gt; Unless You Really Need It
&lt;/h3&gt;

&lt;p&gt;Instead of clearing everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;detach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This detaches only the specific entity you need, preserving most of the persistence context.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 The TL;DR Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Transaction runs slowly&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;flush()&lt;/code&gt; executes SQL immediately&lt;/td&gt;
&lt;td&gt;Avoid frequent flushes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Too many selects&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;clear()&lt;/code&gt; wipes cache&lt;/td&gt;
&lt;td&gt;Detach selectively&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete + insert on same table&lt;/td&gt;
&lt;td&gt;DB contention&lt;/td&gt;
&lt;td&gt;Split into separate transactions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High memory usage&lt;/td&gt;
&lt;td&gt;Large persistence context&lt;/td&gt;
&lt;td&gt;Batch + periodic flush/clear&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cascades killing performance&lt;/td&gt;
&lt;td&gt;Entity-based delete&lt;/td&gt;
&lt;td&gt;Use bulk delete query&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🧠 Key Takeaway
&lt;/h2&gt;

&lt;p&gt;Don’t reach for &lt;code&gt;flush()&lt;/code&gt; + &lt;code&gt;clear()&lt;/code&gt; to “fix visibility.”&lt;br&gt;
They’re low-level hammers that often break performance and caching.&lt;/p&gt;

&lt;p&gt;Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;bulk operations&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Batch inserts&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split transactions&lt;/strong&gt; when visibility matters&lt;/li&gt;
&lt;li&gt;Or use &lt;strong&gt;native SQL&lt;/strong&gt; when you’re replacing data wholesale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your Spring Boot + JPA app will thank you with faster, cleaner transactions.&lt;/p&gt;




&lt;h3&gt;
  
  
  💬 What about you?
&lt;/h3&gt;

&lt;p&gt;Have you run into &lt;code&gt;flush()&lt;/code&gt; / &lt;code&gt;clear()&lt;/code&gt; performance issues before?&lt;br&gt;
How did you handle them — batching, bulk queries, or native SQL?&lt;/p&gt;

&lt;p&gt;Drop your experience below 👇 — it helps others avoid the same trap.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Java 25: Latest Features, Examples, and Real-World Use Cases</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Tue, 30 Sep 2025 05:10:31 +0000</pubDate>
      <link>https://dev.to/haraf/java-25-latest-features-examples-and-real-world-use-cases-43bd</link>
      <guid>https://dev.to/haraf/java-25-latest-features-examples-and-real-world-use-cases-43bd</guid>
      <description>&lt;h1&gt;
  
  
  Java 25: Latest Features, Examples, and Real-World Use Cases
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Everything you need to know ab&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fer5vh310hrcwxvtarsvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fer5vh310hrcwxvtarsvl.png" alt="Java 25: Latest Features, Examples, and Real-World Use Cases" width="800" height="800"&gt;&lt;/a&gt;out the newest Java release&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; &lt;code&gt;java&lt;/code&gt;, &lt;code&gt;programming&lt;/code&gt;, &lt;code&gt;tutorial&lt;/code&gt;, &lt;code&gt;java25&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;Java 25 is here — and as the latest &lt;strong&gt;LTS (Long-Term Support)&lt;/strong&gt; release, it’s packed with language features, JVM improvements, and new APIs that make Java more expressive, performant, and cloud-ready.&lt;/p&gt;

&lt;p&gt;In this post, we’ll cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 New and finalized features in Java 25&lt;/li&gt;
&lt;li&gt;🧑‍💻 Practical code examples&lt;/li&gt;
&lt;li&gt;🌍 Real-world scenarios where they shine&lt;/li&gt;
&lt;li&gt;🔧 Migration tips and best practices&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  1. Compact Source Files &amp;amp; Instance Main Methods (JEP 512)
&lt;/h2&gt;

&lt;p&gt;You can now write minimal Java programs &lt;strong&gt;without boilerplate&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, Java 25!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;code&gt;class&lt;/code&gt;, no &lt;code&gt;public static void main&lt;/code&gt;. Just code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teaching / learning Java&lt;/li&gt;
&lt;li&gt;Quick prototypes and utilities&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Flexible Constructor Bodies (JEP 513)
&lt;/h2&gt;

&lt;p&gt;Constructors are now more flexible: you can add validation or setup &lt;strong&gt;before&lt;/strong&gt; delegating with &lt;code&gt;super(...)&lt;/code&gt; or &lt;code&gt;this(...)&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Person&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Age must be &amp;gt;= 0"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input validation&lt;/li&gt;
&lt;li&gt;Cleaner initialization logic&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Compact Object Headers (JEP 519)
&lt;/h2&gt;

&lt;p&gt;Java objects now have &lt;strong&gt;smaller headers&lt;/strong&gt;, saving memory and improving cache locality.&lt;/p&gt;

&lt;p&gt;Enable with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-XX:+UseCompactObjectHeaders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apps with lots of small objects (DTOs, domain models)&lt;/li&gt;
&lt;li&gt;Memory-sensitive microservices&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Generational Shenandoah GC (JEP 521)
&lt;/h2&gt;

&lt;p&gt;Shenandoah garbage collector now supports &lt;strong&gt;generational mode&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; Most objects die young — separating young vs old reduces pause times and improves throughput.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Ahead-of-Time (AOT) Method Profiling (JEP 515)
&lt;/h2&gt;

&lt;p&gt;The JVM can now &lt;strong&gt;profile hot methods ahead of time&lt;/strong&gt; and reuse that info across runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster warm-up&lt;/li&gt;
&lt;li&gt;Better performance for microservices and serverless apps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Java Flight Recorder (JFR) Enhancements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cooperative sampling&lt;/li&gt;
&lt;li&gt;More detailed method timing &amp;amp; tracing&lt;/li&gt;
&lt;li&gt;Experimental CPU-time profiling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Production-grade observability with lower overhead.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Pattern Matching for Primitive Types (JEP 507 — Preview)
&lt;/h2&gt;

&lt;p&gt;Pattern matching now works for primitives inside &lt;code&gt;switch&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Number&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"positive int "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"non-positive int "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"double "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"other number"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;};&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Cleaner, safer branching without boxing/unboxing.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Module Import Declarations (JEP 511 — Preview)
&lt;/h2&gt;

&lt;p&gt;Declare module dependencies directly in source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;module&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;module&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Improves clarity when working with the module system.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Scoped Values (JEP 506 — Preview)
&lt;/h2&gt;

&lt;p&gt;A lightweight alternative to &lt;code&gt;ThreadLocal&lt;/code&gt;, especially useful with &lt;strong&gt;virtual threads&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Pass immutable context data across async boundaries without leaks.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Key Derivation Function API (JEP 510 — Preview)
&lt;/h2&gt;

&lt;p&gt;Standardizes cryptographic key derivation (e.g., HKDF, Argon2).&lt;br&gt;
&lt;strong&gt;Use case:&lt;/strong&gt; Security-sensitive systems needing deterministic but secure key material.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Removal of 32-bit x86 Port (JEP 503)
&lt;/h2&gt;

&lt;p&gt;Java 25 now runs only on &lt;strong&gt;64-bit platforms&lt;/strong&gt;. Time to retire that old 32-bit code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Scenarios
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Microservices&lt;/td&gt;
&lt;td&gt;AOT profiling&lt;/td&gt;
&lt;td&gt;Faster startup, less warm-up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory-heavy apps&lt;/td&gt;
&lt;td&gt;Compact headers + Shenandoah&lt;/td&gt;
&lt;td&gt;Lower footprint, smoother GC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event-driven systems&lt;/td&gt;
&lt;td&gt;Pattern matching + sealed types&lt;/td&gt;
&lt;td&gt;Safer, cleaner dispatch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Async workflows&lt;/td&gt;
&lt;td&gt;Scoped values&lt;/td&gt;
&lt;td&gt;Context propagation in virtual threads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;KDF API&lt;/td&gt;
&lt;td&gt;Stronger, standard crypto primitives&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Migration Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Start with &lt;strong&gt;finalized features&lt;/strong&gt; (compact files, flexible constructors, compact headers).&lt;/li&gt;
&lt;li&gt;Experiment with &lt;strong&gt;preview features&lt;/strong&gt; in isolated modules.&lt;/li&gt;
&lt;li&gt;Benchmark workloads after enabling GC/AOT options.&lt;/li&gt;
&lt;li&gt;Update build pipelines for 64-bit only support.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Java 25 is more than “just another release.”&lt;br&gt;
It lowers boilerplate, improves runtime performance, and makes Java more cloud-friendly.&lt;/p&gt;

&lt;p&gt;If you’re on Java 17 or 21, now’s the time to explore Java 25 — and start adopting its new features incrementally.&lt;/p&gt;




&lt;p&gt;👉 What’s your favorite Java 25 feature? Planning to adopt it in production? Let me know in the comments!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🐳 Docker &amp; Docker Compose for Beginners: Full Guide + Real Project Example</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Wed, 25 Jun 2025 10:03:49 +0000</pubDate>
      <link>https://dev.to/haraf/docker-docker-compose-for-beginners-full-guide-real-project-example-b7</link>
      <guid>https://dev.to/haraf/docker-docker-compose-for-beginners-full-guide-real-project-example-b7</guid>
      <description>&lt;p&gt;Whether you’re a backend developer, DevOps enthusiast, or just getting into microservices, &lt;strong&gt;Docker&lt;/strong&gt; is one of the most essential tools in the modern development toolbox.&lt;/p&gt;

&lt;p&gt;This guide will walk you through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Docker &amp;amp; Docker Compose are&lt;/li&gt;
&lt;li&gt;Why Docker became so popular&lt;/li&gt;
&lt;li&gt;How to install Docker&lt;/li&gt;
&lt;li&gt;How to use Docker &amp;amp; Docker Compose&lt;/li&gt;
&lt;li&gt;Real-world project: Node.js + MongoDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive in 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 What is Docker?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Docker&lt;/strong&gt; is a platform for packaging applications into &lt;strong&gt;containers&lt;/strong&gt; — lightweight, portable units that bundle your app with its dependencies.&lt;/p&gt;

&lt;p&gt;Imagine this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It works on my machine" – Docker makes that &lt;strong&gt;your reality everywhere.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each container includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code&lt;/li&gt;
&lt;li&gt;Runtime (e.g., Node.js, Java)&lt;/li&gt;
&lt;li&gt;Libraries&lt;/li&gt;
&lt;li&gt;Environment/configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So your app runs the same on &lt;strong&gt;any system&lt;/strong&gt;, cloud, or CI/CD pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Why Docker Became So Popular
&lt;/h2&gt;

&lt;p&gt;Docker took over the world for several key reasons:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Lightning Fast&lt;/strong&gt; – Containers start in milliseconds vs full VMs&lt;br&gt;
✅ &lt;strong&gt;Environment Consistency&lt;/strong&gt; – Same behavior in dev, staging, and prod&lt;br&gt;
✅ &lt;strong&gt;DevOps &amp;amp; CI/CD Friendly&lt;/strong&gt; – Works seamlessly with GitHub Actions, Jenkins, GitLab CI&lt;br&gt;
✅ &lt;strong&gt;Perfect for Microservices&lt;/strong&gt; – Each service in its own container&lt;br&gt;
✅ &lt;strong&gt;Portable&lt;/strong&gt; – Works on Windows, Linux, Mac, cloud platforms&lt;br&gt;
✅ &lt;strong&gt;Vibrant Ecosystem&lt;/strong&gt; – Docker Hub provides 100,000+ ready-to-use images&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚙️ Docker vs Traditional Deployment
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Traditional Deployment&lt;/th&gt;
&lt;th&gt;Docker-Based Deployment&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;Manual setup, often inconsistent&lt;/td&gt;
&lt;td&gt;One-line setup (&lt;code&gt;docker run&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment conflicts&lt;/td&gt;
&lt;td&gt;Very common&lt;/td&gt;
&lt;td&gt;Fully isolated per container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Portability&lt;/td&gt;
&lt;td&gt;OS/Env dependent&lt;/td&gt;
&lt;td&gt;Runs anywhere Docker is installed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling services&lt;/td&gt;
&lt;td&gt;Hard &amp;amp; manual&lt;/td&gt;
&lt;td&gt;Easy with &lt;code&gt;docker-compose&lt;/code&gt; or K8s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dev → Staging → Prod&lt;/td&gt;
&lt;td&gt;Error-prone&lt;/td&gt;
&lt;td&gt;Consistent containers everywhere&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  🧰 How to Install Docker &amp;amp; Docker Compose
&lt;/h2&gt;
&lt;h3&gt;
  
  
  🔹 1. Install Docker
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to: &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;https://www.docker.com/products/docker-desktop&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Download for your OS (Windows, macOS, Linux)&lt;/li&gt;
&lt;li&gt;Follow installer instructions&lt;/li&gt;
&lt;li&gt;After install, run:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Docker version 24.x.x, build abcdef
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔹 2. Docker Compose (usually pre-installed)
&lt;/h3&gt;

&lt;p&gt;Check with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it shows the version, you're good to go!&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 Real Example: Node.js + MongoDB with Docker Compose
&lt;/h2&gt;

&lt;p&gt;Let’s build a simple project that runs a Node.js API connected to MongoDB — all inside Docker.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧱 Project Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker-node-mongo-app/
├── app/
│   ├── server.js
│   └── package.json
├── Dockerfile
└── docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ✏️ Step 1: Node.js Code (&lt;code&gt;app/server.js&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongoose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongoose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;mongoose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb://mongo:27017/mydb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;useNewUrlParser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;useUnifiedTopology&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from Dockerized Node.js + MongoDB!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running on http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ✏️ Step 2: &lt;code&gt;app/package.json&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"docker-node-mongo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node server.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"express"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.18.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mongoose"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^7.2.2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🐳 Step 3: &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app/package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🛠 Step 4: &lt;code&gt;docker-compose.yml&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mongo&lt;/span&gt;

  &lt;span class="na"&gt;mongo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongo&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;27017:27017"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mongo-data:/data/db&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mongo-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ▶️ How to Run the Project
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open terminal in your project root.&lt;/li&gt;
&lt;li&gt;Run the following:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Visit:
📍 &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;
You’ll see:
&lt;code&gt;Hello from Dockerized Node.js + MongoDB!&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🧹 How to Stop &amp;amp; Clean Up
&lt;/h2&gt;

&lt;p&gt;To stop the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To remove the volume data as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose down &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Recap
&lt;/h2&gt;

&lt;p&gt;By now, you've learned:&lt;/p&gt;

&lt;p&gt;✅ What Docker and Docker Compose are&lt;br&gt;
✅ Why Docker became a standard in modern development&lt;br&gt;
✅ How to install and check Docker setup&lt;br&gt;
✅ How to containerize an app&lt;br&gt;
✅ How to run multi-container apps with Compose&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 What's Next?
&lt;/h2&gt;

&lt;p&gt;You can now dockerize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python Flask/Django apps&lt;/li&gt;
&lt;li&gt;Spring Boot + PostgreSQL apps&lt;/li&gt;
&lt;li&gt;React/Next.js with NGINX&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>docker</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🛡️ Mastering Java Encryption in 2025: Modern Methods, Best Practices &amp; Real-World Examples</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Mon, 09 Jun 2025 05:33:43 +0000</pubDate>
      <link>https://dev.to/haraf/mastering-java-encryption-in-2025-modern-methods-best-practices-real-world-examples-3hfk</link>
      <guid>https://dev.to/haraf/mastering-java-encryption-in-2025-modern-methods-best-practices-real-world-examples-3hfk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Encryption is no longer optional—it's essential. In 2025, mastering encryption in Java means staying ahead of vulnerabilities, avoiding outdated APIs, and designing with security-first principles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you're a backend developer, architect, or security-conscious coder, this guide will help you write clean, modern, and secure encryption code in Java.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Why This Guide?
&lt;/h2&gt;

&lt;p&gt;Legacy systems still use insecure methods like ECB mode or outdated algorithms like MD5. Meanwhile, cloud-native, distributed apps demand secure transmission, storage, and user data handling. This post focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modern Java encryption libraries&lt;/li&gt;
&lt;li&gt;Best practices for symmetric/asymmetric encryption&lt;/li&gt;
&lt;li&gt;Practical examples with AES-GCM, RSA-OAEP, and more&lt;/li&gt;
&lt;li&gt;Real-world scenarios (e.g., encrypting passwords, payloads, tokens)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔐 1. Symmetric Encryption (AES-GCM FTW)
&lt;/h2&gt;

&lt;p&gt;AES is the industry standard, but in 2025, ECB is dead. GCM (Galois/Counter Mode) is preferred for its &lt;strong&gt;authenticated encryption&lt;/strong&gt;—it ensures &lt;strong&gt;integrity and confidentiality&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Best Practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use AES-256 with GCM&lt;/li&gt;
&lt;li&gt;Generate IVs randomly&lt;/li&gt;
&lt;li&gt;Never reuse IVs with the same key&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💡 Example: AES-GCM Encryption
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Cipher&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AES/GCM/NoPadding"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SecureRandom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstanceStrong&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;generateSeed&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 96-bit IV&lt;/span&gt;
&lt;span class="nc"&gt;GCMParameterSpec&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GCMParameterSpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iv&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENCRYPT_MODE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secretKey&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;ciphertext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doFinal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plaintext&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔑 2. Asymmetric Encryption (RSA-OAEP)
&lt;/h2&gt;

&lt;p&gt;RSA is still popular for encrypting small data (like keys or tokens). But &lt;strong&gt;PKCS#1 v1.5&lt;/strong&gt; is obsolete. In 2025, go with &lt;strong&gt;RSA-OAEP&lt;/strong&gt; for padding and forward security.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Best Practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use RSA with OAEP (Optimal Asymmetric Encryption Padding)&lt;/li&gt;
&lt;li&gt;Minimum 2048-bit keys (3072+ recommended)&lt;/li&gt;
&lt;li&gt;Use for encrypting symmetric keys, not large data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💡 Example: RSA-OAEP
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;Cipher&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"RSA/ECB/OAEPWithSHA-256AndMGF1Padding"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ENCRYPT_MODE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;publicKey&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;doFinal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secretKeyBytes&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧂 3. Password Encryption ≠ Password Hashing
&lt;/h2&gt;

&lt;p&gt;Don’t encrypt passwords. &lt;strong&gt;Hash them&lt;/strong&gt; using a strong key-derivation function:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Best Practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;PBKDF2&lt;/strong&gt;, &lt;strong&gt;BCrypt&lt;/strong&gt;, &lt;strong&gt;SCrypt&lt;/strong&gt;, or &lt;strong&gt;Argon2&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Store salt separately or alongside the hash&lt;/li&gt;
&lt;li&gt;Never roll your own crypto&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💡 Example: PBKDF2 Hashing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;SecretKeyFactory&lt;/span&gt; &lt;span class="n"&gt;skf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SecretKeyFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PBKDF2WithHmacSHA512"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;KeySpec&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PBEKeySpec&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;65536&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;SecretKey&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;skf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;generateSecret&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEncoded&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 4. Java Libraries You Should Be Using
&lt;/h2&gt;

&lt;p&gt;In 2025, built-in Java crypto is solid but &lt;strong&gt;not always ergonomic&lt;/strong&gt;. Consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔐 &lt;strong&gt;Bouncy Castle&lt;/strong&gt; – Advanced crypto primitives&lt;/li&gt;
&lt;li&gt;🔒 &lt;strong&gt;Tink (by Google)&lt;/strong&gt; – Modern encryption with safe defaults&lt;/li&gt;
&lt;li&gt;🧰 &lt;strong&gt;Spring Security Crypto&lt;/strong&gt; – For secure password encoding, token handling&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 5. Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🧾 Encrypting JSON Payloads
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AES-GCM for payload encryption&lt;/li&gt;
&lt;li&gt;Include IV and authentication tag&lt;/li&gt;
&lt;li&gt;Base64 encode before transmission&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔄 Token Encryption (JWT)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Avoid symmetric keys unless necessary&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;JWE (JSON Web Encryption)&lt;/strong&gt; with RSA-OAEP + AES-GCM&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📂 File Encryption
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stream-based AES encryption for large files&lt;/li&gt;
&lt;li&gt;Split metadata and ciphertext&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Pro Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔄 Rotate keys periodically&lt;/li&gt;
&lt;li&gt;📜 Use key stores (e.g., JCEKS, PKCS12)&lt;/li&gt;
&lt;li&gt;🚫 Never log sensitive keys or plaintext&lt;/li&gt;
&lt;li&gt;🔍 Audit your encryption flow regularly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📚 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Encryption in Java has evolved—but too many apps still use insecure defaults. Mastering encryption means &lt;strong&gt;understanding the algorithms&lt;/strong&gt;, &lt;strong&gt;using proper libraries&lt;/strong&gt;, and &lt;strong&gt;staying updated with best practices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 If you found this useful, drop a ❤️ or follow me for more Java security tips.&lt;br&gt;
🔗 &lt;a href="https://javatech.hashnode.dev/mastering-java-encryption-in-2025-modern-methods-best-practices-and-real-world-examples" rel="noopener noreferrer"&gt;Full version with more examples on Hashnode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>beginners</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Microservices: Mastering the Circuit Breaker Pattern with Real Examples</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Fri, 30 May 2025 05:01:51 +0000</pubDate>
      <link>https://dev.to/haraf/microservices-mastering-the-circuit-breaker-pattern-with-real-examples-2a4l</link>
      <guid>https://dev.to/haraf/microservices-mastering-the-circuit-breaker-pattern-with-real-examples-2a4l</guid>
      <description>&lt;p&gt;When building resilient microservices, failure is not just possible—it's inevitable. In a distributed architecture, one slow or failing service can cause a chain reaction of degraded performance and outages. This is where the &lt;strong&gt;Circuit Breaker Pattern&lt;/strong&gt; becomes essential.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 What is the Circuit Breaker Pattern?
&lt;/h2&gt;

&lt;p&gt;The Circuit Breaker Pattern is a design pattern used to detect failures and encapsulate logic to prevent a network or service failure from constantly recurring during maintenance, temporary downtime, or unexpected system problems.&lt;/p&gt;

&lt;p&gt;Think of it like a power circuit breaker: when the system detects too many failures, it "breaks" the circuit and stops sending requests to the failing service until it becomes healthy again.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔪 Why Do You Need a Circuit Breaker?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prevent cascading failures&lt;/li&gt;
&lt;li&gt;Improve fault tolerance&lt;/li&gt;
&lt;li&gt;Gracefully degrade functionality&lt;/li&gt;
&lt;li&gt;Increase overall system stability&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧰 Core States of a Circuit Breaker
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Closed&lt;/strong&gt;: Everything is normal; all requests go through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open&lt;/strong&gt;: The circuit is "tripped" after failures; all requests are blocked for a cool-down period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Half-Open&lt;/strong&gt;: A limited number of test requests are allowed to check if the service has recovered.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📊 Real-World Use Case
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario:
&lt;/h3&gt;

&lt;p&gt;An eCommerce platform has a Product Service calling a remote Inventory Service. If the Inventory Service becomes unresponsive, the entire checkout flow gets delayed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem:
&lt;/h3&gt;

&lt;p&gt;No timeout or fallback mechanism = bad user experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution:
&lt;/h3&gt;

&lt;p&gt;Implement a Circuit Breaker on the Product Service when calling Inventory Service.&lt;/p&gt;




&lt;h2&gt;
  
  
  📄 Example with Resilience4j (Spring Boot)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Maven Dependency
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.github.resilience4j&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;resilience4j-spring-boot3&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;resilience4j&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;circuitbreaker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;instances&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;inventoryService&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;registerHealthIndicator&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;slidingWindowSize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
        &lt;span class="na"&gt;failureRateThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
        &lt;span class="na"&gt;waitDurationInOpenState&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
        &lt;span class="na"&gt;permittedNumberOfCallsInHalfOpenState&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Service Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@CircuitBreaker&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"inventoryService"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallbackMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"fallbackInventory"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Inventory&lt;/span&gt; &lt;span class="nf"&gt;checkInventory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;restTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getForObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://inventory-service/api/check/"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Inventory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Inventory&lt;/span&gt; &lt;span class="nf"&gt;fallbackInventory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fallback triggered for product {}: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Inventory&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fallback"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔄 State Transitions Illustrated
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Service is healthy → &lt;strong&gt;Closed&lt;/strong&gt; (normal traffic)&lt;/li&gt;
&lt;li&gt;Too many failures detected → &lt;strong&gt;Open&lt;/strong&gt; (requests blocked)&lt;/li&gt;
&lt;li&gt;After &lt;code&gt;waitDurationInOpenState&lt;/code&gt; → &lt;strong&gt;Half-Open&lt;/strong&gt; (limited test traffic)&lt;/li&gt;
&lt;li&gt;If test succeeds → back to &lt;strong&gt;Closed&lt;/strong&gt;; else → &lt;strong&gt;Open&lt;/strong&gt; again&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🌟 Bonus: Integrating with WebClient (Reactive)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Customizer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReactiveResilience4JCircuitBreakerFactory&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;defaultCustomizer&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configureDefault&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Resilience4JConfigBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;circuitBreakerConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CircuitBreakerConfig&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ofDefaults&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;callInventoryReactive&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reactiveCircuitBreakerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inventoryService"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;webClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/check/"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;productId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;retrieve&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;bodyToMono&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;throwable&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;just&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fallback Response"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Production Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Configure &lt;strong&gt;timeouts&lt;/strong&gt; separately (Circuit Breaker ≠ timeout)&lt;/li&gt;
&lt;li&gt;Combine with &lt;strong&gt;rate limiting&lt;/strong&gt; and &lt;strong&gt;bulkheads&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Monitor with &lt;strong&gt;metrics and dashboards&lt;/strong&gt; (e.g., Micrometer + Prometheus)&lt;/li&gt;
&lt;li&gt;Fine-tune thresholds per service&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;In microservices architectures demand resilience. Implementing the Circuit Breaker Pattern isn't optional—it's foundational. Using libraries like Resilience4j or Hystrix (deprecated), we can build self-healing systems that withstand real-world chaos.&lt;/p&gt;

&lt;p&gt;Which failure pattern has caused your microservices to crash? Share below and let's discuss how to bulletproof your system! #microservices #springboot #resilience4j #devops&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>java</category>
    </item>
    <item>
      <title>Spring Boot Anti-Patterns Killing Your App Performance in 2025 (With Real Fixes &amp; Explanations)</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Thu, 29 May 2025 03:41:38 +0000</pubDate>
      <link>https://dev.to/haraf/spring-boot-anti-patterns-killing-your-app-performance-in-2025-with-real-fixes-explanations-2p05</link>
      <guid>https://dev.to/haraf/spring-boot-anti-patterns-killing-your-app-performance-in-2025-with-real-fixes-explanations-2p05</guid>
      <description>&lt;p&gt;Spring Boot helps developers move fast — but bad patterns kill performance, scalability, and maintainability silently.&lt;/p&gt;

&lt;p&gt;Here’s a 2025-ready breakdown of &lt;strong&gt;real anti-patterns&lt;/strong&gt;, &lt;strong&gt;why they’re dangerous&lt;/strong&gt;, and &lt;strong&gt;how to fix them with clean, performant code&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 1. Overusing &lt;code&gt;@Transactional&lt;/code&gt; on Everything
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 Problem:
&lt;/h3&gt;

&lt;p&gt;Even &lt;strong&gt;read-only queries&lt;/strong&gt; run inside unnecessary transactions, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lock resources&lt;/li&gt;
&lt;li&gt;Block threads&lt;/li&gt;
&lt;li&gt;Add overhead to the database&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readOnly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getAllUsers&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findAll&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;readOnly = true&lt;/code&gt; hint allows the database to &lt;strong&gt;optimize the query plan&lt;/strong&gt;, avoids &lt;strong&gt;write locks&lt;/strong&gt;, and improves &lt;strong&gt;throughput&lt;/strong&gt; for concurrent reads.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 2. Business Logic in Controllers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;badRequest&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 Problem:
&lt;/h3&gt;

&lt;p&gt;Mixing logic with HTTP code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard to test&lt;/li&gt;
&lt;li&gt;Difficult to scale&lt;/li&gt;
&lt;li&gt;Breaks SRP (Single Responsibility Principle)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Underage"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getName&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAge&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;Separating logic into a &lt;strong&gt;service layer&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Promotes clean architecture&lt;/li&gt;
&lt;li&gt;Enables reuse across APIs or scheduled jobs&lt;/li&gt;
&lt;li&gt;Makes unit testing easier&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ 3. Blocking Calls in Reactive Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/pdf"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;just&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;createHeavyPdf&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// Blocking!&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 Problem:
&lt;/h3&gt;

&lt;p&gt;Calling blocking I/O (e.g., file, DB, network) on Netty threads &lt;strong&gt;breaks the reactive model&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/pdf"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Mono&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromCallable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;createHeavyPdf&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
               &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subscribeOn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Schedulers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;boundedElastic&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Schedulers.boundedElastic()&lt;/code&gt; offloads blocking tasks to a separate thread pool — &lt;strong&gt;keeping the event loop free&lt;/strong&gt; for I/O-bound processing.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 4. Not Using Virtual Threads
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Executor&lt;/span&gt; &lt;span class="nf"&gt;asyncExecutor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newFixedThreadPool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Limited concurrency&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Fix (Java 22+):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Executor&lt;/span&gt; &lt;span class="nf"&gt;asyncExecutor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Virtual threads&lt;/strong&gt; are lightweight, memory-efficient, and allow &lt;strong&gt;thousands of concurrent tasks&lt;/strong&gt; without blocking kernel threads — &lt;strong&gt;perfect for high-throughput apps&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 5. Overusing &lt;code&gt;EntityManager&lt;/code&gt; Manually
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@PersistenceContext&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;EntityManager&lt;/span&gt; &lt;span class="n"&gt;em&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;em&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FROM User"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;getResultList&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 Problem:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Manual queries are error-prone.&lt;/li&gt;
&lt;li&gt;You miss Spring Data’s features (pagination, filters, query derivation).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Repository&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JpaRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findByStatus&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;Spring Data JPA is optimized, tested, and handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transactions&lt;/li&gt;
&lt;li&gt;Paging&lt;/li&gt;
&lt;li&gt;Dynamic queries
Better abstraction = &lt;strong&gt;fewer bugs, more performance&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ 6. &lt;code&gt;@Cacheable&lt;/code&gt; Without Expiry
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Cacheable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"products"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;productRepo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 Problem:
&lt;/h3&gt;

&lt;p&gt;Caches can grow &lt;strong&gt;unbounded&lt;/strong&gt;, consuming memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;CacheManager&lt;/span&gt; &lt;span class="nf"&gt;cacheManager&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;CaffeineCacheManager&lt;/span&gt; &lt;span class="n"&gt;cacheManager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CaffeineCacheManager&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"products"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;cacheManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCaffeine&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Caffeine&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;expireAfterWrite&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;TimeUnit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;MINUTES&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maximumSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cacheManager&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;Adds &lt;strong&gt;TTL (Time to Live)&lt;/strong&gt; and &lt;strong&gt;max entries&lt;/strong&gt; — preventing memory leaks and stale data. Caffeine is ultra-fast and supports async refresh.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 7. Default Tomcat Thread Pool
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Default max-threads = 200
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔍 Problem:
&lt;/h3&gt;

&lt;p&gt;Your API could &lt;strong&gt;underperform under high load&lt;/strong&gt; — threads wait in queue, requests time out.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Fix:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;server.tomcat.max-threads&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;500&lt;/span&gt;
&lt;span class="py"&gt;server.tomcat.accept-count&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;100&lt;/span&gt;
&lt;span class="py"&gt;server.connection-timeout&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;max-threads&lt;/code&gt;: how many concurrent requests can be served&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;accept-count&lt;/code&gt;: queued connections&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;connection-timeout&lt;/code&gt;: prevents hanging sockets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tuning Tomcat = faster concurrency handling&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 8. Overlapping Scheduled Jobs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Scheduled&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fixedRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendEmails&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Takes 10s to run = jobs overlap = CPU spike&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Fix with ShedLock:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Scheduled&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fixedRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@SchedulerLock&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"emailJob"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lockAtLeastFor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"PT5S"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendEmails&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Run once, skip overlap&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;ShedLock uses distributed locks (e.g., Redis, DB) to &lt;strong&gt;prevent concurrent job runs&lt;/strong&gt; — crucial for long-running tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ 9. No Observability
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Anti-Pattern:
&lt;/h3&gt;

&lt;p&gt;No logs, no metrics, no traces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// How do we know if it’s slow? 🤷&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Fix:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Micrometer + Prometheus + Grafana&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.micrometer&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;micrometer-registry-prometheus&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;management.endpoints.web.exposure.include&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;health,info,metrics,prometheus&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🛠️ Explanation:
&lt;/h3&gt;

&lt;p&gt;Gives &lt;strong&gt;real-time visibility&lt;/strong&gt; into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API latency&lt;/li&gt;
&lt;li&gt;JVM memory&lt;/li&gt;
&lt;li&gt;Cache hit/miss&lt;/li&gt;
&lt;li&gt;DB time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bonus: Add &lt;strong&gt;OpenTelemetry&lt;/strong&gt; for distributed tracing across microservices.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Even in 2025, &lt;strong&gt;these old habits still slow down modern Spring Boot apps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;✅ Virtual threads&lt;br&gt;
✅ Reactive practices&lt;br&gt;
✅ Caching strategies&lt;br&gt;
✅ Observability&lt;br&gt;
✅ Clean architecture&lt;/p&gt;

&lt;p&gt;Start reviewing your codebase for these traps — and refactor for &lt;strong&gt;performance, scalability, and developer sanity&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 What Anti-Pattern Do You See Most?
&lt;/h2&gt;

&lt;p&gt;Comment below with real issues you've solved (or still suffer with). Let’s build a community playbook to clean up enterprise Spring Boot!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>java</category>
    </item>
    <item>
      <title>Understanding TransactionEventListener in Spring Boot: Use Cases, Real-Time Examples, and Challenges</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Wed, 28 May 2025 08:27:34 +0000</pubDate>
      <link>https://dev.to/haraf/understanding-transactioneventlistener-in-spring-boot-use-cases-real-time-examples-and-4aof</link>
      <guid>https://dev.to/haraf/understanding-transactioneventlistener-in-spring-boot-use-cases-real-time-examples-and-4aof</guid>
      <description>&lt;p&gt;Spring Boot provides a rich programming model to handle transactional events efficiently. One such powerful feature is the &lt;strong&gt;&lt;code&gt;TransactionEventListener&lt;/code&gt;&lt;/strong&gt;, which allows you to react to transaction lifecycle events like commit or rollback, enabling clean separation of concerns and robust transaction-aware event handling.&lt;/p&gt;

&lt;p&gt;In this post, we'll dive deep into what &lt;code&gt;TransactionEventListener&lt;/code&gt; is, how it works, explore real-world scenarios where it shines, and also discuss its limitations and challenges.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is &lt;code&gt;TransactionEventListener&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;TransactionEventListener&lt;/code&gt; is an annotation in Spring Framework (since 5.2) that lets you listen to events &lt;strong&gt;within the context of a transaction&lt;/strong&gt;. It means your event handling logic can be triggered &lt;strong&gt;only after a transaction successfully commits&lt;/strong&gt;, or when it rolls back, providing precise control over event-driven behavior tied to transactional outcomes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why use &lt;code&gt;TransactionEventListener&lt;/code&gt;?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ensure consistency:&lt;/strong&gt; Trigger events only after the transaction commits successfully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid side effects on rollback:&lt;/strong&gt; Prevent events from firing if the transaction fails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve decoupling:&lt;/strong&gt; Separate business logic and event handling that depends on transactional state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support asynchronous processing:&lt;/strong&gt; Combine with async event handling while ensuring transaction completion.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;Here's a simple example to illustrate usage in Spring Boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderEventListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handleOrderCreated&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderCreatedEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Order Created Event received for order: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="c1"&gt;// Perform actions that should only occur after successful commit,&lt;/span&gt;
        &lt;span class="c1"&gt;// like sending notification emails or updating caches.&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Controlling the Transaction Phase
&lt;/h2&gt;

&lt;p&gt;By default, &lt;code&gt;@TransactionalEventListener&lt;/code&gt; listens &lt;strong&gt;after commit&lt;/strong&gt; (&lt;code&gt;AFTER_COMMIT&lt;/code&gt;). You can customize it using the &lt;code&gt;phase&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TransactionPhase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_ROLLBACK&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handleRollback&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderCreatedEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Transaction rolled back for order: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="c1"&gt;// Compensate or log rollback-specific actions here.&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BEFORE_COMMIT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AFTER_COMMIT&lt;/code&gt; (default)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AFTER_ROLLBACK&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AFTER_COMPLETION&lt;/code&gt; (after commit or rollback)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Real-Time Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Sending Confirmation Emails After Order Creation
&lt;/h3&gt;

&lt;p&gt;You want to send confirmation emails &lt;strong&gt;only if the order transaction commits successfully&lt;/strong&gt;, ensuring customers aren't notified for failed transactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailNotificationListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendOrderConfirmation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderCreatedEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;emailService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendOrderConfirmation&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCustomerEmail&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Updating Cache Post Transaction Commit
&lt;/h3&gt;

&lt;p&gt;You can refresh cache entries or invalidate cached data &lt;strong&gt;after successful updates&lt;/strong&gt; in your DB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CacheUpdateListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;refreshProductCache&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ProductUpdatedEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cacheManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;evict&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"products"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getProductId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Compensating Actions on Rollback
&lt;/h3&gt;

&lt;p&gt;If a transaction fails, you might want to &lt;strong&gt;log or trigger compensating actions&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RollbackListener&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@TransactionalEventListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TransactionPhase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;AFTER_ROLLBACK&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;handleOrderFailure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OrderCreatedEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Transaction rolled back for order id: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrderId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;auditService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;logFailedOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How to Publish Transactional Events?
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;ApplicationEventPublisher&lt;/code&gt; inside your service methods annotated with &lt;code&gt;@Transactional&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ApplicationEventPublisher&lt;/span&gt; &lt;span class="n"&gt;publisher&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OrderService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ApplicationEventPublisher&lt;/span&gt; &lt;span class="n"&gt;publisher&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publisher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;publisher&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Transactional&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;publisher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;publishEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OrderCreatedEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCustomerEmail&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Potential Challenges and Limitations
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;TransactionEventListener&lt;/code&gt; is powerful, here are some points to consider:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Event Ordering and Transaction Boundaries&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Events are triggered &lt;strong&gt;only after transaction boundaries&lt;/strong&gt;, so if your event handler logic requires real-time processing before commit, this might not suit your needs.&lt;/li&gt;
&lt;li&gt;If multiple events rely on each other, managing their order and dependencies can be tricky.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Long-running or Blocking Event Handlers&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Since event handlers run &lt;strong&gt;within the transaction context&lt;/strong&gt; or immediately after commit, long-running or blocking operations (like sending emails or calling external APIs) can slow down transaction processing.&lt;/li&gt;
&lt;li&gt;To avoid this, you can combine &lt;code&gt;@TransactionalEventListener&lt;/code&gt; with &lt;code&gt;@Async&lt;/code&gt; to handle events asynchronously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Event Handling on Rollbacks&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Events fired on rollback (&lt;code&gt;AFTER_ROLLBACK&lt;/code&gt;) should be used carefully, as the system is in an error state.&lt;/li&gt;
&lt;li&gt;You should avoid triggering further database changes here to prevent inconsistent states.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Complexity in Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Testing transaction-aware event listeners can be complex since you need to simulate transaction commit and rollback behaviors in test scenarios.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;@Transactional&lt;/code&gt; tests and Spring's testing support carefully.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Limited Support for Nested Transactions&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If you use nested transactions or multiple transaction managers, the behavior of &lt;code&gt;TransactionEventListener&lt;/code&gt; may vary or not work as expected.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;@TransactionalEventListener&lt;/code&gt; for &lt;strong&gt;transaction-aware event handling&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose the right &lt;code&gt;phase&lt;/code&gt; depending on your business logic.&lt;/li&gt;
&lt;li&gt;Ensure events that trigger side effects occur &lt;strong&gt;only after successful commits&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Be cautious of long-running event handlers and consider asynchronous processing.&lt;/li&gt;
&lt;li&gt;Test transaction event listeners thoroughly to cover commit and rollback scenarios.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;TransactionEventListener&lt;/code&gt; in Spring Boot enables elegant, transaction-aware event-driven programming. It’s an essential tool when you want to execute actions only after successful database transactions, making your applications more robust and consistent.&lt;/p&gt;

&lt;p&gt;However, understanding its limitations and potential pitfalls helps you use it effectively and avoid unexpected issues.&lt;/p&gt;

&lt;p&gt;Have you used &lt;code&gt;TransactionEventListener&lt;/code&gt; in your projects? Share your experience or questions below!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>java</category>
    </item>
    <item>
      <title>Spring Annotations vs Node.js Decorators: A Cross-Stack Developer’s Guide</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Tue, 27 May 2025 03:58:17 +0000</pubDate>
      <link>https://dev.to/haraf/spring-annotations-vs-nodejs-decorators-a-cross-stack-developers-guide-4n4b</link>
      <guid>https://dev.to/haraf/spring-annotations-vs-nodejs-decorators-a-cross-stack-developers-guide-4n4b</guid>
      <description>&lt;p&gt;If worked with &lt;strong&gt;Java Spring Boot&lt;/strong&gt;, likely familiar with annotations like &lt;code&gt;@RestController&lt;/code&gt;, &lt;code&gt;@Autowired&lt;/code&gt;, and &lt;code&gt;@Transactional&lt;/code&gt;. These annotations help organize code, inject dependencies, and declare behavior in a clean and declarative way.&lt;/p&gt;

&lt;p&gt;But what about the Node.js world? With &lt;strong&gt;TypeScript&lt;/strong&gt;, we now have &lt;strong&gt;decorators&lt;/strong&gt;, which serve a very similar purpose — but with different mechanics under the hood.&lt;/p&gt;

&lt;p&gt;Let’s dive into a &lt;strong&gt;head-to-head comparison&lt;/strong&gt; of &lt;strong&gt;Spring annotations&lt;/strong&gt; vs &lt;strong&gt;Node.js decorators&lt;/strong&gt;, exploring how they align and differ.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 What Are They?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Spring (Java) Annotation&lt;/th&gt;
&lt;th&gt;Node.js (TypeScript) Decorator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Syntax&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@AnnotationName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@DecoratorName&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;Metadata &amp;amp; behavior injection&lt;/td&gt;
&lt;td&gt;Metadata &amp;amp; behavior injection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Under the hood&lt;/td&gt;
&lt;td&gt;Java reflection + AOP (compile/runtime)&lt;/td&gt;
&lt;td&gt;TypeScript decorators (experimental ES syntax)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usage areas&lt;/td&gt;
&lt;td&gt;Controllers, DI, Transactions, etc.&lt;/td&gt;
&lt;td&gt;Classes, methods, params, properties&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  1️⃣ Controllers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Spring Boot:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/users"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/{id}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathVariable&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Node.js (TypeScript + &lt;code&gt;routing-controllers&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;JsonController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📌 Both define routes declaratively&lt;br&gt;
📌 Decorators enable class-based design in TypeScript similar to Spring&lt;/p&gt;


&lt;h2&gt;
  
  
  2️⃣ Dependency Injection
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Spring Boot:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// logic&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@RestController&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Node.js (with &lt;code&gt;typedi&lt;/code&gt; or &lt;code&gt;inversify&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;JsonController&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔄 Constructor injection is more common in Node.js&lt;br&gt;
🧠 Java uses field/constructor injection via reflection&lt;/p&gt;


&lt;h2&gt;
  
  
  3️⃣ Validation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Spring Boot (Hibernate Validator):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@NotEmpty&lt;/span&gt;
    &lt;span class="nd"&gt;@Email&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Node.js (with &lt;code&gt;class-validator&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;IsEmail&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;IsNotEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Both use decorators to declare constraints&lt;br&gt;
✅ Can validate at runtime automatically&lt;/p&gt;


&lt;h2&gt;
  
  
  4️⃣ Transactions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Spring Boot:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Transactional&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// DB logic&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Node.js (with &lt;code&gt;typeorm&lt;/code&gt; or custom wrapper):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// DB logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔐 Decorators help wrap method logic with transaction boundaries&lt;br&gt;
🧱 Node.js needs libraries like &lt;code&gt;typeorm-transactional-cls-hooked&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Under the Hood Differences
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Spring&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;JVM + Reflection + AnnotationProcessor&lt;/td&gt;
&lt;td&gt;V8 + TypeScript metadata APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution context&lt;/td&gt;
&lt;td&gt;Annotations are compiled and scanned&lt;/td&gt;
&lt;td&gt;Decorators are applied at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maturity&lt;/td&gt;
&lt;td&gt;Very mature (20+ years)&lt;/td&gt;
&lt;td&gt;Still evolving (stage 3 ECMAScript)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency Injection&lt;/td&gt;
&lt;td&gt;Built-in (Spring Container)&lt;/td&gt;
&lt;td&gt;External (Inversify, Typedi, NestJS, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  ✅ TL;DR: Should You Care?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Spring (Java)&lt;/th&gt;
&lt;th&gt;Node.js (TypeScript)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise-grade systems&lt;/td&gt;
&lt;td&gt;✅ Battle-tested&lt;/td&gt;
&lt;td&gt;✅ With NestJS/Inversify&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fast APIs / Prototypes&lt;/td&gt;
&lt;td&gt;😐 Verbose setup&lt;/td&gt;
&lt;td&gt;✅ Quick with decorators&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microservices architecture&lt;/td&gt;
&lt;td&gt;✅ Spring Cloud&lt;/td&gt;
&lt;td&gt;✅ Node + gRPC or REST + decorators&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning curve&lt;/td&gt;
&lt;td&gt;📈 Steeper&lt;/td&gt;
&lt;td&gt;📉 Smoother with NestJS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🔚 Final Thoughts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Spring annotations and TypeScript decorators solve similar problems — &lt;strong&gt;declarative, DRY, organized code&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;syntax is almost identical&lt;/strong&gt;, but &lt;strong&gt;the philosophy and tooling differ&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Whether you’re moving from Java to Node.js or exploring both for architecture design, understanding these patterns helps you write &lt;strong&gt;better, cleaner code&lt;/strong&gt; in any backend.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>node</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Master Data Management (MDM) in Microservice Architecture: Best Approaches, Pros/Cons, and Real Examples</title>
      <dc:creator>araf</dc:creator>
      <pubDate>Tue, 20 May 2025 04:01:25 +0000</pubDate>
      <link>https://dev.to/haraf/master-data-management-mdm-in-microservice-architecture-best-approaches-proscons-and-real-32b0</link>
      <guid>https://dev.to/haraf/master-data-management-mdm-in-microservice-architecture-best-approaches-proscons-and-real-32b0</guid>
      <description>&lt;p&gt;Master Data Management (MDM) is often overlooked until microservices start misbehaving due to data inconsistencies. If your services rely on customer, product, or vendor data and you're not managing it centrally, you're inviting chaos. Let's fix that.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 What Is Master Data in Microservices?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Master Data&lt;/strong&gt; refers to the core, non-transactional data that defines business entities such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customers&lt;/li&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Suppliers&lt;/li&gt;
&lt;li&gt;Locations&lt;/li&gt;
&lt;li&gt;Employees&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In microservices, each service owns its own data. But when multiple services need &lt;strong&gt;shared, consistent master data&lt;/strong&gt;, things get complicated.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Common Pitfalls Without MDM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;❌ Customer name mismatch across systems&lt;/li&gt;
&lt;li&gt;❌ Product catalog inconsistencies&lt;/li&gt;
&lt;li&gt;❌ Data duplication &amp;amp; syncing nightmares&lt;/li&gt;
&lt;li&gt;❌ Hard-to-maintain integration logic&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ Common MDM Approaches in Microservices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Centralized MDM Service&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a dedicated microservice that exposes APIs for master data (e.g., &lt;code&gt;CustomerService&lt;/code&gt;, &lt;code&gt;ProductCatalogService&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;
  
  
  🔧 Example:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/products/{id}
POST /api/customers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Central source of truth&lt;/li&gt;
&lt;li&gt;Easy to control validation and versioning&lt;/li&gt;
&lt;li&gt;Ensures consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Becomes a bottleneck or single point of failure&lt;/li&gt;
&lt;li&gt;Doesn’t scale well for all domains&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; When master data rarely changes and strong consistency is needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. &lt;strong&gt;Data Replication (Read-Only Caching)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Services consume master data via APIs or message queues and store local, read-only copies.&lt;/p&gt;

&lt;h4&gt;
  
  
  🛠️ Example:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Product service pushes updates to Kafka&lt;/li&gt;
&lt;li&gt;Order service subscribes and caches product data locally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly available and decoupled&lt;/li&gt;
&lt;li&gt;Local read performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eventual consistency&lt;/li&gt;
&lt;li&gt;Requires sync/reconciliation mechanisms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; High-read use cases (e.g., product catalogs, inventory).&lt;/p&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;Shared Database (Only for Master Data)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A separate shared database is used solely for master data, accessed by services via repositories or shared libraries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy implementation&lt;/li&gt;
&lt;li&gt;Immediate consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Breaks microservice independence&lt;/li&gt;
&lt;li&gt;Tight coupling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; In early-stage systems or when refactoring monoliths.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. &lt;strong&gt;Domain Ownership &amp;amp; Reference Publishing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each service owns its master data domain and &lt;strong&gt;publishes changes&lt;/strong&gt; (via events) for other services to consume.&lt;/p&gt;

&lt;h4&gt;
  
  
  🔄 Example:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Customer Service publishes &lt;code&gt;CustomerUpdated&lt;/code&gt; events&lt;/li&gt;
&lt;li&gt;Billing and Order services subscribe to updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loosely coupled&lt;/li&gt;
&lt;li&gt;Scalable and event-driven&lt;/li&gt;
&lt;li&gt;Easy to track changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eventual consistency&lt;/li&gt;
&lt;li&gt;Requires mature event architecture (Kafka, RabbitMQ, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When to use:&lt;/strong&gt; In mature, distributed systems with asynchronous communication.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Define a canonical data model (avoid ambiguity)&lt;/li&gt;
&lt;li&gt;✅ Use versioned APIs for master data&lt;/li&gt;
&lt;li&gt;✅ Ensure idempotency for updates&lt;/li&gt;
&lt;li&gt;✅ Use CDC (Change Data Capture) or event sourcing for sync&lt;/li&gt;
&lt;li&gt;✅ Audit and monitor master data changes&lt;/li&gt;
&lt;li&gt;✅ Automate reconciliation between services&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔥 Real-World Example: Product Catalog MDM
&lt;/h2&gt;

&lt;p&gt;Imagine an eCommerce system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ProductService&lt;/code&gt;: owns all product master data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OrderService&lt;/code&gt;, &lt;code&gt;CartService&lt;/code&gt;, &lt;code&gt;InventoryService&lt;/code&gt; depend on it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ProductService&lt;/code&gt; publishes product events to Kafka&lt;/li&gt;
&lt;li&gt;Others subscribe and cache locally&lt;/li&gt;
&lt;li&gt;Consistency ensured via periodic sync or hash-based reconciliation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📌 Conclusion
&lt;/h2&gt;

&lt;p&gt;Master Data Management in microservices isn't just a technical choice—it's a business-critical strategy.&lt;/p&gt;

&lt;p&gt;Choose your approach based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequency of change&lt;/li&gt;
&lt;li&gt;Consistency requirements&lt;/li&gt;
&lt;li&gt;Scalability expectations&lt;/li&gt;
&lt;li&gt;Team maturity&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧵 TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Trade-offs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Centralized MDM Service&lt;/td&gt;
&lt;td&gt;Strong consistency, simplicity&lt;/td&gt;
&lt;td&gt;Bottleneck risk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Replication&lt;/td&gt;
&lt;td&gt;Fast reads, loosely coupled systems&lt;/td&gt;
&lt;td&gt;Eventual consistency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared DB for MDM&lt;/td&gt;
&lt;td&gt;Simplicity in early stages&lt;/td&gt;
&lt;td&gt;Breaks service independence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event-Driven Ownership&lt;/td&gt;
&lt;td&gt;Scalability, loosely coupled systems&lt;/td&gt;
&lt;td&gt;Complex setup, requires maturity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💬 Let’s Discuss
&lt;/h2&gt;

&lt;p&gt;What MDM approach have you used in your microservice projects? Any horror stories or success patterns? Drop them below 👇&lt;/p&gt;

</description>
      <category>programming</category>
      <category>microservices</category>
      <category>architecture</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
