<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://feeds.feedblitz.com/feedblitz_rss.xslt"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:webfeeds="http://webfeeds.org/rss/1.0"  xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
<channel>
	<title>Baeldung</title>
	<atom:link href="https://www.baeldung.com/feed" rel="self" type="application/rss+xml" />
	<link>https://www.baeldung.com</link>
	<description>Java, Spring and Web Development tutorials</description>
	<lastBuildDate>Thu, 23 Apr 2026 19:26:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
<meta xmlns="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
<item>
<feedburner:origLink>https://www.baeldung.com/java-weekly-643</feedburner:origLink>
		<title>Java Weekly, Issue 643</title>
		<link>https://feeds.feedblitz.com/~/954364250/0/baeldung~Java-Weekly-Issue</link>
					<comments>https://feeds.feedblitz.com/~/954364250/0/baeldung~Java-Weekly-Issue#respond</comments>
		
		<dc:creator><![CDATA[baeldung]]></dc:creator>
		<pubDate>Thu, 23 Apr 2026 19:26:11 +0000</pubDate>
				<category><![CDATA[Weekly Review]]></category>
		<category><![CDATA[no-ads]]></category>
		<category><![CDATA[no-after-post]]></category>
		<category><![CDATA[no-before-post]]></category>
		<category><![CDATA[no-optins]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203544</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" fetchpriority="high" /><p>Interesting AI-focused pieces and starting to look forward towards JDK 27.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/954364250/0/baeldung~Java-Weekly-Issue">Java Weekly, Issue 643</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954364250/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Weekly-Reviews-4.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-weekly-643#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-weekly-643/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" srcset="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg 952w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-768x402.jpg 768w" sizes="(max-width: 580px) 100vw, 580px" /><h2 style="text-align: left;" id="bd-spring-and-java" data-id="spring-and-java">1.<strong> Spring and Java</strong></h2>
<div class="bd-anchor" id="spring-and-java"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/distributed-cache-invalidation-patterns/">&gt;&gt; Distributed Cache Invalidation Patterns</a></strong> [<span style="color: #993300;">foojay.io</span>]</p>
<p>A pragmatic tour through distributed cache invalidation, with concrete Spring Boot + Redis code for each pattern. Good brushup.</p>
<h4><strong>Also worth reading:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/eliminating-flaky-tests-to-end-world-hunger/" target="_blank" rel="noopener"><strong>Eliminating Flaky Tests to End World Hunger</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/boxlang-ai-deep-dive-part-3-of-7-multi-agent-orchestration-building-ai-teams-that-work/" target="_blank" rel="noopener"><strong>BoxLang AI Deep Dive — Part 3 of 7: Multi-Agent Orchestration</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/crossing-the-river-styx-spring-boot-3-5-and-the-zombie-dependency-problem/" target="_blank" rel="noopener"><strong>Crossing the River Styx: Spring Boot 3.5 and the Zombie Dependency Problem</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/which-java-runtime-should-you-use-in-production-comparing-openjdk-distributions/" target="_blank" rel="noopener"><strong>Which Java Runtime Should You Use in Production? Comparing OpenJDK Distributions</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.infoq.com/articles/redesign-pdf-table-extraction/" target="_blank" rel="noopener"><strong>Redesigning Banking PDF Table Extraction: A Layered Approach with Java</strong></a> [<span style="color: #800000;">infoq.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.infoq.com/news/2026/04/google-adk-1-0-new-architecture/" target="_blank" rel="noopener"><strong>Google ADK for Java 1.0 Introduces New App and Plugin Architecture</strong></a> [<span style="color: #800000;">infoq.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/building-a-personalized-content-delivery-system/" target="_blank" rel="noopener"><strong>Building a Personalized Content Delivery System</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/19/generics-optimization/" target="_blank" rel="noopener"><strong>How the JVM Optimizes Generic Code</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://nipafx.dev/inside-java-newscast-110" target="_blank" rel="noopener"><strong>You Must Avoid Final Field Mutation &#8211; Inside Java Newscast #110</strong></a> [<span style="color: #800000;">nipafx.dev</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.jetbrains.com/kotlin/2026/04/kotlin-professional-certificate-by-jetbrains-now-on-linkedin-learning/" target="_blank" rel="noopener"><strong>Kotlin Professional Certificate by JetBrains – Now on LinkedIn Learning</strong></a> [<span style="color: #800000;">jetbrains.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.jetbrains.com/ai/2026/04/introducing-koog-integration-for-spring-ai-smarter-orchestration-for-your-agents/" target="_blank" rel="noopener"><strong>Introducing Koog Integration for Spring AI</strong></a> [<span style="color: #800000;">jetbrains.com</span>]</li>
</ul>
<h4><strong>Webinars and presentations:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/23/podcast-056/" target="_blank" rel="noopener"><strong>Episode 56 “Ask the Architects at JavaOne” [AtA]</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/16/podcast-055/" target="_blank" rel="noopener"><strong>Episode 55 “You Must Avoid Final Field Mutation” [IJN]</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/23/a-bootiful-podcast-venkat-james" target="_blank" rel="noopener"><strong>A Bootiful Podcast: Dr. Venkat Subramaniam and James Ward</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/20/spring-office-hours-podcast-S5E13" target="_blank" rel="noopener"><strong>Spring Office Hours Podcast: S5E13 &#8211; Community Potluck</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/16/a-bootiful-podcast-craig-walls" target="_blank" rel="noopener"><strong>A Bootiful Podcast: the legendary Craig Walls</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
</ul>
<h4><strong>Time to upgrade:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/azul-zulu-april-2026-quarterly-update-released/" target="_blank" rel="noopener"><strong>Azul Zulu April 2026 Quarterly Update Released</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://in.relation.to/2026/04/23/JPA-4-M2/" target="_blank" rel="noopener"><strong>Jakarta Persistence 4.0 Milestone 2</strong></a> [<span style="color: #800000;">in.relation.to</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/21/quality-heads-up/" target="_blank" rel="noopener"><strong>Quality Outreach Heads-up &#8211; JDK 27: Obsolete Translation Resources Removed</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.jetbrains.com/idea/2026/04/intellij-idea-2026-1-1/" target="_blank" rel="noopener"><strong>IntelliJ IDEA 2026.1.1 Is Out!</strong></a> [<span style="color: #800000;">jetbrains.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://quarkus.io/blog/quarkus-3-34-6-released/" target="_blank" rel="noopener"><strong>Quarkus 3.34.6</strong></a> and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://quarkus.io/blog/quarkus-3-34-5-released/" target="_blank" rel="noopener"><strong>3.34.5 &#8211; Maintenance releases</strong></a> [<span style="color: #800000;">quarkus.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/23/spring-boot-3-5-14-available-now" target="_blank" rel="noopener"><strong>Spring Boot 3.5.14</strong></a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/23/spring-boot-4-0-6-available-now" target="_blank" rel="noopener"><strong>4.0.6</strong></a>, and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/23/spring-boot-4-1-0-RC1-available-now" target="_blank" rel="noopener"><strong>4.1.0-RC1 available now</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/22/spring-for-apache-pulsar-1-2-17-and-2-0-5-are-now-available" target="_blank" rel="noopener"><strong>Spring for Apache Pulsar 1.2.17 and 2.0.5 are now available</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/22/spring-kafka-4" target="_blank" rel="noopener"><strong>Spring for Apache Kafka 4.1.0-RC1, 4.0.5, and 3.3.15 Available</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/21/spring-security-releases" target="_blank" rel="noopener"><strong>Spring Security 2026.04 Releases &#8211; Contains CVE Fixes</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/21/spring-authorization-server-1-5-7-available-now" target="_blank" rel="noopener"><strong>Spring Authorization Server 1.5.7 Available Now</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/17/spring-data-2025-1-5-and-2025-0-11-released" target="_blank" rel="noopener"><strong>Spring Data 2025.1.5 and 2025.0.11 released</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/17/spring-data-2026-0-0-goes-RC" target="_blank" rel="noopener"><strong>Spring Data 2026.0.0-RC1 enters release candidate phase</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/17/spring-framework-6-2-18-and-7-0-7-available-now" target="_blank" rel="noopener"><strong>Spring Framework 6.2.18 and 7.0.7 Available Now</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eclipse-vertx/vert.x/releases/tag/5.0.11" target="_blank" rel="noopener"><strong>Vert.x 5.0.11</strong></a> [<span style="color: #800000;">github.com/eclipse-vertx</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/apache/camel/releases/tag/camel-4.14.6" target="_blank" rel="noopener"><strong>Apache Camel 4.14.6</strong></a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/apache/camel/releases/tag/camel-4.14.7" target="_blank" rel="noopener"><strong>4.14.7</strong></a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/apache/camel/releases/tag/camel-4.18.2" target="_blank" rel="noopener"><strong>4.18.2</strong></a>, and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/apache/camel/releases/tag/camel-4.20.0" target="_blank" rel="noopener"><strong>4.20.0</strong></a> [<span style="color: #800000;">github.com/apache</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/helidon-io/helidon/releases/tag/3.2.17" target="_blank" rel="noopener"><strong>Helidon 3.2.17</strong></a> [<span style="color: #800000;">github.com/helidon-io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/payara/Payara/releases/tag/payara-server-7.2026.4" target="_blank" rel="noopener"><strong>Payara Platform 7.2026.4</strong></a> [<span style="color: #800000;">github.com/payara</span>]</li>
</ul>
<h2 style="text-align: left;" id="bd-technical-amp-musings" data-id="technical-amp-musings">2.<strong> Technical &amp; Musings</strong></h2>
<div class="bd-anchor" id="technical-amp-musings"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.frankel.ch/illegal-state-unrepresentable/">&gt;&gt; Making illegal state unrepresentable</a></strong> [<span style="color: #993300;">frankel.ch</span>]</p>
<p>A solid take on the classic <em>make illegal states unrepresentable</em> principle, walking through the idea across several languages. Types are still our first line of defense against bad data.</p>
<h4><strong>Also worth reading:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://event-driven.io/en/yoda_principle_in_command_design/" target="_blank" rel="noopener"><strong>Yoda Principle for better integrations</strong></a> [<span style="color: #800000;">event-driven.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.jbrains.ca/permalink/playing-well-with-others-an-example" target="_blank" rel="noopener"><strong>Playing Well With Others: An Example</strong></a> [<span style="color: #800000;">jbrains.ca</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.allthingsdistributed.com/2026/04/the-invisible-engineering-behind-lambdas-network.html" target="_blank" rel="noopener"><strong>The invisible engineering behind Lambda&#8217;s network</strong></a> [<span style="color: #800000;">allthingsdistributed.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://nurkiewicz.com/2026/04/open-telemetry-glossary.html" target="_blank" rel="noopener"><strong>OpenTelemetry glossary: 30 terms you should know</strong></a> [<span style="color: #800000;">nurkiewicz.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://netflixtechblog.com/the-human-infrastructure-how-netflix-built-the-operations-layer-behind-live-at-scale-33e2a311c597" target="_blank" rel="noopener"><strong>The Human Infrastructure: How Netflix Built the Operations Layer Behind Live at Scale</strong></a> [<span style="color: #800000;">netflixtechblog.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://netflixtechblog.medium.com/predicting-risk-in-content-launches-how-data-driven-insights-can-transform-launch-planning-587b1f2de928" target="_blank" rel="noopener"><strong>Predicting Risk in Content Launches</strong></a> [<span style="color: #800000;">netflixtechblog.com</span>]</li>
</ul>
<h2 style="text-align: left;" id="bd-pick-of-the-week" data-id="pick-of-the-week">3.<strong> Pick of the Week</strong></h2>
<div class="bd-anchor" id="pick-of-the-week"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://perthirtysix.com/how-the-heck-does-shazam-work">&gt;&gt; How The Heck Does Shazam Work?</a></strong> [<span style="color: #993300;">perthirtysix.com</span>]</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-weekly-643">Java Weekly, Issue 643</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/954364250/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954364250/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Weekly-Reviews-4.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954364250/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-weekly-643#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-weekly-643/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/954364250/0/baeldung~Java-Weekly-Issue/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/java-keystore-p7b-file-import</feedburner:origLink>
		<title>Importing p7b File to Java Keystore Using Keytool in Java</title>
		<link>https://feeds.feedblitz.com/~/954213383/0/baeldung~Importing-pb-File-to-Java-Keystore-Using-Keytool-in-Java</link>
					<comments>https://feeds.feedblitz.com/~/954213383/0/baeldung~Importing-pb-File-to-Java-Keystore-Using-Keytool-in-Java#respond</comments>
		
		<dc:creator><![CDATA[Vishal Shanbhag]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 05:02:48 +0000</pubDate>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[KeyStore]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/java-keystore-p7b-file-import</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" /><p>Explore how keytool works with certificate bundles in the p7b format.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/954213383/0/baeldung~Importing-pb-File-to-Java-Keystore-Using-Keytool-in-Java">Importing p7b File to Java Keystore Using Keytool in Java</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954213383/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f07%2fJava-Featured-10-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-keystore-p7b-file-import#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-keystore-p7b-file-import/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10-1024x536.jpg 1024w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10-768x402.jpg 768w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10-100x52.jpg 100w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10.jpg 1200w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 id="bd-introduction" data-id="introduction">1. Introduction</h2>
<div class="bd-anchor" id="introduction"></div>
<p>When working with production applications in Java, we often find ourselves configuring HTTPS, enabling secure outbound communication, or managing trust stores. <strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/keytool-intro">Keytool</a> is the standard tool for working with the required keys and certificates and thus managing Java <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-keystore">keystores</a>.</strong></p>
<p>In this tutorial, we’ll focus on a specific task: importing a <em>p7b</em> certificate file into a Java keystore using keytool.</p>
<h2 id="bd-understanding-the-p7b-pkcs7-format" data-id="understanding-the-p7b-pkcs7-format">2. Understanding the P7B (PKCS#7) Format</h2>
<div class="bd-anchor" id="understanding-the-p7b-pkcs7-format"></div>
<p>Before we dive into the steps to import a P7B file, it&#8217;s worth reviewing and understanding the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.rfc-editor.org/rfc/rfc2315.html">PKCS#7 format</a>.</p>
<p><strong>In cryptography, PKCS#7 is a standard syntax for storing cryptographically signed or encrypted data</strong>.</p>
<p>One common use for this format is to store SSL certificates. Often, certificate bundles are stored and shared as a <em>.p7b </em>file format.</p>
<h3 id="bd-1-certificate-bundle" data-id="1-certificate-bundle">2.1. Certificate Bundle</h3>
<div class="bd-anchor" id="1-certificate-bundle"></div>
<p>When creating <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-boot-https-self-signed-certificate">self signed</a> certificates for development use, it&#8217;s usually sufficient to have a private key and a self-signed certificate containing the public key. However, when working with production applications that are expected to be available over the internet, we typically need our certificates to be validated by a known Certificate Authority (CA).</p>
<p><strong>Browsers validate a site by validating the site&#8217;s certificate.</strong> Each site presents its own certificate along with information to a chain of intermediate certificates, eventually leading to the root certificate of a CA. Since the browsers trust the CA, any site presenting a validated certificate with a clear chain of certificates leading to a root CA certificate is considered valid.</p>
<p>Once a certificate is validated by a CA, they typically provide a certificate chain consisting of its own root certificate and zero or more intermediate certificates. This certificate chain is provided as a bundle of certificates, sometimes as a <em>.p7b </em>file.</p>
<h3 id="bd-2-the-p7b-format" data-id="2-the-p7b-format">2.2. The P7B Format</h3>
<div class="bd-anchor" id="2-the-p7b-format"></div>
<p><strong>A P7B file is a PKCS#7 container that can store one or more certificates.</strong> It may be encoded either in the binary DER format or in the Base64 PEM format.</p>
<p>When working with Java servers (such as Tomcat), we need to ensure that all the certificates in the bundle are imported into our keystore to prove the validity of our certificate.</p>
<p>Browsers on all modern devices recognise certificates validated by a CA. <strong>During the process of certificate validation, a CA will typically share the signed public certificate for our site along with a certificate chain, aka certificate bundle</strong>.</p>
<p>Sometimes, the certificate bundle comes as a file with a <em>.p7b</em> extension. We note that depending on the encoding, the contents may not be easily readable in a plain text editor. Therefore, we need a few tools to work with these certificates and import them into our keystore.</p>
<h2 id="bd-preparing-a-p7b-file" data-id="preparing-a-p7b-file">3. Preparing a P7B file</h2>
<div class="bd-anchor" id="preparing-a-p7b-file"></div>
<p>Now that we&#8217;ve understood the P7B format, let&#8217;s dive into the process.</p>
<p><strong>Before we can import a certificate bundle, we need a file containing the certificate bundle</strong>. Since we don&#8217;t have a <em>.p7b</em> provided by a CA, we&#8217;ll use the public certificate from <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/">Baeldung.com</a>.</p>
<p>First, we&#8217;ll download the chain and convert it into the P7B file format.</p>
<h3 id="bd-1-downloading-the-certificate-bundle" data-id="1-downloading-the-certificate-bundle">3.1. Downloading the Certificate Bundle</h3>
<div class="bd-anchor" id="1-downloading-the-certificate-bundle"></div>
<p>Most modern browsers allow exporting of certificates to PKCS#7 format encoded files. However, we&#8217;ll do a full command-line interface version using the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/linux/openssl-command-examples"><em>openssl </em></a>command on a Linux terminal:</p>
<pre><code class="language-shell">$ openssl s_client -connect www.baeldung.com:443 -showcerts &lt;/dev/null</code></pre>
<p>This command prints out several certificates along with some other information about each certificate. Each certificate can be identified easily because of the beginning and ending markers:</p>
<pre><code class="language-shell">-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----</code></pre>
<p>We can now copy each of those certificates (including the markers) and store them as a separate <em>.pem </em>file. So now we have three files <em>site.pem, intermediate.pem and root.pem</em>.</p>
<p>Now let&#8217;s use them to create a <em>.p7b </em>bundle:</p>
<pre><code class="language-shell">$ openssl crl2pkcs7 -nocrl -certfile site.pem -certfile intermediate.pem \
-certfile root.pem -out site-chain.p7b</code></pre>
<p>Finally, we can verify that all certificates of interest are present in the bundle:</p>
<pre><code class="language-shell">$ openssl pkcs7 -print_certs -in site-chain.p7b -noout</code></pre>
<p>We see three certificates printed clearly as expected.</p>
<h3 id="bd-2-the-problem-importing-p7b-file" data-id="2-the-problem-importing-p7b-file">3.2. The Problem Importing P7B file</h3>
<div class="bd-anchor" id="2-the-problem-importing-p7b-file"></div>
<p>Now that we have a valid certificate bundle in the <em>.p7b </em>file format, let&#8217;s check it with <em>keytool</em>:</p>
<pre><code class="language-">$ keytool -printcert -file site-chain.p7b</code></pre>
<p>This command prints information about the three certificates clearly.</p>
<p>Let&#8217;s attempt to import this as-is:</p>
<pre><code class="language-">$ keytool -importcert -file site-chain.p7b -keystore test-keystore.jks -alias site</code></pre>
<p>The output presents an error:</p>
<pre><code class="language-shell">keytool error: java.lang.Exception: Input not an X.509 certificate</code></pre>
<p><strong>The certificate import fails because the <em>keytool -importcert </em>expects the input file to contain exactly one X.509 PEM or DER encoded certificate.</strong></p>
<h2 id="bd-importing-the-p7b-file" data-id="importing-the-p7b-file">4. Importing the P7B file</h2>
<div class="bd-anchor" id="importing-the-p7b-file"></div>
<p>We observe that the direct import of a certificate bundle using keytool can be problematic. <strong>The solution is to break down the bundle into its individual certificates and then import those certificates one by one.</strong></p>
<h3 id="bd-1-converting-to-pem-encoding" data-id="1-converting-to-pem-encoding">4.1. Converting to PEM Encoding</h3>
<div class="bd-anchor" id="1-converting-to-pem-encoding"></div>
<p>To break the bundle into individual PEM files, first, we&#8217;ll convert the bundle from the PKCS #7 to a PEM encoded bundle:</p>
<pre><code class="language-">$ openssl pkcs7 -print_certs -in site-chain.p7b -out site-chain.pem</code></pre>
<p data-start="2455" data-end="2522">This produces a PEM file containing one or more X.509 certificates:</p>
<div class="relative w-full mt-4 mb-1">
<div class="">
<div class="relative">
<div class="h-full min-h-0 min-w-0">
<div class="h-full min-h-0 min-w-0">
<div class="border border-token-border-light border-radius-3xl corner-superellipse/1.1 rounded-3xl">
<div class="h-full w-full border-radius-3xl bg-token-bg-elevated-secondary corner-superellipse/1.1 overflow-clip rounded-3xl lxnfua_clipPathFallback">
<div class="pt-3">
<div class="relative z-0 flex max-w-full">
<div id="code-block-viewer" class="q9tKkq_viewer cm-editor z-10 light:cm-light dark:cm-light flex h-full w-full flex-col items-stretch ͼ5 ͼj" dir="ltr">
<div class="cm-scroller">
<div class="cm-content q9tKkq_readonly">
<pre><code class="language-shell">-----BEGIN CERTIFICATE-----
.......
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
.......
-----END CERTIFICATE-----</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<p>We&#8217;re now ready to use <em>keytool</em> to import the certificates.</p>
<h3 id="bd-2-importing-the-pem-bundle" data-id="2-importing-the-pem-bundle">4.2. Importing the PEM Bundle</h3>
<div class="bd-anchor" id="2-importing-the-pem-bundle"></div>
<p><strong>Now that the file is in a format compatible with the <em>keytool</em> import option, we can perform the input</strong>:</p>
<pre><code class="language-">$ keytool -importcert -file site-chain.pem -keystore test-keystore.jks -alias site</code></pre>
<p>This command requires us to set a keystore password and asks us if we trust the certificate. Then the output shows success:</p>
<pre><code class="language-shell">Trust this certificate? [no]:  yes
Certificate was added to keystore</code></pre>
<p>This imports the site&#8217;s certificate under the alias <em>site</em>.</p>
<p><strong>If we need the intermediate and root certificates as well in the same keystore, then we need to import them individually</strong>. From <em>site-chain.pem </em>we can copy each of those certificates (including the begin and end markers) and store them as a separate <em>.pem </em>file. So now we have two more files,<em> intermediate.pem</em> and<em> root.pem</em>.</p>
<p>We can use the same command with different input files and aliases to import the root and intermediate certificates as well:</p>
<pre><code class="language-">$ keytool -importcert -file root.pem -keystore test-keystore.jks -alias root
$ keytool -importcert -file intermediate.pem -keystore test-keystore.jks -alias intermediate</code></pre>
<h3 id="bd-3-verifying-the-import" data-id="3-verifying-the-import">4.3. Verifying the Import</h3>
<div class="bd-anchor" id="3-verifying-the-import"></div>
<p>Now we have all certificates imported, let&#8217;s verify them:</p>
<pre><code class="language-">$ keytool -list -v -keystore test-keystore.jks</code></pre>
<p>This command requests the previously set password and then shows us detailed information about all the imported certificates. At the beginning of the output, we see:</p>
<pre><code class="language-">Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 3 entries
</code></pre>
<p>That&#8217;s it. Our keystore is now ready to use.</p>
<h2 id="bd-conclusion" data-id="conclusion">5. Conclusion</h2>
<div class="bd-anchor" id="conclusion"></div>
<p>In this article, we explored how keytool works with certificate bundles in the PKCS#7 (<em>.p7b</em>) format. While these files can contain complete certificate chains, they&#8217;re not always directly supported for import.</p>
<p>We learnt that <em>keytool</em> expects X.509 certificates in DER or PEM format, not container formats like PKCS#7. <strong>Converting the <em>.p7b</em> bundle into individual certificates ensures a successful and predictable import process</strong>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-keystore-p7b-file-import">Importing p7b File to Java Keystore Using Keytool in Java</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/954213383/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954213383/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f07%2fJava-Featured-10-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954213383/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-keystore-p7b-file-import#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-keystore-p7b-file-import/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/954213383/0/baeldung~Importing-pb-File-to-Java-Keystore-Using-Keytool-in-Java/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-10-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/spring-data-aot-repositories</feedburner:origLink>
		<title>Introduction to Spring Data AOT Repositories</title>
		<link>https://feeds.feedblitz.com/~/954210833/0/baeldung~Introduction-to-Spring-Data-AOT-Repositories</link>
					<comments>https://feeds.feedblitz.com/~/954210833/0/baeldung~Introduction-to-Spring-Data-AOT-Repositories#respond</comments>
		
		<dc:creator><![CDATA[Stelios Anastasakis]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 04:19:23 +0000</pubDate>
				<category><![CDATA[Spring Data]]></category>
		<category><![CDATA[Spring Data JPA]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203515</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Explore Spring Data AOT Repositories using a simple UserRepository class to demonstrate how Spring Data Repositories worked before and what changes exactly this new feature introduced.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/954210833/0/baeldung~Introduction-to-Spring-Data-AOT-Repositories">Introduction to Spring Data AOT Repositories</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954210833/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f11%2fPersistence-Featured-Image-04-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-data-aot-repositories#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-data-aot-repositories/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-1024x536.jpg 1024w, https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-768x402.jpg 768w, https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-100x52.jpg 100w, https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-600x314.jpg 600w, https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04.jpg 1200w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 id="bd-overview" data-id="overview">1. Overview</h2>
<div class="bd-anchor" id="overview"></div>
<p>In the last few years, there has been a lot of effort in the Java ecosystem to improve JVM performance. We have seen the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/graal-java-jit-compiler">JIT compiler</a>, then the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/ahead-of-time-compilation">Ahead of Time (AoT)</a> Compilation, and lately the Native Images.</p>
<p>Popular Java frameworks, like Micronaut and Spring, have moved in the same direction to achieve better performance through compilation improvements. Spring offers both <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-6-ahead-of-time-optimizations">Ahead of Time</a> and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-native-intro">Native Image</a> support. However, in such big frameworks, there is still a lot of use of Reflection, so there is still plenty of room for improvement. The latest feature, to be introduced in Spring Boot 4, is an AOT optimization for Spring Data, with the AOT Repositories.</p>
<p>In this article, we&#8217;re going to see what the new feature of Spring Data AOT Repositories brings in. We&#8217;re going to use one of the milestone versions, since this new feature is not offered in any release version yet. Then, we&#8217;ll demonstrate how it works. In the end, we&#8217;re going to compare its usage with the current alternatives, using Spring Boot 3 with and without AOT compilation.</p>
<h2 id="bd-dependencies" data-id="dependencies">2. Dependencies</h2>
<div class="bd-anchor" id="dependencies"></div>
<p>Let&#8217;s start by defining the minimum dependencies possible, for demonstrating the Spring Data AOT Repositories. We can only keep the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web"><em>spring-boot-starter-web</em></a> and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa"><em>spring-boot-starter-data-jpa</em></a>. The first is for offering an endpoint to verify that the repository actually works, and the latter contains everything needed for Spring to interact with a database:</p>
<pre><code class="language-xml">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
    &lt;version&gt;4.0.5&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;
    &lt;version&gt;4.0.5&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
<p>Spring Boot major version 4 is only available in early stages. We&#8217;re still going to use the stable <em>4.0.5</em> for our demonstration.</p>
<h2 id="bd-spring-data-repository" data-id="spring-data-repository">3. Spring Data Repository</h2>
<div class="bd-anchor" id="spring-data-repository"></div>
<p>Moving on, let’s look at how repository implementations have evolved from being runtime proxies to the build-time generated code with Spring Data AOT Repositories. We&#8217;ll use a very simple and popular example of a <em>User</em> entity and the respective <em>UserRepository</em>. This will let us compare behavior and performance across the three options of repositories without AOT, repositories with AOT (but before AOT Repositories), and AOT Repositories.</p>
<h3 id="bd-1-the-domain-model" data-id="1-the-domain-model">3.1. The Domain Model</h3>
<div class="bd-anchor" id="1-the-domain-model"></div>
<p>We’ll use a short <em>User</em> entity, with just three fields, for demonstration purposes:</p>
<pre><code class="language-java">@Entity
@Table(name = "USERS")
public class User {
    @Id
    @GeneratedValue
    private Long id;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    // constructors, setters, getters, equals, etc.
}</code></pre>
<p>The entity class only contains an <em>id</em>, a <em>firstName</em>, and a <em>lastName</em> field. We can use all of the Spring Data and JPA annotations we&#8217;re familiar with. Then we&#8217;ll create the related <em>UserRepository</em>:</p>
<pre><code class="language-java">public interface UserRepository extends Repository&lt;User, Long&gt; {
    User save(User user);
    @Transactional(readOnly = true)
    List&lt;User&gt; findAll();
    List&lt;User&gt; findAllById(Iterable&lt;Long&gt; longs);
    @Query(value = "SELECT * FROM users", nativeQuery = true)
    List&lt;User&gt; nativeQueryFindAllUsers();
    @Query(value = "SELECT u FROM User u")
    List&lt;User&gt; queryFindAllUsers();
}</code></pre>
<p>First, we&#8217;ll include three methods that Spring Data can translate into queries, as normal. On top of that, we&#8217;ll add two more methods annotated with <em>@Query</em>, one native and one non-native. This is so we see how Spring Data AOT Repository handles the different cases.</p>
<p>Second, we extend the <em>Repository</em> Interface to be more generic. The dependency we&#8217;ve included earlier will translate it to <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-data-repositories"><em>JpaRepository</em></a>.</p>
<h3 id="bd-2-spring-data-repositories-without-aot" data-id="2-spring-data-repositories-without-aot">3.2. Spring Data Repositories Without AOT</h3>
<div class="bd-anchor" id="2-spring-data-repositories-without-aot"></div>
<p>Before Spring AOT optimizations and Spring Data AOT Repositories, we would compile the code by using the <em>mvn clean install</em> command. This would convert the Java file to a class, without any changes, except for indentation.</p>
<p>This means that the implementation is not generated. As we know, everything happens at runtime:</p>
<ol>
<li>Spring finds the <em>Repository</em> interfaces</li>
<li>Passes them to the <em>JpaRepositoryFactory</em></li>
<li>The <em>JpaRepositoryFactory</em> builds the <em>SimpleJpaRepository</em> instances</li>
<li>Then wraps each instance with a dynamic proxy that routes calls from your interface methods, like <em>findAll()</em>, to the corresponding methods on <em>SimpleJpaRepository</em>, or to the <em>Query</em> and <em>JPQL</em> implementations, or to any custom implementations</li>
</ol>
<p><strong>Everything is being built at runtime, based on reflection</strong>. This means that startup time and memory are being affected.</p>
<h3 id="bd-3-repositories-with-aot-before-spring-data-aot-repositories" data-id="3-repositories-with-aot-before-spring-data-aot-repositories">3.3. Repositories With AOT, Before Spring Data AOT Repositories</h3>
<div class="bd-anchor" id="3-repositories-with-aot-before-spring-data-aot-repositories"></div>
<p>Spring 6 came with Ahead of Time Optimizations. To <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-6-ahead-of-time-optimizations#1-aot-optimization">enable this feature</a>, we need to:</p>
<ul>
<li>Compile the code, including the <em>spring-boot:process-aot</em> task, or set up the build plugin to enable AOT compilation by default</li>
<li>Execute the application setting the <em>spring.aot.enabled</em> property to <em>true</em></li>
</ul>
<p>Regarding the Spring Data Repositories, the result is the same as before. This means that we get the same class, and then Spring uses the <em>SimpleJpaRepository</em>, reflection, and proxies at runtime to make everything happen. <strong>The difference is that the AOT compilation creates an additional class, the <em>UserRepository__BeanDefinitions</em> class, with some reflection metadata and other info precomputed at build time. This improves startup time</strong>.</p>
<h3 id="bd-4-spring-data-aot-repositories" data-id="4-spring-data-aot-repositories">3.4. Spring Data AOT Repositories</h3>
<div class="bd-anchor" id="4-spring-data-aot-repositories"></div>
<p>The new feature, coming with Spring Data 4, is the Spring Data AOT Repositories. With this feature, Spring is shifting all the Repository preparations that are done at application startup to build time.</p>
<p>Let&#8217;s see how this works, on a high level. <strong>Spring turns your Repository query methods into actual source code by relying on the store-specific nature of the repository</strong>. The methods that are already implemented are used directly. For instance, the <em>save()</em> method is implemented in <em>SimpleJpaRepository</em>, in our example. Spring doesn&#8217;t need to generate any code for such methods. However, the remaining methods will be implemented inside the <em>UserRepositoryImpl__AotRepository</em> class.</p>
<p>The way to compile the code using AOT remains the same as in the previous Spring version. We can find the generated classes in our <em>target/classes</em> folder:</p>
<pre><code class="language-java">@Generated
public class UserRepositoryImpl__AotRepository extends AotRepositoryFragmentSupport {
    private final RepositoryFactoryBeanSupport.FragmentCreationContext context;
    private final EntityManager entityManager;
    public List&lt;User&gt; nativeQueryFindAllUsers() {
        String var1 = "SELECT * FROM users";
        Query var2 = this.entityManager.createNativeQuery(var1, User.class);
        return var2.getResultList();
    }
    public List&lt;User&gt; queryFindAllUsers() {
        String var1 = "SELECT u FROM User u";
        Query var2 = this.entityManager.createQuery(var1);
        return var2.getResultList();
    }
}</code></pre>
<p><strong>Methods annotated with <em>@Query</em> contain the same code we would write if we weren&#8217;t using Spring Data</strong>. The <em>UserRepository__BeanDefinitions</em> class is present, similar to previous versions. The last source generated by this new feature is a JSON file with hints for native-image, <em>UserRepository.json</em>.</p>
<p><strong>This way Spring generates a concrete repository implementation at build time, eliminating the proxy and most runtime reflection. This improves both the startup time and memory</strong>.</p>
<p>To enable usage of Spring Data AOT Repositories, we need to execute the application setting the <em>spring.aot.repositories.enabled</em> property to <em>true:</em></p>
<pre><code class="language-bash">mvn spring-boot:run -Dspring.aot.enabled=true -Dspring.aot.repositories.enabled=true</code></pre>
<h2 id="bd-performance-implications" data-id="performance-implications">4. Performance Implications</h2>
<div class="bd-anchor" id="performance-implications"></div>
<p>Spring Data AOT Repositories are expected to improve application performance. Startup time should be reduced, and some memory consumption as well, as advertised in the relevant <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2025/05/22/spring-data-ahead-of-time-repositories">Spring Blog article</a>:</p>
<a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/wp-content/uploads/2026/04/spring-petclinic-jpa-aot-repositories-benchmark-green_theme.png"><img decoding="async" class="alignnone size-large wp-image-242852" src="https://www.baeldung.com/wp-content/uploads/2026/04/spring-petclinic-jpa-aot-repositories-benchmark-green_theme-1024x229.png" alt="spring data aot repositories benchmark" /></a>
<p>Next, we&#8217;ll compare the performance of the three implementations we discussed so far:</p>
<ul>
<li>Spring before AOT, using the <em>java -jar spring-data-jpa-not-aot/target/spring-data-jpa-not-aot-0.0.1-SNAPSHOT.jar</em> command</li>
<li>Spring with AOT improvements, using the <em>java -Dspring.aot.enabled=true -jar spring-data-jpa-aot/target/spring-data-jpa-aot-0.0.1-SNAPSHOT.jar</em> command</li>
<li>Spring Data AOT Repositories, using the <em>java -Dspring.aot.enabled=true -Dspring.aot.repositories.enabled=true -jar spring-data-jpa-aot-repository/target/spring-data-jpa-aot-repository-0.0.1-SNAPSHOT.jar</em> command</li>
</ul>
<p>We&#8217;ll use five entity classes and repositories to try to make the changes more visible. And we&#8217;ll focus on the startup time and memory consumption.</p>
<h3 id="bd-1-build-times-comparison" data-id="1-build-times-comparison">4.1. Build Times Comparison</h3>
<div class="bd-anchor" id="1-build-times-comparison"></div>
<p>As already explained, the new AOT Repositories feature performs additional work at build time to construct the Repositories. So, this means that we expect slower build times when we enable this feature:</p>
<ul>
<li>repositories without AOT: <em>Total time: 11.076 s</em></li>
<li>repositories with AOT: <em>Total time: 17.166 s</em></li>
<li>AOT Repositories: <em>Total time: 25.390 s</em></li>
</ul>
<p><strong>With Spring Data AOT Repositories, if we have syntax errors in JPA methods, we see compile-time errors.</strong> This makes sense, since the transformation of JPA methods to SQL Statements now happens at compile rather than runtime.</p>
<h3 id="bd-2-startup-times-comparison" data-id="2-startup-times-comparison">4.2. Startup Times Comparison</h3>
<div class="bd-anchor" id="2-startup-times-comparison"></div>
<p>Next, we&#8217;ll execute a script that starts each service, and at the same time, it starts trying to hit an endpoint that uses a repository. This way, we can monitor how long it took for the service to start, since the server and the repositories are ready for use.</p>
<p>For the repositories without AOT, the script output was:</p>
<pre><code class="language-less">==== RESULTS ====
time elapsed 10148 millis
Process Specific Memory/CPU (RSS KB / CPU Time): 289840 00:00:28</code></pre>
<p>For the repositories with AOT:</p>
<pre><code class="language-less">==== RESULTS ====
time elapsed 9885 millis
Process Specific Memory/CPU (RSS KB / CPU Time): 291104 00:00:25</code></pre>
<p>And for Spring Data AOT Repositories:</p>
<pre><code class="language-less">==== RESULTS ====
time elapsed 8745 millis
Process Specific Memory/CPU (RSS KB / CPU Time): 292864 00:00:23</code></pre>
<p>This makes perfect sense, since we know that AOT and AOT Repositories target the improvement of startup times. And this is clear even for small projects like ours.</p>
<p>The memory improvement that is advertised by Spring is not shown here, but it makes sense for our small project.</p>
<p>Note, when starting the application without AOT, we should notice a log saying: <em>Starting Application</em>. But when using AOT, it should say <em>Starting AOT-processed Application</em>.</p>
<h3 id="bd-3-comparison-under-load" data-id="3-comparison-under-load">4.3. Comparison Under Load</h3>
<div class="bd-anchor" id="3-comparison-under-load"></div>
<p>Our last test includes a script that sends some traffic to each implementation and compares the performance.</p>
<p>For the repositories without AOT, the script output was:</p>
<pre><code class="language-less">==== RESULTS ====
Total requests: 6688
Success (2xx): 6688
...
Avg duration (measured): 51.7629ms
...
Max memory utilised: 331888</code></pre>
<p>For the repositories with AOT:</p>
<pre><code class="language-less">==== RESULTS ====
Total requests: 7664
Success (2xx): 7664
...
Avg duration (measured): 43.934ms
...
Max memory utilised: 334000</code></pre>
<p>And for Spring Data AOT Repositories:</p>
<pre><code class="language-less">==== RESULTS ====
Total requests: 6673
Success (2xx): 6673
...
Avg duration (measured): 49.0766ms
...
Max memory utilised: 337948</code></pre>
<p><strong>The result doesn&#8217;t show the memory improvement that Spring advertises, but this could be impacted by the project sizes and the data store</strong>.</p>
<h2 id="bd-conclusion" data-id="conclusion">5. Conclusion</h2>
<div class="bd-anchor" id="conclusion"></div>
<p>In this article, we explored the new feature of Spring Boot 4, Spring Data AOT Repositories. We used a simple <em>UserRepository</em> class to demonstrate how Spring Data Repository worked before and what changes exactly this new feature introduced. Finally, we compared the performance implications of using the Spring Data AOT Repositories.</p>
<p>As always, the source code of the examples can be found <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~github.com/eugenp/tutorials/tree/master/persistence-modules/spring-data-jpa-repo-5/">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-data-aot-repositories">Introduction to Spring Data AOT Repositories</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/954210833/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954210833/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f11%2fPersistence-Featured-Image-04-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954210833/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-data-aot-repositories#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-data-aot-repositories/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/954210833/0/baeldung~Introduction-to-Spring-Data-AOT-Repositories/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2024/11/Persistence-Featured-Image-04-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/java-ipv4-ipv6-conversion</feedburner:origLink>
		<title>Convert IPv4 to IPv6 Address in Java</title>
		<link>https://feeds.feedblitz.com/~/954210836/0/baeldung~Convert-IPv-to-IPv-Address-in-Java</link>
					<comments>https://feeds.feedblitz.com/~/954210836/0/baeldung~Convert-IPv-to-IPv-Address-in-Java#respond</comments>
		
		<dc:creator><![CDATA[Ali Imran Nagori]]></dc:creator>
		<pubDate>Wed, 22 Apr 2026 04:14:40 +0000</pubDate>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[IP Address]]></category>
		<category><![CDATA[String Conversions]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/java-ipv4-ipv6-conversion</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Core-Java-1.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="almost done featured" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Learn how to use Java for converting between IPv4 and IPv6 addresses.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/954210836/0/baeldung~Convert-IPv-to-IPv-Address-in-Java">Convert IPv4 to IPv6 Address in Java</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954210836/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Core-Java-1.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-ipv4-ipv6-conversion#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-ipv4-ipv6-conversion/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Core-Java-1.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="almost done featured" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2016/10/social-Core-Java-1.jpg 952w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Core-Java-1-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Core-Java-1-768x402.jpg 768w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 id="bd-overview" data-id="overview">1. Overview</h2>
<div class="bd-anchor" id="overview"></div>
<p>Internet Protocol version 6 or IPv6, defined in RFC 2460, is the latest generation of the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/popular-network-protocols#internet-protocol-ip">Internet Protocol</a>. It replaces the limited IPv4 address space. However, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/ipv4-vs-ipv6#ipv6">IPv6</a> doesn&#8217;t directly interoperate with <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/ipv4-datagram#ipv4-datagram">IPv4</a>. Because of this, devices using different protocols often face compatibility issues.</p>
<p>To solve this, modern systems use techniques like dual-stack, tunneling, and translation. Thus, these methods enable systems to support IPv6 while still working with IPv4. However, <strong>they primarily work at the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/osi-transport-vs-networking-layer#services-of-network-layer">Network Layer</a> (Layer 3)</strong>.</p>
<p>In many cases, developers need a way to represent IPv4 addresses in an IPv6-compatible format. So, they write code to map data between the two formats.</p>
<p>In this tutorial, we see how to convert an IPv4 address to IPv6 using <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/get-started-with-java-series">Java</a>.</p>
<h2 id="bd-what-does-converting-mean" data-id="what-does-converting-mean">2. What Does Converting Mean?</h2>
<div class="bd-anchor" id="what-does-converting-mean"></div>
<p>In reality, <strong>there is no direct conversion from IPv4 to IPv6</strong>. The two protocols differ in structure and design.</p>
<p>Instead, a common approach is to embed IPv4 inside IPv6. This format is called an IPv4-mapped IPv6 address.</p>
<p>In addition, we also have other representations. However, not all are standard today. For example, <strong>IPv4-compatible IPv6 addresses are now deprecated</strong>. In the same way, <em>NAT64</em> and <em>6to4</em> act as transition methods, not true conversions.</p>
<p>So, let&#8217;s look at how to implement the above techniques in Java.</p>
<h2 id="bd-java-implementation" data-id="java-implementation">3. Java Implementation</h2>
<div class="bd-anchor" id="java-implementation"></div>
<p>In essence, Java provides built-in classes to work with IP addresses. The <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-get-ip-url#1-using-the-inetaddress-class"><em>InetAddress</em></a> class supports both IPv4 and IPv6.</p>
<h3 id="bd-1-convert-ipv4-to-ipv6-mapped-address" data-id="1-convert-ipv4-to-ipv6-mapped-address">3.1. Convert IPv4 to IPv6-Mapped Address</h3>
<div class="bd-anchor" id="1-convert-ipv4-to-ipv6-mapped-address"></div>
<p>Let&#8217;s look at the case of a mapped address.</p>
<p>For that, we convert an IPv4 address to an IPv6 format using a standard format:</p>
<pre><code class="language-plaintext">::ffff:w.x.y.z</code></pre>
<p>In the above case, <em>w.x.y.z</em> is the target IPv4 address:</p>
<pre><code class="language-java">String toIpv4MappedIpv6(String ipv4Address) throws UnknownHostException {
    validateIpv4(ipv4Address);
    return "::ffff:" + ipv4Address;
}</code></pre>
<p><strong>This method simply adds the <em>::ffff:</em> prefix</strong>. As a result, we get a valid IPv4-mapped IPv6 address.</p>
<h3 id="bd-2-ipv4-compatible-ipv6-address" data-id="2-ipv4-compatible-ipv6-address">3.2. IPv4-Compatible IPv6 Address</h3>
<div class="bd-anchor" id="2-ipv4-compatible-ipv6-address"></div>
<p>Markedly, the IPv4-compatible IPv6 address format is no longer in use. Still, it helps to understand older systems.</p>
<p><strong>In hex notation, this type of address sets all the leading bits to zero</strong>.</p>
<p>Let&#8217;s again take the IPv4 address <em>w.x.y.z</em>:</p>
<pre><code class="language-plaintext">0000:0000:0000:0000:0000:0000:WWXX:YYZZ</code></pre>
<p>This address can also be compressed by omitting all leading zeroes:</p>
<pre><code class="language-plaintext">::w.x.y.z </code></pre>
<p>Furthermore, we see its implementation:</p>
<pre><code class="language-java">String toIpv4CompatibleIpv6(String ipv4Address) throws UnknownHostException {
    validateIpv4(ipv4Address);
    return "::" + ipv4Address;
}</code></pre>
<p>The above method takes an IPv4 address and returns an IPv6 address.</p>
<p>As a result, an IPv4 address, <em>192.0.2.33</em>, returns IPv4-compatible IPv6 <em>::192.0.2.33.</em></p>
<h3 id="bd-3-nat64-implementation" data-id="3-nat64-implementation">3.3. NAT64 Implementation</h3>
<div class="bd-anchor" id="3-nat64-implementation"></div>
<p>NAT64-style translated addresses typically use a <em>64:ff9b::/96</em> prefix. It&#8217;s then followed by the target IPv4 address.</p>
<p>For example, <strong>an IP address of the form <em>w.x.y.z</em> gets the NAT64 ID <em>64:ff9b::w.x.y.z</em></strong>.</p>
<p>The implementation code remains the same as the last ones:</p>
<pre><code class="language-java">String toNat64Ipv6(String ipv4Address) throws UnknownHostException {
    validateIpv4(ipv4Address);
    return "64:ff9b::" + ipv4Address;
}</code></pre>
<p>Thus, if we have an IPv4 address of <em>192.0.2.33</em>, the resulting address should be <em>64:ff9b::192.0.2.33</em>.</p>
<h3 id="bd-4-6to4-addresses-tunneling" data-id="4-6to4-addresses-tunneling">3.4. <em>6to4</em> Addresses (Tunneling)</h3>
<div class="bd-anchor" id="4-6to4-addresses-tunneling"></div>
<p><em>6to4</em> is a transition method. <strong>It wraps IPv6 packets inside IPv4 packets</strong>. Moreover, for this purpose, Internet Assigned Numbers Authority (<a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.iana.org/">IANA</a>) has assigned the <em>2002::/16</em> block.</p>
<p>For example, the IPv4 address <em>192.0.2.4</em> has a hexadecimal equivalent of <em>C000:0204</em>. <strong>The <em>6to4</em> prefix in this case becomes <em>2002:C000:0204::/48</em></strong>:</p>
<pre><code class="language-java">16 bits (the base) + 32 bits (the IPv4) = 48 bits</code></pre>
<p>Thus, the prefix <em>2002::/16</em> is followed by the <em>32</em> bits of the public IPv4 address.</p>
<p>Let&#8217;s see its Java implementation:</p>
<pre><code class="language-java">String toSixToFourIpv6(String ipv4Address) throws UnknownHostException {
    byte[] bytes = validateAndGetBytes(ipv4Address);
    return String.format("2002:%02x%02x:%02x%02x::",
      bytes[0] &amp; 0xff,
      bytes[1] &amp; 0xff,
      bytes[2] &amp; 0xff,
      bytes[3] &amp; 0xff);
}</code></pre>
<p>The above method converts each IPv4 byte into its hexadecimal representation.</p>
<p>Finally, the result gets appended to the <em>2002::/16</em> prefix.</p>
<h2 id="bd-junit-test" data-id="junit-test">4. JUnit Test</h2>
<div class="bd-anchor" id="junit-test"></div>
<p>To verify the class methods, we can write a simple JUnit test:</p>
<pre><code class="language-java">class Ipv4ToIpv6ConverterUnitTest {
    private final Ipv4ToIpv6Converter converter = new Ipv4ToIpv6Converter();
    @Test
    void whenValidIpv4_thenReturnMappedIpv6() throws Exception {
        String result = converter.toIpv4MappedIpv6("192.168.1.1");
        assertEquals("::ffff:192.168.1.1", result);
    }
}</code></pre>
<p>Thus, we can check if the output matches the expected value. In the same way, we can write tests for other methods.</p>
<h2 id="bd-use-cases" data-id="use-cases">5. Use Cases</h2>
<div class="bd-anchor" id="use-cases"></div>
<p>IPv4-mapped IPv6 addresses help both protocols work together in dual-stack systems.</p>
<p>Users can also use a tunneling mechanism, like <em>6to4</em>, if they don&#8217;t have dual-stack support.</p>
<p>Similarly, we have translators like NAT64. They also help in interoperability between an IPv4 device and an IPv6 device.</p>
<p>The general idea of the conversion is to enable the different protocols to work in sync.</p>
<h2 id="bd-conclusion" data-id="conclusion">6. Conclusion</h2>
<div class="bd-anchor" id="conclusion"></div>
<p>In this article, we discussed the conversion between IPv4 and IPv6 with Java. Since both IP protocols differ in structure and semantics, we can&#8217;t truly convert IPv4 into IPv6.</p>
<p>Because of this, <strong>the above approaches don&#8217;t turn an IPv4 host into a native IPv6 host</strong>. Instead, they provide a way for the systems to work together. Java simplifies this process through classes like InetAddress and byte handling.</p>
<p>As a result, applications can support both address formats efficiently.</p>
<p>The complete code for this article is available <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-networking-5">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-ipv4-ipv6-conversion">Convert IPv4 to IPv6 Address in Java</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/954210836/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/954210836/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Core-Java-1.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/954210836/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-ipv4-ipv6-conversion#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-ipv4-ipv6-conversion/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/954210836/0/baeldung~Convert-IPv-to-IPv-Address-in-Java/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2016/10/social-Core-Java-1-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/java-weekly-642</feedburner:origLink>
		<title>Java Weekly, Issue 642</title>
		<link>https://feeds.feedblitz.com/~/953941595/0/baeldung~Java-Weekly-Issue</link>
					<comments>https://feeds.feedblitz.com/~/953941595/0/baeldung~Java-Weekly-Issue#respond</comments>
		
		<dc:creator><![CDATA[baeldung]]></dc:creator>
		<pubDate>Fri, 17 Apr 2026 10:45:25 +0000</pubDate>
				<category><![CDATA[Weekly Review]]></category>
		<category><![CDATA[no-ads]]></category>
		<category><![CDATA[no-after-post]]></category>
		<category><![CDATA[no-before-post]]></category>
		<category><![CDATA[no-optins]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203498</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Interesting AI-focused pieces and starting to look forward towards JDK 27.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953941595/0/baeldung~Java-Weekly-Issue">Java Weekly, Issue 642</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953941595/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Weekly-Reviews-4.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-weekly-642#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-weekly-642/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg 952w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-768x402.jpg 768w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 style="text-align: left;" id="bd-spring-and-java" data-id="spring-and-java">1.<strong> Spring and Java</strong></h2>
<div class="bd-anchor" id="spring-and-java"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.infoq.com/articles/spring-team-spring-7-boot-4/">&gt;&gt; The Spring Team on Spring Framework 7 and Spring Boot 4</a></strong> [<span style="color: #993300;">infoq.com</span>]</p>
<p>A walk through what&#8217;s landed in Spring Framework 7 and Spring Boot 4 &#8211; the direction, the rationale, and what it means for the ecosystem. Good overview.</p>
<h4><strong>Also worth reading:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/13/quality-heads-up/" target="_blank" rel="noopener"><strong>Quality Outreach Heads-up &#8211; JDK 27: Obsolete Translation Resources Removed</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.jetbrains.com/idea/2026/04/using-spring-data-jdbc-with-kotlin/" target="_blank" rel="noopener"><strong>Using Spring Data JDBC With Kotlin</strong></a> [<span style="color: #800000;">jetbrains.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/how-i-automated-weekly-twitter-x-posts-with-java-jbang-and-github-actions/" target="_blank" rel="noopener"><strong>How I Automated Weekly Twitter/X Posts With Java, JBang and GitHub Actions</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/boxlang-ai-deep-dive-part-1-of-7-the-skills-revolution-%f0%9f%8e%93/" target="_blank" rel="noopener"><strong>BoxLang AI Deep Dive — Part 1 of 7: The Skills Revolution</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://quarkus.io/blog/reflection-free-jsckson-serializers/" target="_blank" rel="noopener"><strong>Enabling reflection-free Jackson serializers by default</strong></a> [<span style="color: #800000;">quarkus.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/15/spring-ai-session-management" target="_blank" rel="noopener"><strong>Spring AI Agentic Patterns (Part 7): Session API — Event-Sourced Short-Term Memory with Context Compaction</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
</ul>
<h4><strong>Webinars and presentations:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/foojay-podcast-93/" target="_blank" rel="noopener"><strong>Foojay Podcast #93: Update Your JDK, Read More Code, and Talk to Your Users: Interviews From VoxxedDays Amsterdam</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/09/podcast-054/" target="_blank" rel="noopener"><strong>Episode 54 “How JDK 26 Improves G1&#8217;s Throughput” [AtA]</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/09/a-bootiful-podcast-ana-mark-kropf" target="_blank" rel="noopener"><strong>A Bootiful Podcast: Mark Kropf on AI orchestration</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
</ul>
<h4><strong>Time to upgrade:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/14/java-vscode-extension-update/" target="_blank" rel="noopener"><strong>Oracle Java Extension for Visual Studio Code Version 25.1.0 Is Now Available</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/elastic/elasticsearch/releases/tag/v9.3.3" target="_blank" rel="noopener"><strong>Elasticsearch 9.3.3</strong></a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/elastic/elasticsearch/releases/tag/v9.2.8" target="_blank" rel="noopener"><strong>9.2.8</strong></a> and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/elastic/elasticsearch/releases/tag/v8.19.14" target="_blank" rel="noopener"><strong>8.19.14</strong></a> [<span style="color: #800000;">github.com/elastic</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/grails/grails-core/releases/tag/v7.1.0" target="_blank" rel="noopener"><strong>Grails 7.1.0</strong></a> [<span style="color: #800000;">github.com/grails</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/micronaut-projects/micronaut-core/releases/tag/v4.10.21" target="_blank" rel="noopener"><strong>Micronaut Core 4.10.21</strong></a> [<span style="color: #800000;">github.com/micronaut-projects</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/oracle/helidon/releases/tag/4.4.1" target="_blank" rel="noopener"><strong>Helidon 4.4.1</strong></a> [<span style="color: #800000;">github.com/oracle</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/apache/camel/releases/tag/camel-4.19.0" target="_blank" rel="noopener"><strong>Camel 4.19.0</strong></a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/apache/camel/releases/tag/camel-4.18.2" target="_blank" rel="noopener"><strong>4.18.2</strong></a> and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/apache/camel/releases/tag/camel-4.14.6" target="_blank" rel="noopener"><strong>4.14.6</strong></a> [<span style="color: #800000;">github.com/apache</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/payara/Payara/releases/tag/payara-server-7.2026.4" target="_blank" rel="noopener"><strong>Payara Platform Community 7.2026.4</strong></a> [<span style="color: #800000;">github.com/payara</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/micrometer-metrics/micrometer/releases/tag/v1.16.5" target="_blank" rel="noopener"><strong>Micrometer 1.16.5</strong></a> and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/micrometer-metrics/micrometer/releases/tag/v1.15.11" target="_blank" rel="noopener"><strong>1.15.11</strong></a> [<span style="color: #800000;">github.com/micrometer-metrics</span>]</li>
</ul>
<h2 style="text-align: left;" id="bd-technical-amp-musings" data-id="technical-amp-musings">2.<strong> Technical &amp; Musings</strong></h2>
<div class="bd-anchor" id="technical-amp-musings"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.frankel.ch/agentic-github-workflows/">&gt;&gt; A GitHub agentic workflow</a></strong> [<span style="color: #993300;">frankel.ch</span>]</p>
<p>A hands-on walkthrough of wiring an agentic workflow into GitHub &#8211; using issues and PRs as the coordination surface. Weekend reading.</p>
<h4><strong>Also worth reading:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://lucumr.pocoo.org/2026/4/11/the-center-has-a-bias/" target="_blank" rel="noopener"><strong>The Center Has a Bias</strong></a> [<span style="color: #800000;">lucumr.pocoo.org</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.jbrains.ca/permalink/when-you-can-safely-leave-sprints-behind" target="_blank" rel="noopener"><strong>When You Can Safely Leave Sprints Behind</strong></a> [<span style="color: #800000;">jbrains.ca</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://event-driven.io/en/passive_aggressive_events/" target="_blank" rel="noopener"><strong>Anti-patterns in event modelling &#8211; Passive-Aggressive Events</strong></a> [<span style="color: #800000;">event-driven.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://netflixtechblog.com/evaluating-netflix-show-synopses-with-llm-as-a-judge-6269251e6f28" target="_blank" rel="noopener"><strong>Evaluating Netflix Show Synopses with LLM-as-a-Judge</strong></a> [<span style="color: #800000;">netflixtechblog.com</span>]</li>
</ul>
<h2 style="text-align: left;" id="bd-pick-of-the-week" data-id="pick-of-the-week">3.<strong> Pick of the Week</strong></h2>
<div class="bd-anchor" id="pick-of-the-week"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://sive.rs/balance">&gt;&gt; How to do what you love and make good money</a></strong> [<span style="color: #993300;">sive.rs</span>]</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-weekly-642">Java Weekly, Issue 642</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953941595/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953941595/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Weekly-Reviews-4.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953941595/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-weekly-642#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-weekly-642/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953941595/0/baeldung~Java-Weekly-Issue/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/java-regex-resolving-patternsyntaxexception</feedburner:origLink>
		<title>Resolving PatternSyntaxException: Unclosed character class</title>
		<link>https://feeds.feedblitz.com/~/953868626/0/baeldung~Resolving-PatternSyntaxException-Unclosed-character-class</link>
					<comments>https://feeds.feedblitz.com/~/953868626/0/baeldung~Resolving-PatternSyntaxException-Unclosed-character-class#respond</comments>
		
		<dc:creator><![CDATA[Neetika Khandelwal]]></dc:creator>
		<pubDate>Thu, 16 Apr 2026 03:30:58 +0000</pubDate>
				<category><![CDATA[Java String]]></category>
		<category><![CDATA[Exception]]></category>
		<category><![CDATA[Regex]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203471</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Learn about the PatternSyntaxException: Unclosed character class which is a common yet avoidable issue in Java regular expressions</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953868626/0/baeldung~Resolving-PatternSyntaxException-Unclosed-character-class">Resolving PatternSyntaxException: Unclosed character class</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953868626/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f07%2fJava-Featured-15-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-regex-resolving-patternsyntaxexception#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-regex-resolving-patternsyntaxexception/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15-1024x536.jpg 1024w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15-768x402.jpg 768w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15-100x52.jpg 100w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15.jpg 1200w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 id="bd-overview" data-id="overview">1. Overview</h2>
<div class="bd-anchor" id="overview"></div>
<p>When we work with regular expressions in Java, even a small syntax mistake can break our application at runtime. One of the most common errors we encounter is:</p>
<pre><code class="language-java">java.util.regex.PatternSyntaxException: Unclosed character class</code></pre>
<p>In this tutorial, we&#8217;ll explore why this happens, how to reproduce it, and how to fix it. We also cover a real-world issue involving <em>split()</em> that often triggers this exception.</p>
<h2 id="bd-understanding-character-classes" data-id="understanding-character-classes">2. Understanding Character Classes</h2>
<div class="bd-anchor" id="understanding-character-classes"></div>
<p><strong>A character class in <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/regular-expressions-java">regex</a> allows us to match</strong> <strong data-start="704" data-end="742">any one character from a given set</strong>. This is one of the most commonly used regex constructs in Java.
<br>
Let us first look at a simple example of a character class:</p>
<pre><code class="language-java">"[abc]"</code></pre>
<p>In this pattern, the regex engine matches either <em>a</em>, <em>b</em>, or <em>c</em>. <strong>We should always remember that a character class starts with [ and must end with ]. </strong>We can also define ranges when working with larger sets of characters:</p>
<pre><code class="language-java">"[a-z]"</code></pre>
<p>This pattern matches any lowercase English letter from <em>a</em> to <em>z</em>. <strong>If we forget to close the bracket, Java will throw a runtime exception.</strong></p>
<h2 id="bd-reproducing-the-exception" data-id="reproducing-the-exception">3. Reproducing the Exception</h2>
<div class="bd-anchor" id="reproducing-the-exception"></div>
<p>To better understand the problem, let us intentionally write an invalid regex pattern. This helps us see exactly how Java reacts:</p>
<pre><code class="language-java">public class RegexExample {
    public static void main(String[] args) {
        Pattern.compile("[a-z");
    }
}</code></pre>
<p>In the above example, we try to compile a regex that starts a character class but never closes it. When we run this code, Java throws the following exception:</p>
<pre><code class="language-java">java.util.regex.PatternSyntaxException: Unclosed character class near index 4
[a-z
    ^</code></pre>
<p>This clearly indicates that the regex parser expected a closing ] but did not find one.</p>
<h2 id="bd-fixing-the-exception" data-id="fixing-the-exception">4. Fixing the Exception</h2>
<div class="bd-anchor" id="fixing-the-exception"></div>
<p>Now that we understand the problem, fixing it becomes straightforward. We simply need to close the character class properly:</p>
<pre><code class="language-java">Pattern.compile("[a-z]");</code></pre>
<p>After making this change, the pattern compiles successfully without any errors. <strong data-start="2266" data-end="2357">We should always verify that every opening bracket has a corresponding closing bracket.</strong></p>
<h2 id="bd-common-causes-of-this-exception" data-id="common-causes-of-this-exception">5. Common Causes of This Exception</h2>
<div class="bd-anchor" id="common-causes-of-this-exception"></div>
<p>Let&#8217;s have a look at some of the common causes of <em>PatternSyntaxException</em>.</p>
<h3 data-start="2406" data-end="2440" id="bd-1-missing-closing-bracket" data-id="1-missing-closing-bracket">5.1. Missing Closing Bracket</h3>
<div class="bd-anchor" id="1-missing-closing-bracket"></div>
<p>One of the most frequent mistakes is forgetting to close the character class:</p>
<pre><code class="language-java">Pattern.compile("[0-9");</code></pre>
<p>This pattern is incomplete and results in a runtime exception. We can fix it by adding the missing closing bracket:</p>
<pre><code class="language-java">Pattern.compile("[0-9]");</code></pre>
<p><strong>Even a small omission like this can break the entire regex.</strong></p>
<h3 data-start="2791" data-end="2827" id="bd-2-incorrect-nested-patterns" data-id="2-incorrect-nested-patterns">5.2. Incorrect Nested Patterns</h3>
<div class="bd-anchor" id="2-incorrect-nested-patterns"></div>
<p>Sometimes, while writing a complex regex, we accidentally introduce extra brackets:</p>
<pre><code class="language-java">Pattern.compile("[a-zA-Z[0-9]");</code></pre>
<p>In this pattern, we have an extra [ inside the character class.<strong> Character classes do not support nesting using [ like this, so the regex becomes invalid</strong>. As a result, Java throws a <em>PatternSyntaxException</em>.</p>
<p>To fix this, we should remove the unnecessary bracket and define the character set correctly:</p>
<pre><code class="language-java">Pattern.compile("[a-zA-Z0-9]");</code></pre>
<p>Now the pattern is valid and matches any alphanumeric character. <strong data-start="983" data-end="1081">Instead of nesting, we should combine all required characters within a single character class.</strong></p>
<h2 id="bd-issue-with-split" data-id="issue-with-split">6. Issue with <em data-start="3673" data-end="3682">split()</em></h2>
<div class="bd-anchor" id="issue-with-split"></div>
<p>Let us now look at a practical example that often causes confusion in real projects. Before jumping into the issue, we first define a sample 2D array.</p>
<pre><code class="language-java">String[][] array2d = {
    {"a", "b"},
    {"c", "d"}
};</code></pre>
<p>In many cases, we convert this array into a string using <em data-start="656" data-end="679">Arrays.deepToString()</em> for quick inspection or processing:</p>
<pre><code class="language-java">String str = Arrays.deepToString(array2d);
System.out.println(str);</code></pre>
<p>When we run this, the output looks like:</p>
<pre><code class="language-java">[[a, b], [c, d]]</code></pre>
<p><strong data-start="894" data-end="953">Notice that the output contains nested square brackets.</strong> This is important for understanding the issue. Now, let us attempt to split this string into individual rows. At first glance, the following code looks correct:</p>
<pre><code class="language-java">String[][] split = new String[1][rows];
split[0] = str.split("], [");</code></pre>
<p>However, when we run this code, we encounter a runtime exception:</p>
<pre><code class="language-java">java.util.regex.PatternSyntaxException: Unclosed character class</code></pre>
<p>This happens because <em data-start="1397" data-end="1406">split()</em> expects a <strong data-start="1417" data-end="1426">regex</strong>, not a plain string. The pattern: &#8220;], [&#8221; is interpreted incorrectly, since [ and ] are special characters in regex. <strong data-start="1578" data-end="1683">As a result, the regex engine treats [ as the start of a character class, leading to the exception.</strong>
<br>
To resolve this issue, we need to escape the square brackets so they are treated as literal characters:</p>
<pre><code class="language-java">split[0] = str.split("\\], \\[");</code></pre>
<p>With this change, the regex becomes valid, and the code works as expected. <strong data-start="4534" data-end="4609">Proper escaping ensures that special characters do not break our regex. </strong>Although the fix works, we can further improve the solution for cleaner output. The result of <em data-start="4745" data-end="4768">Arrays.deepToString()</em> contains outer brackets that we may want to remove:</p>
<pre><code class="language-java">String str = Arrays.deepToString(array2d);
str = str.substring(1, str.length() - 1);
String[] result = str.split("\\], \\[");</code></pre>
<p>By trimming the outer brackets, we get a cleaner split result. <strong data-start="5027" data-end="5102">This makes the output easier to process and avoids unwanted characters.</strong></p>
<h2 id="bd-conclusion" data-id="conclusion">7. Conclusion</h2>
<div class="bd-anchor" id="conclusion"></div>
<p>In this article, we saw that the <em>PatternSyntaxException: Unclosed character class</em> is a common yet avoidable issue in Java. It usually occurs due to missing brackets or incorrect handling of special characters like [ and ]. By carefully writing regex patterns, properly escaping characters in methods like <em>split()</em>, and validating inputs, we can build more reliable applications. A small attention to detail in regex can prevent major runtime issues.</p>
<p>As always, the code presented in this article is available <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-regex-4">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-regex-resolving-patternsyntaxexception">Resolving PatternSyntaxException: Unclosed character class</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953868626/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953868626/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f07%2fJava-Featured-15-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953868626/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-regex-resolving-patternsyntaxexception#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-regex-resolving-patternsyntaxexception/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953868626/0/baeldung~Resolving-PatternSyntaxException-Unclosed-character-class/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-15-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/spring-boot-scheduled-db-cron-expression</feedburner:origLink>
		<title>Getting a Cron Expression From Database for a Spring Boot Scheduled Job</title>
		<link>https://feeds.feedblitz.com/~/953867825/0/baeldung~Getting-a-Cron-Expression-From-Database-for-a-Spring-Boot-Scheduled-Job</link>
					<comments>https://feeds.feedblitz.com/~/953867825/0/baeldung~Getting-a-Cron-Expression-From-Database-for-a-Spring-Boot-Scheduled-Job#respond</comments>
		
		<dc:creator><![CDATA[Kai Yuan]]></dc:creator>
		<pubDate>Thu, 16 Apr 2026 03:22:02 +0000</pubDate>
				<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[popular]]></category>
		<category><![CDATA[Spring Scheduling]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203448</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Explore two ways to get a scheduled job's cron value from a database in Spring Boot.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953867825/0/baeldung~Getting-a-Cron-Expression-From-Database-for-a-Spring-Boot-Scheduled-Job">Getting a Cron Expression From Database for a Spring Boot Scheduled Job</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953867825/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f11%2fSpring-Boot-Featured-Image-02-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-boot-scheduled-db-cron-expression#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-boot-scheduled-db-cron-expression/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-1024x536.jpg 1024w, https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-768x402.jpg 768w, https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-100x52.jpg 100w, https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-600x314.jpg 600w, https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02.jpg 1200w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 id="bd-overview" data-id="overview">1. Overview</h2>
<div class="bd-anchor" id="overview"></div>
<p>Spring Boot allows us to easily schedule a job, for example, using the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-scheduled-tasks"><em>@Scheduled</em></a> annotation. Sometimes, we don&#8217;t want to hardcode the scheduling parameters, such as the cron expression. Instead, we would like to schedule a job using a cron expression from a database.</p>
<p>In this tutorial, we&#8217;ll first explore two approaches to achieve it. Further, we&#8217;ll discuss when to use which.</p>
<h2 id="bd-introduction-to-the-problem" data-id="introduction-to-the-problem">2. Introduction to the Problem</h2>
<div class="bd-anchor" id="introduction-to-the-problem"></div>
<p>When we work with Spring scheduling, the most straightforward option is usually to place the cron expression directly in <em>@Scheduled, </em>for example:</p>
<pre><code class="language-java">@Scheduled(cron = "*/5 * * * * ?")
public void run() {
    // job logic
}</code></pre>
<p>This works well, but it also hardcodes the schedule into the application.</p>
<p>The problem appears when we want to fetch the cron expression from a database. This is because we cannot simply write something like this:</p>
<pre><code class="language-java">private String cronExpression = loadFromDatabase();
@Scheduled(cron = cronExpression)
public void run() {
    // invalid approach
}</code></pre>
<p>If we compile this code, the compiler will complain:</p>
<pre><code class="language-bash">java: element value must be a constant expression</code></pre>
<p>The reason is that <strong>the <em>cron</em> attribute in an annotation cannot be populated from an arbitrary runtime variable.</strong> In practice, we either need an indirection that Spring can resolve for us, or we need to move away from annotation-driven scheduling altogether.</p>
<p>In this tutorial, we&#8217;ll explore both approaches. But let&#8217;s do some preparation before we dive into the solutions.</p>
<h2 id="bd-preparing-data-in-a-database" data-id="preparing-data-in-a-database">3. Preparing Data in a Database</h2>
<div class="bd-anchor" id="preparing-data-in-a-database"></div>
<p>For this tutorial, we use a small <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-boot-h2-database">H2</a> in-memory database. Also, for simplicity, we&#8217;ll skip <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa">Spring Data JPA</a> configurations</p>
<h3 id="bd-1-creating-a-simple-table" data-id="1-creating-a-simple-table">3.1. Creating a Simple Table</h3>
<div class="bd-anchor" id="1-creating-a-simple-table"></div>
<p>We want our Spring Boot application to <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-h2-automatically-create-schemas">automatically create a database table and insert some data into it</a> when it starts. Therefore, let&#8217;s prepare a <em>schema.sql</em> file:</p>
<pre><code class="language-sql">CREATE TABLE IF NOT EXISTS cron_config (
    id BIGINT PRIMARY KEY,
    cron_expression VARCHAR(255) NOT NULL
);</code></pre>
<p>As we can see, the <em>cron_config</em> table is intentionally minimal. <strong>We only need an identifier and the cron expression itself</strong>.</p>
<p>Next, let&#8217;s create a <em>data.sql</em> file to insert a row into the table:</p>
<pre><code class="language-sql">INSERT INTO cron_config (id, cron_expression) VALUES (1, '*/5 * * * * ?');</code></pre>
<p>We insert a single row so the application has a cron value as soon as it starts. So by default, <strong>the schedule runs every five seconds</strong>.</p>
<h3 id="bd-2-preparing-the-entity-and-the-repository-classes" data-id="2-preparing-the-entity-and-the-repository-classes">3.2. Preparing the <em>Entity</em> and the <em>Repository</em> Classes</h3>
<div class="bd-anchor" id="2-preparing-the-entity-and-the-repository-classes"></div>
<p>The corresponding JPA entity is equally small:</p>
<pre><code class="language-java">@Entity
@Table(name = "cron_config")
public class CronEntity {
    @Id
    private Long id;
    private String cronExpression;
    // ... the default constructor, getters and setters are omitted
}</code></pre>
<p>The repository is just as simple and gives us <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-data-3-crud-repository-interfaces">the CRUD operations</a> we need:</p>
<pre><code class="language-java">public interface CronConfigRepository extends JpaRepository&lt;CronEntity, Long&gt; {
}</code></pre>
<p>With these pieces in place, we can read and update cron values from the database.</p>
<p>Now, let&#8217;s see how to tell Spring to schedule jobs using the cron expression we stored in the database.</p>
<h2 id="bd-using-a-cronloader-bean" data-id="using-a-cronloader-bean">4. Using a <em>cronLoader</em> Bean</h2>
<div class="bd-anchor" id="using-a-cronloader-bean"></div>
<p>In our first approach, we would like to keep the <em>@Scheduled </em>annotation, but avoid placing the cron expression directly in the annotation. Instead, <strong>we&#8217;ll create a Spring Bean to read the cron expression from our database and reference the bean in <em>@Scheduled&#8217;s cron</em> attribute.</strong></p>
<h3 id="bd-1-defining-the-cronloader-bean-to-load-the-cron-expression" data-id="1-defining-the-cronloader-bean-to-load-the-cron-expression">4.1. Defining the <em>cronLoader</em> Bean to Load the Cron Expression</h3>
<div class="bd-anchor" id="1-defining-the-cronloader-bean-to-load-the-cron-expression"></div>
<p>We start with a small configuration class that defines a bean named <em>cronLoader</em>:</p>
<pre><code class="language-java">@Configuration
public class CronLoaderConfig {
    @Bean
    String cronLoader(CronConfigRepository repository) {
        return repository.findById(1L)
          .map(CronEntity::getCronExpression)
          .orElseThrow(() -&gt; new RuntimeException("Cron expression not found in DB"));
    }
}</code></pre>
<p>As the code above shows, this bean is pretty straightforward. <strong>It reads the cron expression from the row with <em>id = 1</em> and returns it as a </strong><em><strong>String</strong>.</em></p>
<h3 id="bd-2-referencing-the-bean-from-scheduled" data-id="2-referencing-the-bean-from-scheduled">4.2. Referencing the Bean from <em>@Scheduled</em></h3>
<div class="bd-anchor" id="2-referencing-the-bean-from-scheduled"></div>
<p>Next, <strong>we can reference that bean through <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-expression-language">SpEL</a> in our scheduled job</strong>:</p>
<pre><code class="language-java">@Component
public class AnnotationScheduledJob {
    private static final Logger log = LoggerFactory.getLogger(AnnotationScheduledJob.class);
    @Scheduled(cron = "#{@cronLoader}")
    public void run() {
        log.info("&#x2705; [{}] Job executed - cron loaded from DB via @Scheduled", now());
    }
}</code></pre>
<p>This is the key idea: <strong>we still use <em>@Scheduled,</em> but the cron expression comes from the <em>cronLoader</em> bean instead of being embedded directly in the annotation.</strong></p>
<p>Also, our job does nothing but print a line with the execution time, so we can verify whether the executions match our cron expression in the database.</p>
<p>Next, let&#8217;s verify if the job scheduling works as we expected.</p>
<h3 id="bd-3-starting-the-application-and-observing-the-console-outputs" data-id="3-starting-the-application-and-observing-the-console-outputs">4.3. Starting the Application and Observing the Console Outputs</h3>
<div class="bd-anchor" id="3-starting-the-application-and-observing-the-console-outputs"></div>
<p>If we start our Spring Boot application, we can see these lines in the console log:</p>
<pre><code class="language-bash">...
... AnnotationScheduledJob : &#x2705; [10:00:05.002] Job executed - cron loaded from DB via @Scheduled
... AnnotationScheduledJob : &#x2705; [10:00:10.001] Job executed - cron loaded from DB via @Scheduled
... AnnotationScheduledJob : &#x2705; [10:00:15.000] Job executed - cron loaded from DB via @Scheduled
... AnnotationScheduledJob : &#x2705; [10:00:20.001] Job executed - cron loaded from DB via @Scheduled
...</code></pre>
<p>Because our <em>data.sql</em> inserts &#8220;<em>*/5 * * * * ?&#8221; </em>as the cron expression, we see the annotation-based job log roughly every five seconds. This gives us a straightforward way to verify that the cron value is being loaded from the database.</p>
<h3 id="bd-4-limitation-of-the-cronloader-bean-approach" data-id="4-limitation-of-the-cronloader-bean-approach">4.4. Limitation of the <em>cronLoader</em> Bean Approach</h3>
<div class="bd-anchor" id="4-limitation-of-the-cronloader-bean-approach"></div>
<p>This approach is convenient, but it comes with an important limitation.</p>
<p>Spring loads the cron value when it creates the <em>cronLoader</em> bean during application startup. After that, the scheduled method continues using the resolved value.</p>
<p><strong>If we update the <em>cron_config</em> table later, the schedule won&#8217;t automatically change for the running application.</strong> In practice, we would typically need to restart the application to pick up the new value.</p>
<p>So, <strong>this approach is a good fit only when loading the schedule once at startup is acceptable.</strong></p>
<h2 id="bd-using-springs-schedulingconfigurer" data-id="using-springs-schedulingconfigurer">5. Using Spring&#8217;s <em>SchedulingConfigurer</em></h2>
<div class="bd-anchor" id="using-springs-schedulingconfigurer"></div>
<p>If we want our scheduled jobs to react to database changes without restarting, we need a more dynamic solution. Next, let&#8217;s dive in.</p>
<h3 id="bd-1-implementing-schedulingconfigurer" data-id="1-implementing-schedulingconfigurer">5.1. Implementing <em>SchedulingConfigurer</em></h3>
<div class="bd-anchor" id="1-implementing-schedulingconfigurer"></div>
<p>Instead of relying on the <em>@Scheduled</em> annotation, <strong>we can implement Spring&#8217;s <em>SchedulingConfigurer</em> and register our own trigger task</strong>.</p>
<p>First, let&#8217;s create a <em>DynamicScheduledConfig</em> configuration class implementing <em>SchedulingConfigurer</em>:</p>
<pre><code class="language-java">@Configuration
public class DynamicScheduledConfig implements SchedulingConfigurer {
    private static final Logger log = LoggerFactory.getLogger(DynamicScheduledConfig.class);
    private final CronConfigRepository repository;
    public DynamicScheduledConfig(CronConfigRepository repository) {
        this.repository = repository;
    }
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -&gt; log.info(
          "&#x2705; [{}] DynamicScheduledConfig executed - cron re-read from DB per execution",
          now()), triggerContext -&gt; {
            String cronExpression = repository.findById(1L)
              .map(CronEntity::getCronExpression)
              .orElseThrow(() -&gt; new RuntimeException("Cron expression not found in DB"));
            return new CronTrigger(cronExpression).nextExecution(triggerContext);
        });
    }
}</code></pre>
<p>Next, let&#8217;s understand how the <em>configureTasks()</em> method works:</p>
<p>First, we register a task with the <em>addTriggerTask(&#8230;)</em> method. The <em>addTriggerTask()</em> method has two parameters: <strong>a <em>Runnable</em> (the &#8220;What&#8221;) that contains the work we want to execute in this task and a <em>Trigger</em> object (the &#8220;When&#8221;) that specifies when the task should be triggered</strong>.</p>
<p>In our example, our task simply prints a log with the current time.</p>
<p>The <em>Trigger</em> parameter is the &#8220;magic&#8221; part of the implementation. <strong>It calculates the next execution time every time the task finishes:</strong></p>
<ul>
<li>Fetching the cron expression from our database using the injected <em>repository</em></li>
<li>Creating a new <em>CronTrigger</em> object from the cron expression on the fly, and Spring asks that trigger for the next execution time</li>
</ul>
<p>This means that if we change the cron expression in our database, the trigger callback will pick up the new value immediately when it calculates the next execution time. This is the main difference from the <em>cronLoader</em> bean approach: <strong>the cron expression is re-read from the database whenever Spring calculates the next execution time.</strong></p>
<h3 id="bd-2-a-simple-rest-controller-to-update-the-cron-expression-in-our-database" data-id="2-a-simple-rest-controller-to-update-the-cron-expression-in-our-database">5.2. A Simple REST Controller to Update the Cron Expression in Our Database</h3>
<div class="bd-anchor" id="2-a-simple-rest-controller-to-update-the-cron-expression-in-our-database"></div>
<p>For easier testing, let&#8217;s create a simple REST controller that allows us to quickly update the database record by HTTP request:</p>
<pre><code class="language-java">@RestController
public class CronController {
    private static final Logger log = LoggerFactory.getLogger(CronController.class);
    private final CronConfigRepository repository;
    public CronController(CronConfigRepository repository) {
        this.repository = repository;
    }
    @GetMapping("/cron")
    public String updateCron() {
        CronEntity cronEntity = repository.findById(1L)
          .orElseThrow(() -&gt; new RuntimeException("Cron expression not found in database"));
        cronEntity.setCronExpression("*/10 * * * * ?");
        repository.save(cronEntity);
        String msg = "[DB] &#x23f0; Updated cron expression in DB to: */10 * * * * ?";
        log.info(msg);
        return msg;
    }
}</code></pre>
<p>As the example shows, for simplicity, <strong>this endpoint always sets the cron to run every 10 seconds</strong>.</p>
<p>Next, let&#8217;s verify if the <em>SchedulingConfigurer</em> approach can always reschedule the job according to the database change.</p>
<h3 id="bd-3-starting-the-application-and-observing-the-console-outputs-1" data-id="3-starting-the-application-and-observing-the-console-outputs-1">5.3. Starting the Application and Observing the Console Outputs</h3>
<div class="bd-anchor" id="3-starting-the-application-and-observing-the-console-outputs-1"></div>
<p>To make the logs easier to read during the demonstration, we can temporarily comment out the annotation-based scheduling line in <em>AnnotationScheduledJob</em> so that only the dynamic task is running:</p>
<pre><code class="language-java">@Component
public class AnnotationScheduledJob {
    // ...
    // @Scheduled(cron = "#{@cronLoader}")  &lt;-- comment out
    public void run() {
        // ...
    }
}</code></pre>
<p>Next, let&#8217;s launch our Spring Boot application. Once it starts, the scheduled job will also begin. Log outputs similar to these will appear in the console:</p>
<pre><code class="language-bash">... DynamicScheduledConfig : &#x2705; [10:05:05.001] DynamicScheduledConfig executed - cron re-read from DB per execution
... DynamicScheduledConfig : &#x2705; [10:05:10.001] DynamicScheduledConfig executed - cron re-read from DB per execution
... DynamicScheduledConfig : &#x2705; [10:05:15.001] DynamicScheduledConfig executed - cron re-read from DB per execution
... DynamicScheduledConfig : &#x2705; [10:05:20.000] DynamicScheduledConfig executed - cron re-read from DB per execution</code></pre>
<p>Because the <em>data.sql</em> file still seeds <em>&#8220;*/5 * * * * ?&#8221;</em>, the dynamic task initially runs about every five seconds.</p>
<p>Next, let&#8217;s call the <em>&#8220;/cron&#8221;</em> endpoint to update the cron expression. For example, we can launch this <em>curl</em> command to send a GET request:</p>
<pre><code class="language-bash">curl http://localhost:8080/cron</code></pre>
<p>Then, in the Spring Boot application console, we can see this log, meaning the cron expression has been changed to &#8220;every 10 seconds&#8221;:</p>
<pre><code class="language-bash">... CronController : [DB] &#x23f0; Updated cron expression in DB to: */10 * * * * ?</code></pre>
<p>After that, the dynamic task should start following the new interval. In other words, instead of firing every five seconds, subsequent executions should move to a ten-second rhythm:</p>
<pre><code class="language-bash">... DynamicScheduledConfig : &#x2705; [10:05:30.000] DynamicScheduledConfig executed - cron re-read from DB per execution
... DynamicScheduledConfig : &#x2705; [10:05:40.002] DynamicScheduledConfig executed - cron re-read from DB per execution
... DynamicScheduledConfig : &#x2705; [10:05:50.000] DynamicScheduledConfig executed - cron re-read from DB per execution
... DynamicScheduledConfig : &#x2705; [10:05:60.000] DynamicScheduledConfig executed - cron re-read from DB per execution</code></pre>
<p>This demonstrates the main benefit of <em>SchedulingConfigurer:</em> <strong>we can change the cron expression in the database and let the running application adapt without a restart.</strong></p>
<h2 id="bd-conclusion" data-id="conclusion">6. Conclusion</h2>
<div class="bd-anchor" id="conclusion"></div>
<p>In this article, we explored two ways to get a scheduled job&#8217;s cron value from a database in Spring Boot.</p>
<p>With the <em>cronLoader</em> bean approach, we keep the implementation simple and continue using <em>@Scheduled,</em> but <strong>we only load the cron value once during startup.</strong></p>
<p>With <em>SchedulingConfigurer,</em> we take control of task registration and re-read the cron expression from the database whenever Spring calculates the next execution time. <strong>This makes the schedule dynamic and allows runtime updates.</strong></p>
<p>So if we only need a startup-time value, a bean-backed <em>@Scheduled</em> setup is often enough. But if we want truly dynamic scheduling, <em>SchedulingConfigurer</em> is the better choice.</p>
<p>As always, the complete source code for the examples is available <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eugenp/tutorials/tree/master/spring-scheduling-2">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-boot-scheduled-db-cron-expression">Getting a Cron Expression From Database for a Spring Boot Scheduled Job</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953867825/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953867825/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f11%2fSpring-Boot-Featured-Image-02-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953867825/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-boot-scheduled-db-cron-expression#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-boot-scheduled-db-cron-expression/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953867825/0/baeldung~Getting-a-Cron-Expression-From-Database-for-a-Spring-Boot-Scheduled-Job/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2024/11/Spring-Boot-Featured-Image-02-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/java-fast-gaussian-blur</feedburner:origLink>
		<title>Fast Gaussian Blur Implementation in Java</title>
		<link>https://feeds.feedblitz.com/~/953643002/0/baeldung~Fast-Gaussian-Blur-Implementation-in-Java</link>
					<comments>https://feeds.feedblitz.com/~/953643002/0/baeldung~Fast-Gaussian-Blur-Implementation-in-Java#respond</comments>
		
		<dc:creator><![CDATA[Nikhil Bhargav]]></dc:creator>
		<pubDate>Sat, 11 Apr 2026 05:45:20 +0000</pubDate>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Math]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203451</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Explore a faster, more computationally efficient solution for implementing Gaussian blur in Java.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953643002/0/baeldung~Fast-Gaussian-Blur-Implementation-in-Java">Fast Gaussian Blur Implementation in Java</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953643002/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f11%2fAlgorithms-Featured-Image-03-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-fast-gaussian-blur#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-fast-gaussian-blur/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-1024x536.jpg 1024w, https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-768x402.jpg 768w, https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-100x52.jpg 100w, https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-600x314.jpg 600w, https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03.jpg 1200w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 id="bd-introduction" data-id="introduction">1. Introduction</h2>
<div class="bd-anchor" id="introduction"></div>
<p>Gaussian blur is a widely used image processing technique for reducing image noise and detail. However, achieving accurate Gaussian blur can be computationally expensive, especially for high-resolution images with large blur radii.</p>
<p>In this tutorial, we&#8217;ll explore a faster, more computationally efficient solution for implementing Gaussian blur in Java.</p>
<h2 id="bd-problem-overview" data-id="problem-overview">2. Problem Overview</h2>
<div class="bd-anchor" id="problem-overview"></div>
<p data-path-to-node="7">We implement a <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/cv-blur-images#gaussian-blur">standard Gaussian blur</a> on a grayscale image by <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/convolution-matrix-multiplication">convolving</a> it with a 2D Gaussian kernel. Here, for each pixel in an image, the algorithm first examines a surrounding grid of pixels (the kernel). Then, it multiplies each pixel&#8217;s intensity by a specific weight. Finally, it sums them up.</p>
<p data-path-to-node="7">For an image with <em><span class="math-inline" data-math="n" data-index-in-node="16">n</span></em> pixels and a blur radius of <em><span class="math-inline" data-math="r" data-index-in-node="48">r</span></em>, our kernel size is <em><span class="math-inline" data-math="(2r + 1) \times (2r + 1)" data-index-in-node="70">(2r + 1)  x  (2r + 1)</span></em>. Thus, the standard 2D convolution algorithm has a <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-collections-complexity">time complexity</a> of <em>O(n.r<sup>2</sup>)</em>. <strong>As the blur radius <em>r</em> grows, the performance degrades quadratically. Thus, it is not optimal for real-time processing over large images.</strong></p>
<h2 id="bd-the-fast-approximation-algorithm" data-id="the-fast-approximation-algorithm">3. The Fast Approximation Algorithm</h2>
<div class="bd-anchor" id="the-fast-approximation-algorithm"></div>
<p>Our fast approximations make two key enhancements to the standard Gaussian 2D blur method.</p>
<h3 id="bd-1-separable-filters" data-id="1-separable-filters">3.1. Separable Filters</h3>
<div class="bd-anchor" id="1-separable-filters"></div>
<p data-path-to-node="12">A 2D Gaussian kernel can be seen and used as two 1D Gaussian vectors. In other words, we can separate them as horizontal and vertical vectors. So, instead of applying a 2D matrix to every pixel of the image, we can achieve the same result by applying a horizontal 1D blur across all rows, followed by a vertical 1D blur down all columns.</p>
<p data-path-to-node="13"><strong>This simple separation reduces our average-case time complexity from <em>O(n.r<sup>2</sup>) </em>to <em>O(n.r)</em>.</strong></p>
<h3 id="bd-2-repeated-box-blurs" data-id="2-repeated-box-blurs">3.2. Repeated Box Blurs</h3>
<div class="bd-anchor" id="2-repeated-box-blurs"></div>
<p data-path-to-node="15">We repeat a specific blur operation (box blur) to achieve the desired effect.</p>
<p data-path-to-node="15">We define box blur as the simplest form of blurring, assigning equal weight to every pixel within the blur radius. Then, we make use of the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/central-limit-theorem">Central Limit Theorem</a> to approximate a valid and matching <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/cs/gaussian-mixture-models">Gaussian distribution</a>. <strong>According to the Central Limit Theorem, applying a simple Box Blur multiple times closely approximates an accurate Gaussian distribution</strong>. We run five consecutive passes of a box blur to get a visually indistinguishable result from a strict Gaussian blur with a fraction of the computational overhead.</p>
<p data-path-to-node="16">Furthermore, we make all weights in a Box Blur equal, so we don&#8217;t need to re-sum the entire radius for every pixel. This gives us the freedom to use a sliding window or a moving average. <strong>As the window shifts to the right by one pixel, we subtract the leaving pixel and add the entering pixel. This drops our average time complexity to <em>O(n)</em>, making the performance entirely independent of the blur radius <em>r!</em></strong></p>
<h2 id="bd-solution" data-id="solution">4. Solution</h2>
<div class="bd-anchor" id="solution"></div>
<p>Let&#8217;s move to the solution.</p>
<h3 id="bd-1-the-sliding-window-box-blur" data-id="1-the-sliding-window-box-blur">4.1. The Sliding Window Box Blur</h3>
<div class="bd-anchor" id="1-the-sliding-window-box-blur"></div>
<p>First, we define a function, <em>horizontalBoxBlur()</em>, that performs a 1D horizontal blur using the sliding-window technique.</p>
<p>Here, we process the image row by row. <strong>We don&#8217;t recalculate the pixel sum at every position. Instead, we initialize <em>windowSum</em> for the very first pixel in a row. As it moves left to right, it subtracts the value of the pixel beyond the trailing edge of the radius and adds the value of the pixel at the leading edge.</strong></p>
<p>Lastly, we clamp edges to ensure that if the radius extends beyond the image boundaries, our logic duplicates the edge pixels rather than throwing an <em>ArrayIndexOutOfBoundsException</em>.</p>
<pre><code class="language-java">private static void horizontalBoxBlur(int[] source, int[] target, int width, int height, int radius) {
    double scale = 1.0 / (radius * 2 + 1);
    for (int y = 0; y &lt; height; y++) {
        int windowSum = 0;
        int offset = y * width;        
        for (int x = -radius; x &lt;= radius; x++) {
            int safeX = Math.min(Math.max(x, 0), width - 1);
            windowSum += source[offset + safeX];
        }        
        for (int x = 0; x &lt; width; x++) {
            target[offset + x] = (int) Math.round(windowSum * scale);
            int leftX = Math.max(x - radius, 0);
            int rightX = Math.min(x + radius + 1, width - 1);
            windowSum -= source[offset + leftX];
            windowSum += source[offset + rightX];
        }
    }
}</code></pre>
<p><span class="hljs-comment">The <em>verticalBoxBlur()</em> is identical in logic, but here we traverse columns rather than rows (top to bottom)</span>:</p>
<pre><code class="language-java">private static void verticalBoxBlur(int[] source, int[] target, int width, int height, int radius) {
    double scale = 1.0 / (radius * 2 + 1);
    for (int x = 0; x &lt; width; x++) {
        int windowSum = 0;
        for (int y = -radius; y &lt;= radius; y++) {
            int safeY = Math.min(Math.max(y, 0), height - 1);
            windowSum += source[safeY * width + x];
        }
        for (int y = 0; y &lt; height; y++) {
            target[y * width + x] = (int) Math.round(windowSum * scale);
            int topY = Math.max(y - radius, 0);
            int bottomY = Math.min(y + radius + 1, height - 1);
            windowSum -= source[topY * width + x];
            windowSum += source[bottomY * width + x];
        }
    }
}</code></pre>
<h3 id="bd-2-integration" data-id="2-integration">4.2.  Integration</h3>
<div class="bd-anchor" id="2-integration"></div>
<p>This is our orchestrator.</p>
<p>Leveraging the Central Limit Theorem, we apply a horizontal and vertical box blur three times (configurable). This smooths out peaky regions, thus creating a near-perfect approximation of a true Gaussian bell curve. It uses a temp array (<em>temp</em>) to safely ping-pong the data between passes without corrupting the source:</p>
<pre><code class="language-java">public static int[] applyFastGaussianBlur(int[] source, int numPasses, int width, int height, int radius) {
    int[] target = new int[source.length];
    int[] temp = new int[source.length];
    System.arraycopy(source, 0, target, 0, source.length);
    for (int i = 0; i &lt; numPasses; i++) {
        horizontalBoxBlur(target, temp, width, height, radius);
        verticalBoxBlur(temp, target, width, height, radius);
    }
    return target;
}</code></pre>
<h2 id="bd-test-1" data-id="test-1">5. Test</h2>
<div class="bd-anchor" id="test-1"></div>
<h3 id="bd-1-test-using-impulse-image" data-id="1-test-using-impulse-image">5.1. Test Using Impulse Image</h3>
<div class="bd-anchor" id="1-test-using-impulse-image"></div>
<p>First, let&#8217;s test this method using an impulse image (artificial images with a single black pixel). Our main objective is to verify if  our algorithm handles edges correctly and applies a smoothing effect:</p>
<pre><code class="language-java">void givenSharpImage_whenAppliedBlur_thenCenterIsSmoothed() {
    int width = 5;
    int height = 5;
    int numPasses = 5;
    int[] image = new int[width * height];
    image[12] = 255; 
    int[] blurredImage = FastGaussianBlur.applyFastGaussianBlur(image, numPasses, width, height, 1);
    assertTrue(blurredImage[12] &lt; 255);
    assertTrue(blurredImage[12] &gt; 0);
    assertTrue(blurredImage[11] &gt; 0); // Left neighbor
    assertTrue(blurredImage[13] &gt; 0); // Right neighbor
}</code></pre>
<p>We begin by creating a 5&#215;5 image (25 pixels) and set all pixels to 0, making them pure black. Then we set the exact center pixel (index 12) to 255, making it pure white. This sharp point is our impulse or peak. Then we apply the fast blur algorithm with a radius of 1.</p>
<p>Our main claim is that blur, when applied correctly, spreads the brightness of the central pixel outwards into the surrounding black pixels. Further, <em>assertTrue(blurredImage[12] &lt; 255)</em> confirms the center pixel has dimmed because it shared its brightness, and <em>assertTrue(blurredImage[11] &gt; 0)</em> and <em>assertTrue(blurredImage[13] &gt; 0)</em> confirm that the immediate left and right neighbors (both black) have absorbed that dispersed brightness.</p>
<h3 id="bd-2-test-using-real-image" data-id="2-test-using-real-image">5.2. Test Using Real Image</h3>
<div class="bd-anchor" id="2-test-using-real-image"></div>
<p>We take an open-source image and blur it using our algorithm. Here is the sample image:</p>
<img decoding="async" class="aligncenter size-full wp-image-242392" src="https://www.baeldung.com/wp-content/uploads/2026/04/sample.jpg" alt="Kodim17 Original Face" />
<p>Please check the blurred version:</p>
<img decoding="async" class="aligncenter size-full wp-image-242393" src="https://www.baeldung.com/wp-content/uploads/2026/04/sample_blurred.png" alt="Blurred Kodim17 Face" />
<p>We used a single channel of integer values for our impulse image (grayscale) test case. For this case, we use real images. Each real image is packed with 32-bit ARGB (Alpha, Red, Green, Blue) data. So, here we extract the ARGB channels, then blur each of the RGB channels independently, and finally pack them back together:</p>
<pre><code class="language-java">public static BufferedImage blurRealImage(@Nonnull BufferedImage image, int radius, int numPasses) {
    int width = image.getWidth();
    int height = image.getHeight();
    int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);
    int[] a = new int[pixels.length];
    int[] r = new int[pixels.length];
    int[] g = new int[pixels.length];
    int[] b = new int[pixels.length];
    for (int i = 0; i &lt; pixels.length; i++) {
        a[i] = (pixels[i] &gt;&gt; 24) &amp; 0xff;
        r[i] = (pixels[i] &gt;&gt; 16) &amp; 0xff;
        g[i] = (pixels[i] &gt;&gt; 8) &amp; 0xff;
        b[i] = pixels[i] &amp; 0xff;
    }
    r = FastGaussianBlur.applyFastGaussianBlur(r, width, height, radius, numPasses);
    g = FastGaussianBlur.applyFastGaussianBlur(g, width, height, radius, numPasses);
    b = FastGaussianBlur.applyFastGaussianBlur(b, width, height, radius, numPasses);
    int[] resultPixels = new int[pixels.length];
    for (int i = 0; i &lt; pixels.length; i++) {
        resultPixels[i] = (a[i] &lt;&lt; 24) | (r[i] &lt;&lt; 16) | (g[i] &lt;&lt; 8) | b[i];
    }
    BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    result.setRGB(0, 0, width, height, resultPixels, 0, width);
    return result;
}</code></pre>
<h2 id="bd-conclusion" data-id="conclusion">6. Conclusion</h2>
<div class="bd-anchor" id="conclusion"></div>
<p>In this article, we learned a faster Gaussian blur method in Java. We made two key enhancements to the standard Gaussian blur implementation to achieve linear time complexity. First, we decomposed a 2D convolution matrix into separable 1D arrays, and second, we used a moving-average sliding window across three box-blur passes. Thus, our solution works in a constant processing time that is independent of the blur radius.</p>
<p>As always, the complete code examples are available <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eugenp/tutorials/tree/master/algorithms-modules/algorithms-numeric">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-fast-gaussian-blur">Fast Gaussian Blur Implementation in Java</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953643002/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953643002/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f11%2fAlgorithms-Featured-Image-03-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953643002/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-fast-gaussian-blur#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-fast-gaussian-blur/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953643002/0/baeldung~Fast-Gaussian-Blur-Implementation-in-Java/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2024/11/Algorithms-Featured-Image-03-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/java-weekly-641</feedburner:origLink>
		<title>Java Weekly, Issue 641</title>
		<link>https://feeds.feedblitz.com/~/953606012/0/baeldung~Java-Weekly-Issue</link>
					<comments>https://feeds.feedblitz.com/~/953606012/0/baeldung~Java-Weekly-Issue#respond</comments>
		
		<dc:creator><![CDATA[baeldung]]></dc:creator>
		<pubDate>Fri, 10 Apr 2026 09:51:00 +0000</pubDate>
				<category><![CDATA[Weekly Review]]></category>
		<category><![CDATA[no-ads]]></category>
		<category><![CDATA[no-after-post]]></category>
		<category><![CDATA[no-before-post]]></category>
		<category><![CDATA[no-optins]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203436</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Doing things that don't scale has real value. Oh and S3 is now a filesystem :)</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953606012/0/baeldung~Java-Weekly-Issue">Java Weekly, Issue 641</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953606012/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Weekly-Reviews-4.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-weekly-641#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-weekly-641/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4.jpg 952w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-768x402.jpg 768w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 style="text-align: left;" id="bd-spring-and-java" data-id="spring-and-java">1.<strong> Spring and Java</strong></h2>
<div class="bd-anchor" id="spring-and-java"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.infoq.com/articles/beyond-rag-context-aware/">&gt;&gt; Beyond RAG: Architecting Context-Aware AI Systems with Spring Boot</a></strong> [<span style="color: #993300;">infoq.com</span>]</p>
<p>A solid look at Context-Augmented Generation (CAG) — an architectural layer on top of RAG that adds user identity, session state, and business constraints before the retrieval step. With Boot of course.</p>
<h4><strong>Also worth reading:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/java-native-memory-access-modes/" target="_blank" rel="noopener"><strong>Thread-Safe Native Memory in Java: VarHandle Access Modes Explained</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/from-zero-to-full-observability-with-dash0/" target="_blank" rel="noopener"><strong>From Zero to Full Observability with Dash0</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://foojay.io/today/does-java-really-use-too-much-memory-lets-look-at-the-facts-jeps/" target="_blank" rel="noopener"><strong>Does Java Really Use Too Much Memory? Let&#8217;s Look at the Facts (JEPs)</strong></a> [<span style="color: #800000;">foojay.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/07/spring-ai-agentic-patterns-6-memory-tools" target="_blank" rel="noopener"><strong>Spring AI Agentic Patterns (Part 6): AutoMemoryTools — Persistent Agent Memory Across Sessions</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://developers.googleblog.com/announcing-adk-for-java-100-building-the-future-of-ai-agents-in-java/" target="_blank" rel="noopener"><strong>Announcing ADK for Java 1.0.0: Building the Future of AI Agents in Java</strong></a> [<span style="color: #800000;">googleblog.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.pollack.ai/p/8a0a3a73-144a-4615-a992-560da556f13c/" target="_blank" rel="noopener"><strong>ACP Java SDK: Building IDE Agents in Java</strong></a> [<span style="color: #800000;">blog.pollack.ai</span>]</li>
</ul>
<h4><strong>Webinars and presentations:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/02/a-bootiful-podcast-ana-maria-mihalceanu" target="_blank" rel="noopener"><strong>A Bootiful Podcast: Java developer advocate Ana-Maria Mihalceanu</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/08/javaone-post-quantum-cryptography/" target="_blank" rel="noopener"><strong>Java and Post-Quantum Cryptography</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://inside.java/2026/04/04/podcast-053/" target="_blank" rel="noopener"><strong>Episode 53 “Analyzing Crashed JVMs”</strong></a> [<span style="color: #800000;">inside.java</span>]</li>
</ul>
<h4><strong>Time to upgrade:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2026/04/02/spring-cloud-2025-0-2-aka-northfields-has-been-released" target="_blank" rel="noopener"><strong>Spring Cloud 2025.0.2 (aka Northfields) Has Been Released</strong></a> [<span style="color: #800000;">spring.io</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://in.relation.to/2026/04/07/orm-73/" target="_blank" rel="noopener"><strong>Hibernate 7.3.0.Final</strong></a> [<span style="color: #800000;">in.relation.to</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.infoq.com/news/2026/04/helidon-4-4-released/" target="_blank" rel="noopener"><strong>Helidon 4.4.0 Introduces Alignment with OpenJDK Cadence and Support via Java Verified Portfolio</strong></a> [<span style="color: #800000;">infoq.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/quarkusio/quarkus/releases/tag/3.34.3" target="_blank" rel="noopener"><strong>Quarkus 3.34.3</strong></a> [<span style="color: #800000;">github.com/quarkusio</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/elastic/elasticsearch/releases/tag/v9.3.3" target="_blank" rel="noopener"><strong>Elasticsearch 9.3.3</strong></a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/elastic/elasticsearch/releases/tag/v9.2.8" target="_blank" rel="noopener"><strong>9.2.8</strong></a>, and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/elastic/elasticsearch/releases/tag/v8.19.14" target="_blank" rel="noopener"><strong>8.19.14</strong></a> [<span style="color: #800000;">github.com/elastic</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/beehive-lab/TornadoVM/releases/tag/v4.0.0-jdk25" target="_blank" rel="noopener"><strong>TornadoVM 4.0.0</strong></a> [<span style="color: #800000;">github.com/beehive-lab</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/Netflix/zuul/releases/tag/v3.5.8" target="_blank" rel="noopener"><strong>Netflix Zuul 3.5.8</strong></a> [<span style="color: #800000;">github.com/Netflix</span>]</li>
</ul>
<h2 style="text-align: left;" id="bd-technical-amp-musings" data-id="technical-amp-musings">2.<strong> Technical &amp; Musings</strong></h2>
<div class="bd-anchor" id="technical-amp-musings"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.allthingsdistributed.com/2026/04/s3-files-and-the-changing-face-of-s3.html">&gt;&gt; S3 Files and the changing face of S3</a></strong> [<span style="color: #993300;">allthingsdistributed.com</span>]</p>
<p>AWS&#8217;s new S3 Files feature mounts S3 buckets as network filesystems via EFS, letting you use standard file operations on object storage without copying data around. Bout time <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<h4><strong>Also worth reading:</strong></h4>
<ul>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://martinfowler.com/articles/reduce-friction-ai/feedback-flywheel.html" target="_blank" rel="noopener"><strong>Feedback Flywheel</strong></a> [<span style="color: #800000;">martinfowler.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://martinfowler.com/articles/harness-engineering.html" target="_blank" rel="noopener"><strong>Harness engineering for coding agent users</strong></a> [<span style="color: #800000;">martinfowler.com</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://blog.frankel.ch/experimenting-ai-subagents/" target="_blank" rel="noopener"><strong>Experimenting with AI subagents</strong></a> [<span style="color: #800000;">frankel.ch</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://lucumr.pocoo.org/2026/4/4/absurd-in-production/" target="_blank" rel="noopener"><strong>Absurd In Production</strong></a> [<span style="color: #800000;">lucumr.pocoo.org</span>]</li>
<li><strong>&gt;&gt;</strong> <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://netflixtechblog.com/powering-multimodal-intelligence-for-video-search-3e0020cf1202" target="_blank" rel="noopener"><strong>Synchronizing the Senses: Powering Multimodal Intelligence for Video Search</strong></a> [<span style="color: #800000;">netflixtechblog.com</span>]</li>
</ul>
<h2 style="text-align: left;" id="bd-pick-of-the-week" data-id="pick-of-the-week">3.<strong> Pick of the Week</strong></h2>
<div class="bd-anchor" id="pick-of-the-week"></div>
<p><strong><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.paulgraham.com/ds.html">&gt;&gt; Do Things that Don&#8217;t Scale</a></strong> [<span style="color: #993300;">paulgraham.com</span>]</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-weekly-641">Java Weekly, Issue 641</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953606012/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953606012/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2016%2f10%2fsocial-Weekly-Reviews-4.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953606012/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-weekly-641#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-weekly-641/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953606012/0/baeldung~Java-Weekly-Issue/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2016/10/social-Weekly-Reviews-4-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/spring-resttemplate-no-suitable-httpmessageconverter</feedburner:origLink>
		<title>Handle &#8220;No Suitable HttpMessageConverter&#8221; in Spring RestTemplate</title>
		<link>https://feeds.feedblitz.com/~/953488283/0/baeldung~Handle-No-Suitable-HttpMessageConverter-in-Spring-RestTemplate</link>
					<comments>https://feeds.feedblitz.com/~/953488283/0/baeldung~Handle-No-Suitable-HttpMessageConverter-in-Spring-RestTemplate#respond</comments>
		
		<dc:creator><![CDATA[Sudarshan Hiray]]></dc:creator>
		<pubDate>Tue, 07 Apr 2026 23:02:40 +0000</pubDate>
				<category><![CDATA[Spring Web]]></category>
		<category><![CDATA[RestTemplate]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203399</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Learn how to prevent one of the most common RestClientExceptions when using RestTeamplate.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953488283/0/baeldung~Handle-No-Suitable-HttpMessageConverter-in-Spring-RestTemplate">Handle “No Suitable HttpMessageConverter” in Spring RestTemplate</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953488283/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f07%2fJava-Featured-11-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-resttemplate-no-suitable-httpmessageconverter#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-resttemplate-no-suitable-httpmessageconverter/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11-1024x536.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11-1024x536.jpg 1024w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11-768x402.jpg 768w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11-100x52.jpg 100w, https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11.jpg 1200w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 data-path-to-node="1" id="bd-introduction" data-id="introduction"><b data-path-to-node="1" data-index-in-node="0">1. Introduction</b></h2>
<div class="bd-anchor" id="introduction"></div>
<p data-path-to-node="2">When consuming RESTful services in Spring, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/rest-template"><i data-path-to-node="2" data-index-in-node="43">RestTemplate</i></a> is a reliable workhorse for synchronous <em>HTTP</em> communication. However, one of the most common and frustrating hurdles developers face is the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-boot-restclient#:~:text=By%20default%2C%20when%20RestClient%20encounters%20a%204xx%20or%205xx%20status%20code%20in%20the%20HTTP%20response%2C%20it%20raises%20an%20exception%20that%E2%80%99s%20a%20subclass%20of%20RestClientException."><em>RestClientException</em></a>. Specifically, the following error message:</p>
<pre><code class="language-java">Could not extract response: no suitable HttpMessageConverter found for response type and content type...</code></pre>
<p data-path-to-node="3"><strong>This error typically occurs when the client receives a response that it doesn&#8217;t know how to deserialize into the desired Java object.</strong> In this article, we’ll explore why this happens and how to configure our application to handle non-standard API responses effectively without encountering any such errors.</p>
<h2 data-path-to-node="5" id="bd-project-setup" data-id="project-setup"><b data-path-to-node="5" data-index-in-node="0">2. Project Setup</b></h2>
<div class="bd-anchor" id="project-setup"></div>
<p data-path-to-node="6">To get started, we&#8217;ll need the standard <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web">Spring Boot Starter Web</a> dependency:</p>
<div class="code-block ng-tns-c2827611141-91 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwiIvrb72dOTAxUAAAAAHQAAAAAQaw">
<div class="formatted-code-block-internal-container ng-tns-c2827611141-91">
<div class="animated-opacity ng-tns-c2827611141-91">
<pre><code class="language-java">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
    &lt;version&gt;4.0.5&lt;/version&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
</div>
<p data-path-to-node="8">For <em>JSON</em> processing, Spring Boot includes <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/jackson"><em>Jackson</em></a> by default. To better understand it, we&#8217;ll ensure <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind">jackson-databind</a> is on our classpath, as it provides the underlying logic for the <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.html"><em>MappingJackson2HttpMessageConverter</em></a>.</p>
<h2 data-path-to-node="10" id="bd-understanding-and-identifying-the-root-cause" data-id="understanding-and-identifying-the-root-cause"><b data-path-to-node="10" data-index-in-node="0">3. Understanding and Identifying the Root Cause</b></h2>
<div class="bd-anchor" id="understanding-and-identifying-the-root-cause"></div>
<p data-path-to-node="4">To fix this error, we’ll first understand how Spring maps the raw HTTP response to Java objects. The issue is rarely with the data itself, but rather a mismatch in the expected communication protocol. We&#8217;ll now examine the internal conversion mechanism, identify common misleading media types, and learn how to inspect the actual response headers.</p>
<h3 data-path-to-node="11" id="bd-1-how-resttemplate-converts-responses" data-id="1-how-resttemplate-converts-responses"><b data-path-to-node="11" data-index-in-node="0">3.1. How RestTemplate Converts Responses</b></h3>
<div class="bd-anchor" id="1-how-resttemplate-converts-responses"></div>
<p data-path-to-node="12"><i data-path-to-node="12" data-index-in-node="0">RestTemplate</i> relies on a list of <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-httpmessageconverter-rest"><em>HttpMessageConverter</em> beans</a> to transform HTTP request and response bodies. <strong>When a response arrives, Spring looks at the <em>Content-Type</em> header sent by the server. It then iterates through its registered converters to find one that supports both that <em>MediaType</em> and the target Java class.</strong></p>
<h3 data-path-to-node="13" id="bd-2-common-mismatched-media-types" data-id="2-common-mismatched-media-types"><b data-path-to-node="13" data-index-in-node="0">3.2. Common Mismatched Media Types</b></h3>
<div class="bd-anchor" id="2-common-mismatched-media-types"></div>
<p data-path-to-node="14">The issue usually isn&#8217;t that the data is invalid, but that the metadata is misleading. Many legacy or third-party APIs return valid JSON, but set the <span style="margin: 0px;padding: 0px"><em>Content-Type </em>header</span> to something other than <em>application/json</em>. Common mismatched types include <em>text/plain</em>, <em>text/javascript,</em> and <em>application/octet-stream.</em></p>
<p data-path-to-node="16"><strong>The default <span style="margin: 0px;padding: 0px"><em>MappingJackson2HttpMessageConverter </em>only</span> claims to support <em>application/</em><span style="margin: 0px;padding: 0px"><em>json </em>and</span> <em>application/*+json.</em></strong> It ignores any other type of responses, leading to the &#8220;Could not extract response: no suitable HttpMessageConverter found for response type and content type&#8221; error.</p>
<h3 data-path-to-node="17" id="bd-3-checking-api-response-headers" data-id="3-checking-api-response-headers"><b data-path-to-node="17" data-index-in-node="0">3.3. Checking API Response Headers</b></h3>
<div class="bd-anchor" id="3-checking-api-response-headers"></div>
<p data-path-to-node="18">To diagnose this, we must inspect the headers. <strong>If we can&#8217;t access external logs, we can enable debug logging for Spring Web in our <em>application.properties</em></strong>:</p>
<div class="code-block ng-tns-c2827611141-92 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwiIvrb72dOTAxUAAAAAHQAAAAAQbA">
<div class="formatted-code-block-internal-container ng-tns-c2827611141-92">
<div class="animated-opacity ng-tns-c2827611141-92">
<pre><code class="language-java">logging.level.org.springframework.web.client.RestTemplate=DEBUG</code></pre>
</div>
</div>
</div>
<p data-path-to-node="20">This will reveal the exact <span style="margin: 0px;padding: 0px"><em>Content-Type</em></span> the server is providing, allowing us to target the specific mismatch.</p>
<h2 data-path-to-node="22" id="bd-solving-the-error-configuration-strategies" data-id="solving-the-error-configuration-strategies"><b data-path-to-node="22" data-index-in-node="0">4. Solving the Error: Configuration Strategies</b></h2>
<div class="bd-anchor" id="solving-the-error-configuration-strategies"></div>
<p>In this section, we&#8217;ll create a config class named <em>RestTemplateConverterConfig </em>to inject the <em>RestTemplate </em>bean, which will help us resolve this error. The following section mentions the details on it:</p>
<h3 data-path-to-node="23" id="bd-1-adding-support-for-custom-media-types" data-id="1-adding-support-for-custom-media-types"><b data-path-to-node="23" data-index-in-node="0">4.1. Adding Support for Custom Media Types</b></h3>
<div class="bd-anchor" id="1-adding-support-for-custom-media-types"></div>
<p data-path-to-node="24"><strong>The most surgical fix is to tell the Jackson converter to treat these uncommon media types as JSON</strong>. We can create an instance of <span style="margin: 0px;padding: 0px"><em>MappingJackson2HttpMessageConverter </em></span>and update its supported media types:</p>
<div class="code-block ng-tns-c2827611141-93 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwiIvrb72dOTAxUAAAAAHQAAAAAQbQ">
<div class="formatted-code-block-internal-container ng-tns-c2827611141-93">
<div class="animated-opacity ng-tns-c2827611141-93">
<pre><code class="language-java">@Configuration
public class RestTemplateConverterConfig {
    @Bean("specificMediaTypesRestTemplate")
    public RestTemplate specificMediaTypesRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        List&lt;HttpMessageConverter&lt;?&gt;&gt; converters = restTemplate.getMessageConverters();
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.setSupportedMediaTypes(Arrays.asList(
          MediaType.APPLICATION_JSON,
          MediaType.TEXT_PLAIN,
          MediaType.valueOf("text/javascript")
        ));
        converters.add(jsonConverter);
        restTemplate.setMessageConverters(converters);
        return restTemplate;
    }
}</code></pre>
</div>
</div>
</div>
<p>Here we explicitly list only the media types we expect to encounter. This keeps the converter&#8217;s scope narrow and intentional. Other unexpected content types, such as <em>application/octet-stream, </em>would still fail, which is often the desired behavior in a controlled environment.</p>
<h3 data-path-to-node="26" id="bd-2-manually-registering-converters-in-resttemplate" data-id="2-manually-registering-converters-in-resttemplate"><b data-path-to-node="26" data-index-in-node="0">4.2. Manually Registering Converters in <em>RestTemplate</em></b></h3>
<div class="bd-anchor" id="2-manually-registering-converters-in-resttemplate"></div>
<p data-path-to-node="27">If we want a more permissive setup, within the same <em>RestTemplateConverterConfig</em> class, we&#8217;ll register another Jackson converter with <em>MediaType.ALL. </em>This instructs the <em>RestTemplate</em> to handle any content type the server returns:</p>
<div class="code-block ng-tns-c2827611141-94 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwiIvrb72dOTAxUAAAAAHQAAAAAQbg">
<div class="formatted-code-block-internal-container ng-tns-c2827611141-94">
<div class="animated-opacity ng-tns-c2827611141-94">
<pre><code class="language-java">@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    List&lt;HttpMessageConverter&lt;?&gt;&gt; converters = restTemplate.getMessageConverters();
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
    jsonConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
    converters.add(jsonConverter);
    restTemplate.setMessageConverters(converters);
    return restTemplate;
}</code></pre>
</div>
</div>
</div>
<p data-path-to-node="29">Here, we call the <em>getMessageConverters() </em>method and append to the existing list rather than replacing it. This preserves all the default converters Spring registers, such as those for <em>String </em>and <em>byte[]</em>, and simply adds our custom Jackson converter at the end.</p>
<h3 data-path-to-node="29" id="bd-3-using-resttemplateexchange-with-parameterizedtypereference" data-id="3-using-resttemplateexchange-with-parameterizedtypereference"><b data-path-to-node="29" data-index-in-node="0">4.3. Using <em>RestTemplate.exchange()</em> With <em>ParameterizedTypeReference</em></b></h3>
<div class="bd-anchor" id="3-using-resttemplateexchange-with-parameterizedtypereference"></div>
<p data-path-to-node="30">Sometimes the error arises because we are trying to deserialize into a generic collection, like <em>List&lt;User&gt;</em>. <strong>In this example, the <em>User</em> class is a simple POJO with <em>id</em> and <em>name</em> fields that <em>Jackson</em> maps from the <em>JSON</em> response.</strong></p>
<p data-path-to-node="30">Using <em>getForObject() </em>with <em>List.class </em>loses generic type information at runtime due to type erasure. Instead, we should use the <em>restTemplate.exchange() </em>method with a <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-parameterized-type-reference"><em>ParameterizedTypeReference</em></a>:</p>
<pre><code class="language-java">ResponseEntity&lt;List&lt;User&gt;&gt; response = restTemplate.exchange(
  "/users",
  HttpMethod.GET,
  null,
  new ParameterizedTypeReference&lt;List&lt;User&gt;&gt;() {}
);</code></pre>
<p data-path-to-node="33">The anonymous subclass of <em>ParameterizedTypeReference</em> captures the full generic type <em>List&lt;User&gt;</em> at compile time, giving Jackson enough information to correctly deserialize each element in the array into a <em>User</em> object.</p>
<h2 data-path-to-node="0" id="bd-testing-and-verification" data-id="testing-and-verification"><b data-path-to-node="0" data-index-in-node="0">5. Testing and Verification</b></h2>
<div class="bd-anchor" id="testing-and-verification"></div>
<p data-path-to-node="1">To verify our configurations, we’ll use <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-mock-rest-template#:~:text=MockRestServiceServer%20actually%20works%20by%20intercepting%20the%20HTTP%20API%20calls%20using%20a%20MockClientHttpRequestFactory.%20Based%20on%20our%20configuration%2C%20it%20creates%20a%20list%20of%20expected%20requests%20and%20corresponding%20responses."><em>MockRestServiceServer</em></a>. This allows us to simulate the exact mismatched header scenarios that typically trigger the <em>RestClientException </em>without needing a live external API.</p>
<h3 data-path-to-node="2" id="bd-1-testing-the-surgical-fix" data-id="1-testing-the-surgical-fix"><b data-path-to-node="2" data-index-in-node="0">5.1. Testing the Surgical Fix</b></h3>
<div class="bd-anchor" id="1-testing-the-surgical-fix"></div>
<p data-path-to-node="3">In this first scenario, we use the <em>@Qualifier</em> to inject our <em>specificMediaTypesRestTemplate</em>. We&#8217;ll simulate a response that is explicitly labeled as <em>text/plain</em>. <strong>This proves that our surgical inclusion of that specific media type works as intended</strong>:</p>
<div class="code-block ng-tns-c2827611141-138 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwiIvrb72dOTAxUAAAAAHQAAAAAQzAE">
<div class="formatted-code-block-internal-container ng-tns-c2827611141-138">
<div class="animated-opacity ng-tns-c2827611141-138">
<pre><code class="language-java">@Autowired
@Qualifier("specificMediaTypesRestTemplate")
private RestTemplate specificMediaTypesRestTemplate;
@Test
void givenSpecificMediaTypesRestTemplate_whenTextPlainResponse_thenDeserializeCorrectly() {
    MockRestServiceServer mockServer = MockRestServiceServer.createServer(specificMediaTypesRestTemplate);
    mockServer.expect(requestTo("/user"))
      .andRespond(withSuccess("{\"id\":1,\"name\":\"Sudarshan\"}", MediaType.TEXT_PLAIN));
    User user = specificMediaTypesRestTemplate.getForObject("/user", User.class);
    assertNotNull(user);
    assertEquals("Sudarshan", user.getName());
}</code></pre>
</div>
</div>
</div>
<h3 data-path-to-node="5" id="bd-2-testing-the-permissive-fix" data-id="2-testing-the-permissive-fix"><b data-path-to-node="5" data-index-in-node="0">5.2. Testing the Permissive Fix</b></h3>
<div class="bd-anchor" id="2-testing-the-permissive-fix"></div>
<p data-path-to-node="6">Next, <strong>we test the primary <em>RestTemplate</em> bean configured with <em>MediaType.ALL</em></strong>. This test confirms that<span style="margin: 0px;padding: 0px">, by making the converter permissive, it ignores the misleading <em>text/plain</em> header and defaults to <em>Jackson</em> for </span>deserialization.</p>
<div class="code-block ng-tns-c2827611141-139 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwiIvrb72dOTAxUAAAAAHQAAAAAQzQE">
<div class="formatted-code-block-internal-container ng-tns-c2827611141-139">
<div class="animated-opacity ng-tns-c2827611141-139">
<pre><code class="language-java">@Test
void givenMockServer_whenTextPlainResponse_thenDeserializeCorrectly() {
    MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
    mockServer.expect(requestTo("/user"))
      .andRespond(withSuccess("{\"id\":1,\"name\":\"Sudarshan\"}", MediaType.TEXT_PLAIN));
    User user = restTemplate.getForObject("/user", User.class);
    assertNotNull(user);
    assertEquals("Sudarshan", user.getName());
}</code></pre>
</div>
</div>
</div>
<h3 data-path-to-node="8" id="bd-3-verifying-generic-type-resolution" data-id="3-verifying-generic-type-resolution"><b data-path-to-node="8" data-index-in-node="0">5.3. Verifying Generic Type Resolution</b></h3>
<div class="bd-anchor" id="3-verifying-generic-type-resolution"></div>
<p data-path-to-node="9">Finally, <strong>we verify that our <em>restTemplate.exchange()</em> strategy correctly handles collections</strong>. Even with a mismatched <em>text/plain</em> header, the <em>ParameterizedTypeReference </em>ensures that the generic information <em>List&lt;User&gt;</em> is preserved during the conversion process:</p>
<div class="code-block ng-tns-c2827611141-140 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahgKEwiIvrb72dOTAxUAAAAAHQAAAAAQzgE">
<div class="formatted-code-block-internal-container ng-tns-c2827611141-140">
<div class="animated-opacity ng-tns-c2827611141-140">
<pre><code class="language-java">@Test
void givenMockServer_whenTextPlainResponseForList_thenDeserializeWithParameterizedTypeReference() {
    MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
    mockServer.expect(requestTo("/users"))
      .andRespond(
        withSuccess(
          "[{\"id\":1,\"name\":\"Sudarshan\"},{\"id\":2,\"name\":\"Baeldung\"}]",
          MediaType.TEXT_PLAIN));
    ResponseEntity&lt;List&lt;User&gt;&gt; response = restTemplate.exchange(
      "/users",
      HttpMethod.GET,
      null,
      new ParameterizedTypeReference&lt;List&lt;User&gt;&gt;() {}
    );
    assertNotNull(response.getBody());
    assertEquals(2, response.getBody().size());
    assertEquals("Sudarshan", response.getBody().get(0).getName());
}</code></pre>
</div>
</div>
</div>
<h2 data-path-to-node="41" id="bd-conclusion" data-id="conclusion"><b data-path-to-node="41" data-index-in-node="0">6. Conclusion</b></h2>
<div class="bd-anchor" id="conclusion"></div>
<p data-path-to-node="42">In this tutorial, we understood that the &#8220;<em>No Suitable HttpMessageConverter</em>&#8221; error is rarely a sign of broken data; it’s a communication breakdown between the server&#8217;s headers and the client&#8217;s expectations. <strong>By identifying the returned <span style="margin: 0px;padding: 0px"><em>Content-Type</em></span> and explicitly configuring our <span style="margin: 0px;padding: 0px"><em>MappingJackson2HttpMessageConverter </em></span>to support it, we can bridge this gap.</strong></p>
<p data-path-to-node="43">Whether you choose to support all media types via <em>MediaType.ALL</em> or strictly list the exceptions, like <em>text/plain</em>, understanding the converter registration process is key to building resilient Spring clients.</p>
<p data-path-to-node="43">As always, the complete code samples used in this article are available <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eugenp/tutorials/tree/master/spring-web-modules/spring-resttemplate-3">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-resttemplate-no-suitable-httpmessageconverter">Handle “No Suitable HttpMessageConverter” in Spring RestTemplate</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953488283/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953488283/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2024%2f07%2fJava-Featured-11-1024x536.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953488283/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-resttemplate-no-suitable-httpmessageconverter#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-resttemplate-no-suitable-httpmessageconverter/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953488283/0/baeldung~Handle-No-Suitable-HttpMessageConverter-in-Spring-RestTemplate/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2024/07/Java-Featured-11-150x150.jpg</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/java-flip-bits-number</feedburner:origLink>
		<title>Flip the Bits of a Number in Java</title>
		<link>https://feeds.feedblitz.com/~/953487332/0/baeldung~Flip-the-Bits-of-a-Number-in-Java</link>
					<comments>https://feeds.feedblitz.com/~/953487332/0/baeldung~Flip-the-Bits-of-a-Number-in-Java#respond</comments>
		
		<dc:creator><![CDATA[Zachary Bouhannana]]></dc:creator>
		<pubDate>Tue, 07 Apr 2026 22:58:58 +0000</pubDate>
				<category><![CDATA[Java Numbers]]></category>
		<category><![CDATA[Java Integer]]></category>
		<category><![CDATA[Java Operators]]></category>
		<category><![CDATA[Math]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/java-flip-bits-number</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured-1024x536.png" class="webfeedsFeaturedVisual wp-post-image" alt="Contact Us Featured" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Learn standard and alternative ways to invert the value of all bits or only the significant bits of a number in Java.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953487332/0/baeldung~Flip-the-Bits-of-a-Number-in-Java">Flip the Bits of a Number in Java</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953487332/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2021%2f09%2fJava-8-Featured-1024x536.png"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-flip-bits-number#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-flip-bits-number/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured-1024x536.png" class="webfeedsFeaturedVisual wp-post-image" alt="Contact Us Featured" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured-1024x536.png 1024w, https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured-300x157.png 300w, https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured-768x402.png 768w, https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured-100x52.png 100w, https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured.png 1200w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 id="bd-overview" data-id="overview">1. Overview</h2>
<div class="bd-anchor" id="overview"></div>
<p>Bit manipulation is a fundamental concept in programming that involves working with individual bits of binary data. One common operation is flipping all bits in an integer, converting every <em>0</em> to <em>1</em> and every <em>1</em> to <em>0</em>.</p>
<p>In this tutorial, we&#8217;ll explain what bit flipping means and explore several Java methods to flip the bits of an integer. For completeness, we&#8217;ll cover both full 32-bit flipping and flipping only the significant bits.</p>
<h2 id="bd-understanding-bit-flipping" data-id="understanding-bit-flipping">2. Understanding Bit Flipping</h2>
<div class="bd-anchor" id="understanding-bit-flipping"></div>
<p>Before we learn how to flip bits in an integer, it&#8217;s best to look at a visual example.</p>
<p>To begin with, let&#8217;s consider the decimal number <em>21</em> and, more specifically, its binary representation:</p>
<pre><code class="language-java">10101</code></pre>
<p>The goal is to invert each bit so that every <em>0</em> becomes a <em>1</em> and every <em>1</em> becomes a <em>0</em>:</p>
<pre><code class="language-java">01010</code></pre>
<p>This corresponds to the decimal value <em>10</em> (<em>8+2</em>).</p>
<p>During this transformation, each bit at position <em>i</em> in the original number gets inverted in the result. However, there&#8217;s an important distinction to make. <strong>When we flip all 32 bits of an integer, i.e., its full size, the result differs from flipping only the significant bits</strong>. For instance, flipping all 32 bits of the integer <em>21</em> produces <em>-22</em> due to <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-compute-twos-complement">two&#8217;s complement</a> representation, whereas flipping only the significant bits (<em>10101</em> -&gt; <em>01010</em>) yields <em>10</em>.</p>
<p>In the following sections, let&#8217;s explore both scenarios in detail.</p>
<h2 id="bd-using-the-bitwise-not-operator" data-id="using-the-bitwise-not-operator">3. Using the Bitwise NOT Operator</h2>
<div class="bd-anchor" id="using-the-bitwise-not-operator"></div>
<p>The most direct approach to flip bits is the bitwise NOT operator <em>~</em>. This <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-operators#unary-operators">unary operator</a> inverts every bit in the integer&#8217;s binary representation:</p>
<pre><code class="language-java">public static int flipAllBits(int n) {
    return ~n;
}</code></pre>
<p>The operator flips all 32 bits of the integer. <strong>This means that <em>~</em> inverts every bit, including leading zeros, turning a positive number into a negative one due to the two&#8217;s complement representation in Java</strong>.</p>
<p>Let&#8217;s verify the results using a <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/junit-5">JUnit 5</a> test and <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/introduction-to-assertj">AssertJ</a> matchers:</p>
<pre><code class="language-java">@Test
void givenPositiveInteger_whenFlipAllBits_thenReturnsNegativeComplement() {
    assertThat(flipAllBits(21)).isEqualTo(-22);
    assertThat(flipAllBits(0)).isEqualTo(-1);
    assertThat(flipAllBits(-1)).isEqualTo(0);
}</code></pre>
<p>As we can see, flipping all 32 bits of <em>21</em> gives us <em>-22</em>, not <em>10</em>. This is because Java&#8217;s <em>int</em> type is a signed 32-bit integer.</p>
<p>To get a result like <em>10</em> from <em>21</em>, we need to flip only the significant bits. Let&#8217;s cover this case next.</p>
<h2 id="bd-flipping-only-the-significant-bits" data-id="flipping-only-the-significant-bits">4. Flipping Only the Significant Bits</h2>
<div class="bd-anchor" id="flipping-only-the-significant-bits"></div>
<p>In many practical scenarios, we want to flip only the bits that are actually used in the binary representation of the number, excluding leading zeros. For instance, flipping the significant bits of <em>21</em> (<em>10101</em>) should give us <em>10</em> (<em>01010</em>).</p>
<h3 id="bd-1-using-a-mask-with-bit-length-calculation" data-id="1-using-a-mask-with-bit-length-calculation">4.1. Using a Mask With Bit Length Calculation</h3>
<div class="bd-anchor" id="1-using-a-mask-with-bit-length-calculation"></div>
<p>The idea is straightforward: we create a mask with a <em>1</em> at each significant bit position, then <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-xor-operator">XOR</a> the number with this mask. The XOR operation flips only the bits where the mask has a <em>1</em>:</p>
<pre><code class="language-java">public static int flipSignificantBits(int n) {
    if (n == 0) {
        return 0;
    }
    int bitLength = Integer.SIZE - Integer.numberOfLeadingZeros(n);
    int mask = (1 &lt;&lt; bitLength) - 1;
    return n ^ mask;
}</code></pre>
<p>First, we handle the edge case where <em>n</em> is <em>0</em>. Then, we calculate the number of significant bits using <em>Integer.numberOfLeadingZeros()</em>. With this value, we create a <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-bitmasking">mask</a> by shifting <em>1</em> left by <em>bitLength</em> positions and subtracting <em>1</em>, which gives us a sequence of 1s matching the significant bit length.</p>
<p><strong>Finally, the XOR operation (<em>^</em>) flips only the significant bits, since XOR with <em>1</em> inverts a bit while XOR with <em>0</em> leaves it unchanged</strong>.</p>
<p>Let&#8217;s verify this with a test:</p>
<pre><code class="language-java">@Test
void givenPositiveInteger_whenFlipSignificantBits_thenReturnsFlippedValue() {
    assertThat(flipSignificantBits(21)).isEqualTo(10);
    assertThat(flipSignificantBits(26)).isEqualTo(5);
    assertThat(flipSignificantBits(0)).isEqualTo(0);
    assertThat(flipSignificantBits(1)).isEqualTo(0);
    assertThat(flipSignificantBits(7)).isEqualTo(0);
}</code></pre>
<p>To illustrate, let&#8217;s trace through the example with <em>26</em> (binary <em>11010</em>):</p>
<pre><code class="language-java">n     = 11010  (26)
mask  = 11111  (31)
n ^ mask = 00101  (5)</code></pre>
<p>This approach effectively and efficiently flips only the significant bits.</p>
<h3 id="bd-2-using-integerhighestonebit" data-id="2-using-integerhighestonebit">4.2. Using <em>Integer.highestOneBit()</em></h3>
<div class="bd-anchor" id="2-using-integerhighestonebit"></div>
<p>We can also use the built-in <em>Integer.highestOneBit()</em> method to build the mask. This method returns a value with only the highest bit of the input set:</p>
<pre><code class="language-java">public static int flipSignificantBitsUsingHighestOneBit(int n) {
    if (n == 0) {
        return 0;
    }
    int mask = (Integer.highestOneBit(n) &lt;&lt; 1) - 1;
    return n ^ mask;
}</code></pre>
<p>Here, <em>Integer.highestOneBit(n)</em> returns the value of the most significant bit. <strong>By shifting it left by one position and subtracting <em>1</em>, we create a mask with a <em>1</em> at each significant bit</strong>. Then, a XOR operation with this mask again flips only those bits.</p>
<h3 id="bd-3-using-the-bitwise-not-with-a-mask" data-id="3-using-the-bitwise-not-with-a-mask">4.3. Using the Bitwise NOT With a Mask</h3>
<div class="bd-anchor" id="3-using-the-bitwise-not-with-a-mask"></div>
<p>Instead of XOR, we can also combine the bitwise NOT operator with a mask to get the same result:</p>
<pre><code class="language-java">public static int flipSignificantBitsUsingNot(int n) {
    if (n == 0) {
        return 0;
    }
    int bitLength = Integer.SIZE - Integer.numberOfLeadingZeros(n);
    int mask = (1 &lt;&lt; bitLength) - 1;
    return ~n &amp; mask;
}</code></pre>
<p>This function first computes the bitwise NOT of <em>n</em>, which flips all 32 bits. Then, the AND operation with the mask zeroes out all the bits beyond the significant ones. Simply put, <strong>the result is equivalent to flipping only the significant bits</strong>.</p>
<h2 id="bd-alternative-methods" data-id="alternative-methods">5. Alternative Methods</h2>
<div class="bd-anchor" id="alternative-methods"></div>
<p>Apart from the standard bitwise operators, there are other, more unorthodox ways to flip all 32 bits of an integer.</p>
<h3 id="bd-1-using-arithmetic-negation" data-id="1-using-arithmetic-negation">5.1. Using Arithmetic Negation</h3>
<div class="bd-anchor" id="1-using-arithmetic-negation"></div>
<p>Due to the two&#8217;s complement representation, flipping all bits of <em>n</em> is equivalent to computing <em>-n &#8211; 1</em>:</p>
<pre><code class="language-java">public static int flipBitsArithmetic(int n) {
    return -n - 1;
}</code></pre>
<p>This works because, in two&#8217;s complement, the negation of <em>n</em> is the bitwise complement plus <em>1</em> (<em>-n = ~n + 1</em>). <strong>Therefore, <em>~n = -n &#8211; 1</em>, which gives the same result as the bitwise NOT operator</strong>.</p>
<h3 id="bd-2-using-xor-with--1" data-id="2-using-xor-with--1">5.2. Using XOR With <em>-1</em></h3>
<div class="bd-anchor" id="2-using-xor-with--1"></div>
<p>Another way to flip all bits is to XOR the number with <em>-1</em>. In binary, we represent <em>-1</em> as all 1s (<em>11111111&#8230;1</em> in 32 bits). Notably, <em>~0</em> also evaluates to <em>-1</em>, so we can use either interchangeably:</p>
<pre><code class="language-java">public static int flipBitsXorMinusOne(int n) {
    return n ^ -1;
}</code></pre>
<p>Since XOR with <em>1</em> flips a bit, performing XOR with a value where all bits are <em>1</em> effectively flips every bit in the integer. <strong>This produces the same result as the ~ operator</strong>.</p>
<h2 id="bd-conclusion" data-id="conclusion">6. Conclusion</h2>
<div class="bd-anchor" id="conclusion"></div>
<p>In this article, we explored several approaches for flipping bits of an integer in Java. We started with the bitwise NOT operator for full 32-bit flipping. Next, we looked at mask-based methods for flipping only the significant bits using XOR and AND operations. Finally, we covered alternative approaches using arithmetic negation and XOR.</p>
<p>As always, all the source code is available <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-lang-math-5">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/java-flip-bits-number">Flip the Bits of a Number in Java</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953487332/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953487332/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2021%2f09%2fJava-8-Featured-1024x536.png"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953487332/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/java-flip-bits-number#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/java-flip-bits-number/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953487332/0/baeldung~Flip-the-Bits-of-a-Number-in-Java/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2021/09/Java-8-Featured-150x150.png</webfeeds:featuredImage></item>
<item>
<feedburner:origLink>https://www.baeldung.com/spring-security-7-mfa</feedburner:origLink>
		<title>Multi-Factor Authentication in Spring Security 7</title>
		<link>https://feeds.feedblitz.com/~/953487335/0/baeldung~MultiFactor-Authentication-in-Spring-Security</link>
					<comments>https://feeds.feedblitz.com/~/953487335/0/baeldung~MultiFactor-Authentication-in-Spring-Security#respond</comments>
		
		<dc:creator><![CDATA[Sagar Verma]]></dc:creator>
		<pubDate>Tue, 07 Apr 2026 22:52:17 +0000</pubDate>
				<category><![CDATA[Spring Security]]></category>
		<category><![CDATA[Authentication]]></category>
		<category><![CDATA[popular]]></category>
		<guid isPermaLink="false">https://www.baeldung.com/?p=203362</guid>
					<description><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2017/08/Spring-Security-2.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="max-width:100% !important;height:auto !important;float: left; margin-right: 5px;" loading="lazy" /><p>Spring Security 7 introduces built-in support for multi-factor authentication, allowing developers to enforce multiple authentication steps using the existing authorization model.</p>
The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/953487335/0/baeldung~MultiFactor-Authentication-in-Spring-Security">Multi-Factor Authentication in Spring Security 7</a> first appeared on <a rel="NOFOLLOW" href="https://www.baeldung.com">Baeldung</a>.<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953487335/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2017%2f08%2fSpring-Security-2.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-security-7-mfa#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-security-7-mfa/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<img src="https://www.baeldung.com/wp-content/uploads/2017/08/Spring-Security-2.jpg" class="webfeedsFeaturedVisual wp-post-image" alt="" style="float: left; margin-right: 5px;" decoding="async" loading="lazy" srcset="https://www.baeldung.com/wp-content/uploads/2017/08/Spring-Security-2.jpg 952w, https://www.baeldung.com/wp-content/uploads/2017/08/Spring-Security-2-300x157.jpg 300w, https://www.baeldung.com/wp-content/uploads/2017/08/Spring-Security-2-768x402.jpg 768w" sizes="auto, (max-width: 580px) 100vw, 580px" /><h2 data-section- data-start="52" data-end="66" id="bd-v7scl5" data-id="v7scl5">1. Overview</h2>
<div class="bd-anchor" id="v7scl5"></div>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-security-basic-authentication">Authentication</a> is the first line of defense in all web applications. Traditionally, applications rely on a username and password to verify a user&#8217;s identity. However, experts no longer consider relying on a single authentication factor secure for modern systems.</p>
<p><strong>Multi-Factor Authentication (MFA)</strong> <strong>addresses this by requiring users to verify their identity using multiple independent factors before accessing a system.</strong></p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://docs.spring.io/spring-security/reference/whats-new.html">Spring Security 7</a> introduces built-in support for <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://spring.io/blog/2025/10/21/multi-factor-authentication-in-spring-security-7">multi-factor authentication</a>, allowing developers to enforce multiple authentication steps using the existing authorization model. In this article, we’ll explore how MFA works in Spring Security 7 and how to implement it in a Spring Boot application.</p>
<h2 data-section- data-start="1736" data-end="1779" id="bd-f626pv" data-id="f626pv">2. Understanding MFA in Spring Security 7</h2>
<div class="bd-anchor" id="f626pv"></div>
<p><strong>Spring Security 7</strong> <strong>introduces a new way to model authentication factors using authorities</strong>. <strong>Instead of treating MFA as a separate authentication mechanism, Spring Security progressively grants authorities for each successful authentication factor.</strong></p>
<p>Multi-Factor Authentication (MFA) strengthens security by requiring users to verify their identity using multiple independent factors. These factors typically fall into three categories: something the user knows, such as a password or PIN, something the user has, such as a mobile device or email token, and something the user is, such as a fingerprint or other biometric data. By combining these factors, applications significantly reduce the risk of compromised credentials and unauthorized access.</p>
<p>Each time a user successfully authenticates with a specific factor, Spring Security adds a corresponding authority to the authentication object. This authority represents the factor that has already been verified during the authentication process. Some common examples include <strong><em>FACTOR_PASSWORD</em> for password-based authentication, <em>FACTOR_X509</em> for certificate-based authentication, and <em>FACTOR_OTT</em> for one-time token authentication.</strong> These authorities are represented internally by the <em>FactorGrantedAuthority</em> class and become part of the authenticated user&#8217;s security context.</p>
<p>This design allows authorization rules to verify that the required authentication factors are satisfied before granting access to protected resources.</p>
<h2 data-section- data-start="2865" data-end="2883" id="bd-p5u09" data-id="p5u09">3. Project Setup</h2>
<div class="bd-anchor" id="p5u09"></div>
<p data-start="2885" data-end="2977">Before implementing multi-factor authentication, we’ll set up a simple <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-boot">Spring Boot</a> application <span style="margin: 0px;padding: 0px">using <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://start.spring.io/" target="_blank" rel="noopener">Spring Initializr</a></span> with Spring Security 7. First, we need to configure the required dependencies.</p>
<p data-start="2885" data-end="2977">We include Spring Boot starters for <em><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web/4.0.3">web</a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security/4.0.3/dependencies">security</a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test/4.0.3/dependencies">starter-test</a>, <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webmvc-test/4.0.3">webmvc-test</a>, </em>and <em><a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://mvnrepository.com/artifact/org.springframework.security/spring-security-test/7.0.0">security-testing</a></em>:</p>
<pre><code class="language-xml">&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
    &lt;version&gt;4.0.3&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-security&lt;/artifactId&gt;
    &lt;version&gt;4.0.3&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
    &lt;version&gt;4.0.3&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-webmvc-test&lt;/artifactId&gt;
    &lt;version&gt;4.0.3&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.security&lt;/groupId&gt;
    &lt;artifactId&gt;spring-security-test&lt;/artifactId&gt;
    &lt;version&gt;7.0.0&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
<p data-start="0" data-end="308">This configuration adds the core dependencies required for our application. It includes Spring Boot’s web support for building REST endpoints, the Spring Security framework for implementing authentication and authorization, and Spring Security testing utilities for writing security-focused unit tests.</p>
<p data-start="310" data-end="458" data-is-last-node="" data-is-only-node="">With these dependencies in place, the application now has everything required to configure and enable multi-factor authentication.</p>
<h2 data-section- data-start="4204" data-end="4254" id="bd-vp91pr" data-id="vp91pr">4. Enabling Multi-Factor Authentication Globally</h2>
<div class="bd-anchor" id="vp91pr"></div>
<p>Spring Security 7 introduces a convenient annotation called <em>@EnableMultiFactorAuthentication</em>. <strong>This annotation allows developers to define which authentication factors are required for all protected endpoints.</strong></p>
<p data-start="4502" data-end="4598">The following configuration enables MFA globally using password and X509 authentication factors:</p>
<pre><code class="language-java">@Configuration
@EnableWebSecurity
@EnableMultiFactorAuthentication(
  authorities = { FactorGrantedAuthority.PASSWORD_AUTHORITY, FactorGrantedAuthority.X509_AUTHORITY }
)
public class GlobalMfaSecurityConfig {
    @Bean
    @Order(3)
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.securityMatcher("/**").authorizeHttpRequests(auth -&gt;auth.requestMatchers("/public")
          .permitAll().anyRequest().authenticated()).formLogin(withDefaults());
        return http.build();
    }
}</code></pre>
<p data-start="0" data-end="257">This configuration enables Spring Security for the application and enables multi-factor authentication globally. As part of the setup, it specifies that the user must complete two authentication factors before the system considers them fully authenticated.</p>
<p data-start="259" data-end="629" data-is-last-node="" data-is-only-node="">In this case, the required factors are password and X.509 certificate authentication. Once the configuration is active, every secured endpoint in the application requires both factors for access to be granted. Applying MFA globally like this helps avoid inconsistencies and reduces the risk of missing MFA rules in individual authorization configurations.</p>
<h2 data-section- data-start="5594" data-end="5633" id="bd-kbel6w" data-id="kbel6w">5. Applying MFA to Specific Endpoints</h2>
<div class="bd-anchor" id="kbel6w"></div>
<p data-start="5635" data-end="5774">In many applications, MFA should be required only for sensitive endpoints, such as account settings, financial operations, or admin actions. <strong>Spring Security provides <i>the AuthorizationManagerFactory</i> API to define MFA rules programmatically.</strong></p>
<p data-start="5919" data-end="5985">The following configuration requires MFA only for admin endpoints:</p>
<pre><code class="language-java">@Configuration
@EnableWebSecurity
public class AdminMfaSecurityConfig {
    @Bean
    @Order(1)
    SecurityFilterChain adminSecurityFilterChain(HttpSecurity http) throws Exception {
        AuthorizationManagerFactory&lt;Object&gt; mfa = AuthorizationManagerFactories.multiFactor()
          .requireFactors(
            FactorGrantedAuthority.PASSWORD_AUTHORITY,
            FactorGrantedAuthority.X509_AUTHORITY)
          .build();
        http.securityMatcher("/admin/**").authorizeHttpRequests(auth -&gt;auth.requestMatchers("/admin/**")
          .access(mfa.hasRole("ADMIN")).anyRequest().authenticated()).formLogin(withDefaults());
        return http.build();
    }
}</code></pre>
<p data-start="0" data-end="262">In this configuration, multi-factor authentication is applied only to requests that match the <em data-start="94" data-end="103">/admin/</em>** endpoints. When a user attempts to access these routes, Spring Security checks whether the required authentication factors are present.</p>
<p data-start="264" data-end="571" data-is-last-node="" data-is-only-node="">In addition to completing both authentication factors, the user must also have the <em data-start="347" data-end="354">ADMIN</em> role. This approach provides fine-grained control over security rules, allowing developers to enforce MFA only on sensitive endpoints while keeping the rest of the application accessible with standard authentication.</p>
<h2 data-section- data-start="7060" data-end="7109" id="bd-oeaajp" data-id="oeaajp">6. Implementing Time-Based Authentication Rules</h2>
<div class="bd-anchor" id="oeaajp"></div>
<p data-start="7111" data-end="7296">Some applications require users to re-authenticate before performing sensitive actions. For example, a banking application may require a fresh login before updating payment information. Spring Security 7 supports time-based MFA rules.</p>
<p data-start="7391" data-end="7497">The following configuration requires the user to authenticate the password factor within the last five minutes:</p>
<pre><code class="language-java">@Configuration
@EnableWebSecurity
public class TimeBasedMfaSecurityConfig {
    @Bean
    @Order(2)
    SecurityFilterChain profileSecurityFilterChain(HttpSecurity http) throws Exception {
        AuthorizationManagerFactory&lt;Object&gt; recentLogin = AuthorizationManagerFactories.
          multiFactor().requireFactor(
            factor -&gt; factor.passwordAuthority().validDuration(Duration.ofMinutes(5)))
          .build();
        http.securityMatcher("/profile", "/profile/**").authorizeHttpRequests(
          auth -&gt; auth.requestMatchers("/profile", "/profile/**")
            .access(recentLogin.authenticated())
            .anyRequest().
            authenticated()).formLogin(withDefaults());
        return http.build();
    }
}</code></pre>
<p data-start="0" data-end="258">This rule allows users to navigate most parts of the application using their existing authenticated session. However, when a user attempts to access endpoints under <em>*/profile/**</em>, the system verifies whether the password authentication was completed recently.</p>
<p data-start="260" data-end="546" data-is-last-node="" data-is-only-node=""><strong>If the password factor is older than five minutes, Spring Security requires the user to authenticate again before granting access. This approach commonly allows users to perform sensitive operations, ensuring they complete critical actions only after a recent, verified authentication step.</strong></p>
<h2 data-section- data-start="8828" data-end="8866" id="bd-k4s5ze" data-id="k4s5ze">7. Implementing User-Based MFA Rules</h2>
<div class="bd-anchor" id="k4s5ze"></div>
<p data-start="8868" data-end="9025">Sometimes MFA rules apply only to specific users. For example, administrators may be required to use MFA while regular users can log in with a single factor. Spring Security allows implementing custom authorization managers to support such scenarios.</p>
<p data-start="9159" data-end="9218">The following example enforces MFA only for the admin user:</p>
<pre><code class="language-java">@Component
public class AdminMfaAuthorizationManager implements AuthorizationManager&lt;Object&gt; {
    AuthorizationManager&lt;Object&gt; mfa =
      AllAuthoritiesAuthorizationManager.hasAllAuthorities(FactorGrantedAuthority.OTT_AUTHORITY,
        FactorGrantedAuthority.PASSWORD_AUTHORITY);
    @Override
    public AuthorizationResult authorize(Supplier&lt;? extends Authentication&gt; authentication, Object context) {
        Authentication auth = authentication.get();
        if (auth != null &amp;&amp; "admin".equals(auth.getName())) {
            return mfa.authorize(authentication, context);
        }
        return new AuthorizationDecision(true);
    }
}</code></pre>
<p data-start="0" data-end="245">This logic checks the authenticated user&#8217;s identity and applies MFA rules conditionally. If the authenticated user is an admin, the system verifies that the user has completed both required authentication factors before granting access.</p>
<p data-start="247" data-end="515" data-is-last-node="" data-is-only-node="">For all other users, the system allows the request without enforcing additional MFA checks. This approach is useful when introducing MFA gradually, allowing organizations to enforce stronger security for high-privilege users first before extending it to the entire user base.</p>
<h2 data-section- data-start="10148" data-end="10179" id="bd-15wz0nu" data-id="15wz0nu">8. Writing Unit Tests for MFA</h2>
<div class="bd-anchor" id="15wz0nu"></div>
<p data-start="0" data-end="247">Testing authentication flows is essential to ensure that security rules behave as expected. Without proper tests, it becomes difficult to verify whether authentication requirements such as roles, permissions, or MFA factors are correctly enforced.</p>
<p data-start="249" data-end="541" data-is-last-node="" data-is-only-node="">Spring Security provides dedicated testing utilities that make it easier to simulate authenticated users and validate authorization behavior. These tools allow developers to write focused tests that verify that security configurations function correctly without requiring a full authentication setup.</p>
<h3 data-section- data-start="10349" data-end="10375" id="bd-dkifrs" data-id="dkifrs">8.1. Controller Example</h3>
<div class="bd-anchor" id="dkifrs"></div>
<p data-start="10377" data-end="10425">Before writing tests, we define a simple controller that exposes the endpoints secured by our MFA configurations:</p>
<pre><code class="language-java">@RestController
public class DemoController {
    @GetMapping("/public")
    public String publicEndpoint() {
        return "public endpoint";
    }
    @GetMapping("/profile")
    public String profileEndpoint() {
        return "profile endpoint";
    }
    @GetMapping("/admin/dashboard")
    public String adminDashboard() {
        return "admin dashboard";
    }
}</code></pre>
<p>This controller exposes three endpoints <em>/public, /profile, </em>and <em>/admin/dashboard</em> that help demonstrate different MFA enforcement strategies.</p>
<h3 data-section- data-start="10640" data-end="10665" id="bd-1buszc5" data-id="1buszc5">8.2. MFA Security Test</h3>
<div class="bd-anchor" id="1buszc5"></div>
<p data-start="10667" data-end="10736">This test verifies how the system behaves when it enforces multi-factor authentication globally:</p>
<pre><code class="language-java">@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
class GlobalMfaSecurityTest {
    @Autowired
    MockMvc mockMvc;
    @Test
    void givenUserWithoutMfa_whenAccessProfile_thenForbidden() throws Exception {
        mockMvc.perform(get("/profile").with(user("user").roles("USER")))
          .andExpect(status().is3xxRedirection())
          .andExpect(header().string("Location", containsString("/login")));
    }
}</code></pre>
<p>This test simulates a user attempting to access the admin endpoint without completing the required MFA factors. Since the authentication request only contains the basic role and does not include the necessary factor authorities, the request does not satisfy the configured security rules. As a result, Spring Security returns a 403 Forbidden response because the user has not completed all required authentication factors.</p>
<h3 data-section- data-start="11803" data-end="11819" id="bd-f2307e" data-id="f2307e">8.3. Admin Endpoint MFA Test</h3>
<div class="bd-anchor" id="f2307e"></div>
<p data-section-id="f2307e" data-start="11803" data-end="11819">Next, we&#8217;ll verify that the system enforces MFA for admin endpoints:</p>
<pre><code class="language-java">@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
class AdminMfaSecurityTest {
    @Autowired
    MockMvc mockMvc;
    @Test
    void givenAdminWithoutMfa_whenAccessAdminEndpoint_thenForbidden() throws Exception {
        mockMvc.perform(get("/admin/dashboard").with(user("admin").roles("ADMIN")))
          .andExpect(status().is3xxRedirection())
          .andExpect(header().string("Location", containsString("/login")));
    }
}</code></pre>
<p>This test simulates an administrator attempting to access the <em>/admin/dashboard</em> endpoint. Although the user has the required ADMIN role, the request does not include the required MFA authorities. Because the authentication factors are incomplete, Spring Security redirects the request to the login page. This confirms that MFA enforcement works correctly for privileged endpoints.</p>
<h3 id="bd-4-time-based-mfa-security-test" data-id="4-time-based-mfa-security-test">8.4. Time-Based MFA Security Test</h3>
<div class="bd-anchor" id="4-time-based-mfa-security-test"></div>
<p>Some operations require users to authenticate recently to ensure no one has compromised the session. The following test verifies that the profile endpoint requires a recent authentication:</p>
<pre><code class="language-java">@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
class TimeBasedMfaSecurityTest {
    @Autowired
    MockMvc mockMvc;
    @Test
    void givenUserWithoutRecentAuthentication_whenAccessProfile_thenForbidden() throws Exception {
        mockMvc.perform(get("/profile").with(user("user").roles("USER")))
          .andExpect(status().is3xxRedirection())
          .andExpect(header().string("Location", containsString("/login")));
    }
}</code></pre>
<p>This test checks that the <em>/profile</em> endpoint requires a recent authentication. Since the simulated request does not include the necessary MFA factor information, Spring Security redirects the request to the login page. This confirms that the system correctly enforces the time-based MFA rule.</p>
<h2 data-section- data-start="11803" data-end="11819" id="bd-f2307e-1" data-id="f2307e-1">9. Conclusion</h2>
<div class="bd-anchor" id="f2307e-1"></div>
<p>Multi-Factor Authentication (MFA) is a critical security measure for modern applications, helping reduce the risk of unauthorized access by requiring multiple verification factors.</p>
<p>Spring Security 7 provides built-in support for MFA, allowing developers to enforce multiple authentication steps using the existing authorization model. In this article, we explored how <em>FactorGrantedAuthority</em> models MFA, how to enable it globally with <em>@EnableMultiFactorAuthentication</em>, and how to apply it selectively to specific endpoints using <em>AuthorizationManagerFactory</em>. We also covered time-based rules, custom user-based policies, and testing MFA behavior using Spring Security test utilities.</p>
<p>By leveraging these features, developers can build secure and flexible authentication flows. As security threats continue to evolve, implementing MFA is no longer optional but an essential step in protecting user data and critical systems. As always, the code for this example is available <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://github.com/eugenp/tutorials/tree/master/spring-security-modules/spring-security-mfa">over on GitHub</a>.</p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com/spring-security-7-mfa">Multi-Factor Authentication in Spring Security 7</a> first appeared on <a href="https://feeds.feedblitz.com/~/t/0/0/baeldung/~https://www.baeldung.com">Baeldung</a>.<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/953487335/0/baeldung">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Pin it!" href="https://feeds.feedblitz.com/_/29/953487335/baeldung,https%3a%2f%2fwww.baeldung.com%2fwp-content%2fuploads%2f2017%2f08%2fSpring-Security-2.jpg"><img height="20" src="https://assets.feedblitz.com/i/pinterest20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by email" href="https://feeds.feedblitz.com/_/19/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/email20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/953487335/baeldung"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a rel="NOFOLLOW" title="View Comments" href="https://www.baeldung.com/spring-security-7-mfa#respond"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/comments20.png"></a>&#160;<a title="Follow Comments via RSS" href="https://www.baeldung.com/spring-security-7-mfa/feed"><img height="20" style="border:0;margin:0;padding:0;" src="https://assets.feedblitz.com/i/commentsrss20.png"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/953487335/0/baeldung~MultiFactor-Authentication-in-Spring-Security/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<webfeeds:featuredImage>https://www.baeldung.com/wp-content/uploads/2017/08/Spring-Security-2-150x150.jpg</webfeeds:featuredImage></item>
</channel></rss>

