<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Java - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Java - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 14 May 2026 11:47:08 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/java/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Install Java on Mac in 2026 ]]>
                </title>
                <description>
                    <![CDATA[ Java is the most widely used programming language for enterprise software, Android development, and university computer science courses. Apple doesn't include Java with macOS, so you need to install i ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-install-java-on-mac/</link>
                <guid isPermaLink="false">69987a933dc17c4862f4c18d</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ macOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Development Tools ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Kehoe ]]>
                </dc:creator>
                <pubDate>Fri, 20 Feb 2026 15:15:31 +0000</pubDate>
                <media:content url="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/5e1e335a7a1d3fcc59028c64/ab23255a-f10d-485b-9fd2-ee247138ed9e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Java is the most widely used programming language for enterprise software, Android development, and university computer science courses. Apple doesn't include Java with macOS, so you need to install it yourself.</p>
<p>If you search for "install Java on Mac," you'll find a confusing number of vendors, version numbers, and installation methods. To make it easy, I'll cut through the confusion and show you a recommended Java installation path that takes about five minutes.</p>
<p>Here's my recommendation: Install <strong>Java 25</strong> using <strong>Homebrew</strong> with the <strong>Eclipse Temurin</strong> distribution. Java 25 is the current LTS (Long-Term Support) release and your best choice unless your work team or university course uses an older version. With Homebrew, one terminal command accommodates the entire installation. The Temurin distribution is free, certified, and unencumbered by Oracle's licensing restrictions.</p>
<p>Now I’ll walk you through the process.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a href="#heading-what-you-need-before-you-begin">What You Need Before You Begin</a></p>
</li>
<li><p><a href="#heading-how-to-check-if-java-is-already-installed">How to Check if Java Is Already Installed</a></p>
</li>
<li><p><a href="#heading-why-eclipse-temurin-and-why-not-oracle">Why Eclipse Temurin and Why Not Oracle</a></p>
</li>
<li><p><a href="#heading-how-to-install-java-with-homebrew">How to Install Java with Homebrew</a></p>
</li>
<li><p><a href="#heading-how-to-verify-the-installation">How to Verify the Installation</a></p>
</li>
<li><p><a href="#heading-how-to-set-javahome-for-build-tools">How to Set JAVA_HOME for Build Tools</a></p>
</li>
<li><p><a href="#heading-how-to-troubleshoot-common-problems">How to Troubleshoot Common Problems</a></p>
</li>
<li><p><a href="#heading-alternative-installation-methods">Alternative Installation Methods</a></p>
</li>
<li><p><a href="#heading-whats-next">What's Next</a></p>
</li>
</ol>
<h2 id="heading-what-you-need-before-you-begin">What You Need Before You Begin</h2>
<p>With this recommended path, you only need two things before you install Java: a terminal application and the Homebrew package manager.</p>
<h3 id="heading-terminal">Terminal</h3>
<p>Terminal is the built-in <a href="https://mac.install.guide/terminal/">Mac terminal application</a>. If you don’t know, you can learn <a href="https://mac.install.guide/terminal/open">how to open Terminal here</a>. You'll use it to run the installation commands.</p>
<h3 id="heading-homebrew">Homebrew</h3>
<p>Homebrew is a package manager you can use to install software programs for the command line. Check if you already have it like this:</p>
<pre><code class="language-bash">$ brew --version
Homebrew 5.0.11
</code></pre>
<p>If you see a version number, you're ready. If you see <a href="https://mac.install.guide/homebrew/zsh-command-not-found-brew">zsh: command not found: brew</a> you need to install Homebrew first. Follow the instructions at <a href="https://mac.install.guide/homebrew/3">Install Homebrew</a>.</p>
<h2 id="heading-how-to-check-if-java-is-already-installed">How to Check if Java Is Already Installed</h2>
<p>Run this command to check for an existing Java installation:</p>
<pre><code class="language-bash">$ java -version
</code></pre>
<p>You'll see one of two results.</p>
<p><strong>If Java is installed,</strong> you'll see output like this:</p>
<pre><code class="language-bash">openjdk version "25.0.1" 2025-10-21 LTS
OpenJDK Runtime Environment Temurin-25.0.1+8 (build 25.0.1+8-LTS)
OpenJDK 64-Bit Server VM Temurin-25.0.1+8 (build 25.0.1+8-LTS, mixed mode)
</code></pre>
<p>If the version number shows 25, you already have the latest Java and you can stop here.</p>
<p><strong>If Java is not installed,</strong> you'll see a message, "The operation couldn't be completed. Unable to locate a Java Runtime." You'll need to install Java as described below.</p>
<p>If you previously installed Java but see this dialog, something is wrong with your installation. See <a href="https://mac.install.guide/java/unable-to-locate">Unable to Locate a Java Runtime</a> for troubleshooting. For detailed guidance on Java version output, see <a href="https://mac.install.guide/java/version">Check Java Version on Mac</a>.</p>
<h2 id="heading-why-eclipse-temurin-and-why-not-oracle">Why Eclipse Temurin and Why Not Oracle</h2>
<p>If you search for Java downloads, you'll encounter several potentially confusing terms. Here's what they mean.</p>
<p><strong>JDK</strong> stands for Java Development Kit. It contains the compiler, runtime, and developer tools you need to build and run Java applications. Vendors used to offer a JRE (Java Runtime Environment) for non-developers, but now the JDK does everything.</p>
<p><strong>OpenJDK</strong> is the official open-source implementation of Java. All major Java vendors build from this same source code, so the core functionality is identical across vendors.</p>
<p><strong>Eclipse Temurin</strong> is the distribution many developers recommend. It comes from the Adoptium project and is backed by IBM, Microsoft, Red Hat, and Google, among others. It's completely free for any use, including commercial production. Temurin is TCK-certified, meaning it passes Oracle's official compatibility tests (over 139,000 of them). You can trust that your Java code will run correctly.</p>
<p><strong>Why not Oracle JDK?</strong> Oracle changed its licensing in January 2023. The new model charges per employee across the entire organization, not per Java user. A 500-person company would pay $90,000 per year. Oracle actively audits for compliance.</p>
<p>Temurin is functionally identical to Oracle JDK and is free to use under its open‑source license, avoiding Oracle’s Java subscription fees.</p>
<p>If you deploy to AWS, Amazon Corretto is another good free option. If you need Java 8 for legacy code, Azul Zulu provides well-supported builds. For a comparison of Java distributions, see <a href="https://mac.install.guide/java/jdk">Install JDK on Mac</a>.</p>
<h2 id="heading-how-to-install-java-with-homebrew">How to Install Java with Homebrew</h2>
<p>Homebrew offers two ways to install Java: the cask method and the formula method. The cask method is easier because it installs the vendor's macOS package to the standard system location. Apple's macOS discovers it automatically with no extra configuration.</p>
<p>Run these two commands:</p>
<pre><code class="language-bash">$ brew update
$ brew install --cask temurin@25
</code></pre>
<p>The first command refreshes Homebrew's package list. The second downloads and installs Eclipse Temurin JDK 25.</p>
<p>Homebrew places the JDK at <code>/Library/Java/JavaVirtualMachines/temurin-25.jdk/</code>. This is the standard macOS location for Java installations. Apple's macOS includes a Java launcher at <code>/usr/bin/java</code> that automatically searches this directory. You don't need to configure your PATH.</p>
<p>Homebrew also detects your Mac's chip architecture automatically. You'll get the correct native build whether you have an Apple Silicon or Intel Mac.</p>
<p>For more details about the Homebrew installation process, including the alternative formula method and troubleshooting, see <a href="https://mac.install.guide/java/brew-cask">Brew Install Java, Cask Method</a>.</p>
<h2 id="heading-how-to-verify-the-installation">How to Verify the Installation</h2>
<p>After installation, open a new Terminal window. Existing windows may not detect the new installation.</p>
<p>Check the Java version:</p>
<pre><code class="language-bash">$ java -version
openjdk version "25.0.1" 2025-10-21 LTS
OpenJDK Runtime Environment Temurin-25.0.1+8 (build 25.0.1+8-LTS)
OpenJDK 64-Bit Server VM Temurin-25.0.1+8 (build 25.0.1+8-LTS, mixed mode)
</code></pre>
<p>This confirms three things: the version number (25.0.1), the distribution (Temurin), and that the 64-Bit Server VM is active.</p>
<p>Check the compiler:</p>
<pre><code class="language-bash">$ javac -version
javac 25.0.1
</code></pre>
<p>List all installed JDKs:</p>
<pre><code class="language-bash">$ /usr/libexec/java_home -V
Matching Java Virtual Machines (1):
    25.0.1 (arm64) "Eclipse Adoptium" - "OpenJDK 25.0.1" /Library/Java/JavaVirtualMachines/temurin-25.jdk/Contents/Home
</code></pre>
<p>If all three commands produce the expected output, Java is installed and working.</p>
<h2 id="heading-how-to-set-javahome-for-build-tools">How to Set JAVA_HOME for Build Tools</h2>
<p>For most users, Java works immediately after installation. The <code>java</code> and <code>javac</code> commands are available with no additional setup.</p>
<p>However, some build tools require the <code>JAVA_HOME</code> environment variable. Apache Maven, Gradle, and Android SDK all look for it. If you see errors mentioning "JAVA_HOME is not set," you need this step.</p>
<p>If you only run Java applications or use IntelliJ IDEA (which manages Java paths internally), you can skip this section.</p>
<p>Add this line to your <code>~/.zprofile</code> file:</p>
<pre><code class="language-bash">export JAVA_HOME=$(/usr/libexec/java_home)
</code></pre>
<p>This uses Apple's <code>java_home</code> utility to find the installed JDK automatically. After saving the file, you'll need to run <code>source ~/.zprofile</code> or close and reopen your terminal. Verify it works:</p>
<pre><code class="language-bash">\( echo \)JAVA_HOME
/Library/Java/JavaVirtualMachines/temurin-25.jdk/Contents/Home
</code></pre>
<p>For complete configuration instructions, see <a href="https://mac.install.guide/java/java-home">Set JAVA_HOME on Mac</a>.</p>
<h2 id="heading-how-to-troubleshoot-common-problems">How to Troubleshoot Common Problems</h2>
<p><strong>"Unable to locate a Java Runtime" message keeps appearing.</strong> Run <code>java -version</code> to verify Java is installed. If you just installed Java, see <a href="https://mac.install.guide/java/unable-to-locate">Unable to Locate a Java Runtime</a>.</p>
<p><strong>Wrong Java version appears.</strong> You have multiple JDKs installed and macOS selected a different one. Run <code>/usr/libexec/java_home -V</code> to list all installed versions. See <a href="https://mac.install.guide/java/java-home">Set JAVA_HOME on Mac</a> to point to the version you want.</p>
<h2 id="heading-alternative-installation-methods">Alternative Installation Methods</h2>
<p>Homebrew is the fastest path, but other options exist.</p>
<ol>
<li><p><strong>Manual download</strong>: You can download the .pkg installer directly from <a href="http://adoptium.net">adoptium.net</a> and double-click to install. This is a good choice if you don't use Homebrew. See <a href="https://mac.install.guide/java/install">Install Java on Mac</a> for detailed instructions.</p>
</li>
<li><p><strong>Homebrew formula.</strong> The command <code>brew install openjdk@25</code> installs a Homebrew-managed build. This approach requires manual symlink configuration before macOS can discover it. See <a href="https://mac.install.guide/java/brew-formula">Brew Install Java, Formula Method</a> for details.</p>
</li>
<li><p><strong>Version managers.</strong> Tools like SDKMAN and mise can install and switch between multiple Java versions per project. If you work on codebases that require different Java versions, see <a href="https://mac.install.guide/java/version-managers">Java Version Managers</a>.</p>
</li>
</ol>
<h2 id="heading-whats-next">What's Next</h2>
<p>You now have Java 25 installed on your Mac. You've verified it works and configured <code>JAVA_HOME</code> for build tools. You're ready to compile and run Java applications.</p>
<p>If your team or university course requires Java 21 instead, see <a href="https://mac.install.guide/java/java-21">Install Java 21 on Mac</a>. If you need to remove Java, see <a href="https://mac.install.guide/java/uninstall">Uninstall Java on Mac</a>.</p>
<p>This article is based on my guides that offer additional details about how to <a href="https://mac.install.guide/java/install">install Java on Mac</a> and choose the <a href="https://mac.install.guide/java/new">latest Java version</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Your Own Circuit Breaker in Spring Boot – and Really Understand Resilience4j ]]>
                </title>
                <description>
                    <![CDATA[ This article explains how to design and implement your own circuit breaker in Spring Boot using explicit failure tracking, a scheduler-driven recovery model, and clear state transitions. Instead of relying solely on Resilience4j, we’ll walk through t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-your-own-circuit-breaker-in-spring-boot-and-really-understand-resilience4j/</link>
                <guid isPermaLink="false">69938789dce780a9836b8f09</guid>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Resilience ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Circuit breaker pattern ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ fault tolerance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Backend Engineering ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jessica Patel ]]>
                </dc:creator>
                <pubDate>Mon, 16 Feb 2026 21:09:29 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1771276149217/e55b0a5c-53e2-4d2c-a004-1467a7c2b17a.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This article explains how to design and implement your own circuit breaker in Spring Boot using explicit failure tracking, a scheduler-driven recovery model, and clear state transitions.</p>
<p>Instead of relying solely on Resilience4j, we’ll walk through the internal mechanics so you understand how circuit breakers actually work.</p>
<h2 id="heading-what-well-cover">What We’ll Cover</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites-and-technical-context">Prerequisites and Technical Context</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-circuit-breaker-in-distributed-systems">What Is a Circuit Breaker in Distributed Systems</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-circuit-breakers-matter-in-spring-boot">Why Circuit Breakers Matter in Spring Boot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-circuit-breakers-are-foundational">Why Circuit Breakers Are Foundational</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-problem-circuit-breakers-solve-that-times-and-retries-do-not">What Problem Circuit Breakers Solve That Timeouts and Retries Do Not</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-circuit-breaker-state-model">The Circuit Breaker State Model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-not-just-use-resilience4j">Why Not Just Use Resilience4j?</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-design-goals-for-a-custom-circuit-breaker">Design Goals for a Custom Circuit Breaker</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-minimal-working-circuitbreaker-class">How to Build a Minimal Working CircuitBreaker Class</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-concurrency-and-state-transition-guarantees">Concurrency and State Transition Guarantees</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-explaining-the-state-model-in-the-class">Explaining the State Model in the Class</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-failure-tracking-inside-the-class">Failure Tracking Inside the Class</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-closed-state-transitions-to-open">How Closed State Transitions to Open</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-open-state-behavior-in-the-class">OPEN State Behavior in the Class</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-schedulerdriven-recovery-entering-halfopen">Scheduler‑Driven Recovery: Entering HALF_OPEN</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-spring-boot-scheduler-example">Spring Boot Scheduler Example</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-this-connects-to-execution-flow">How This Connects to Execution Flow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-scheduler-design-and-thread-safety">Scheduler Design and Thread Safety</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-we-avoid-scheduled-for-this-design">Why We Avoid @Scheduled for This Design</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-bringing-it-all-together">Bringing It All Together</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-observability-making-the-breaker-understandable">Observability: Making the Breaker Understandable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-handling-different-failure-types">Handling Different Failure Types</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-custom-breaker-vs-resilience4j">Custom Breaker vs Resilience4j</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-you-should-not-build-your-own">When You Should Not Build Your Own</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-extending-the-design">Extending the Design</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-mistakes">Common Mistakes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites-and-technical-context"><strong>Prerequisites and Technical Context</strong></h2>
<p>This article assumes you are comfortable with core Spring Boot and Java concepts. We won’t cover framework fundamentals or basic concurrency principles in depth. Here’s what you’ll need to know:</p>
<h3 id="heading-spring-boot-basics">Spring Boot Basics</h3>
<p>You should be comfortable with how dependency injection works in Spring, how to define <code>@Configuration</code> classes and <code>@Bean</code> definitions, and the basic service-layer structure of a Spring application. In this tutorial, we’ll treat the circuit breaker as a plain Java component and wire it into Spring through configuration classes rather than annotations.</p>
<h3 id="heading-java-concurrency-fundamentals">Java Concurrency Fundamentals</h3>
<p>You don’t need to be a concurrency expert, but you should be comfortable with Java’s basic concurrency tools. The implementation uses <code>AtomicInteger</code>, volatile fields, a <code>ScheduledExecutorService</code>, and simple synchronization, so you should understand why shared mutable state is dangerous, how atomic operations differ from synchronized blocks, and why state transitions in a shared state machine must be serialized.</p>
<h3 id="heading-functional-interfaces">Functional Interfaces</h3>
<p>The circuit breaker exposes an <code>execute(Supplier&lt;T&gt;)</code> method, so you should be comfortable using <code>Supplier&lt;T&gt;</code>, writing simple lambda expressions, and wrapping outbound service calls inside a function you can pass to the breaker.</p>
<h3 id="heading-resilience4j-basics">Resilience4j Basics</h3>
<p>You don’t need hands-on Resilience4j experience, but you should know that it’s a lightweight Java fault-tolerance library that offers circuit breakers, retries, rate limiters, bulkheads, and is commonly used in Spring Boot via annotations or config. In this article we’ll only reference Resilience4j for comparison, not for actual configuration or usage.</p>
<h2 id="heading-what-is-a-circuit-breaker-in-distributed-systems">What Is a Circuit Breaker in Distributed Systems?</h2>
<p>A circuit breaker is a fault-tolerance pattern that stops a system from repeatedly attempting operations that are likely to fail.</p>
<p>The name comes from electrical engineering. In a physical circuit, a breaker “opens” when the current becomes unsafe, preventing damage. After a cooldown period, it allows current to flow again to test whether the issue has been resolved.</p>
<p>In software, the same principle applies. When Service A depends on Service B, and Service B becomes slow or unavailable, naïvely retrying every request can:</p>
<ul>
<li><p>Exhaust thread pools</p>
</li>
<li><p>Saturate connection pools</p>
</li>
<li><p>Increase latency across the system</p>
</li>
<li><p>Trigger cascading failures</p>
</li>
<li><p>Bring down otherwise healthy services</p>
</li>
</ul>
<p>Instead of continuing to send requests to a failing dependency, a circuit breaker:</p>
<ul>
<li><p>Detects repeated failures</p>
</li>
<li><p>Opens the circuit and blocks calls</p>
</li>
<li><p>Fails fast without attempting the operation</p>
</li>
<li><p>Periodically tests whether the dependency has recovered</p>
</li>
</ul>
<p>This turns uncontrolled failure into controlled degradation.</p>
<h3 id="heading-why-circuit-breakers-matter-in-spring-boot">Why Circuit Breakers Matter in Spring Boot</h3>
<p>Because circuit breakers are a foundational resilience pattern in distributed systems, most Spring Boot teams reach immediately for Resilience4j or legacy Hystrix‑style abstractions – and for good reason. These libraries are mature, well-tested, and production-proven.​</p>
<p>However, treating circuit breakers as black boxes often leads to:​</p>
<ul>
<li><p>Misconfigured thresholds</p>
</li>
<li><p>Incorrect assumptions about failure handling</p>
</li>
<li><p>Difficulty extending behavior beyond library defaults</p>
</li>
<li><p>Debugging issues where “the breaker opened, but we don’t know why”​</p>
</li>
</ul>
<p>Building your own circuit breaker – even if you never ship it to production – forces you to understand the mechanics that actually protect your system. In some cases, a custom implementation also provides flexibility that general-purpose libraries cannot.</p>
<h3 id="heading-why-circuit-breakers-are-foundational">Why Circuit Breakers Are Foundational</h3>
<p>Circuit breakers are a foundational resilience pattern because they protect your scarcest resources (like threads, network and database connections, and CPU time) from being exhausted by a failing dependency.</p>
<p>Without a breaker, a single slow service can gradually consume all of those resources and turn a local problem into a system-wide outage.</p>
<p>Circuit breakers enforce isolation boundaries between services and sit alongside timeouts, retries, bulkheads, and rate limiters, but they make one crucial strategic choice that simple retries do not: they <strong>stop trying for now</strong>. That decision is what prevents cascading collapse.</p>
<h3 id="heading-what-problem-circuit-breakers-solve-that-timeouts-and-retries-do-not">What Problem Circuit Breakers Solve That Timeouts and Retries Do Not</h3>
<p>Timeouts and retries are reactive: timeouts cap how long you wait, and retries try the same operation again in the hope it succeeds.</p>
<p>A circuit breaker is proactive. It monitors failure patterns and, once a threshold is crossed, temporarily disables the failing integration point so new requests are rejected immediately instead of timing out.This dramatically reduces resource waste and stabilizes the system under stress.</p>
<h3 id="heading-the-circuit-breaker-state-model">The Circuit Breaker State Model</h3>
<p>Any circuit breaker – library-based or custom – follows the same conceptual state machine.​</p>
<ol>
<li><p><strong>Closed:</strong> In the Closed state, all requests are allowed and failures are simply monitored.</p>
</li>
<li><p><strong>Open:</strong> When failures cross a configured threshold, the breaker moves to Open, blocks new requests, and makes them fail immediately.</p>
</li>
<li><p><strong>Half-Open:</strong> After a cooldown period, it enters Half-Open, where it lets a small number of trial requests through to test whether the dependency has recovered; based on those results, it either returns to Closed or goes back to Open.</p>
</li>
</ol>
<p>The complexity lies not in the states themselves, but in <strong>how and when transitions occur</strong>.​</p>
<h3 id="heading-why-not-just-use-resilience4j">Why Not Just Use Resilience4j?</h3>
<p>Resilience4j is excellent, but there are valid reasons to build your own:​</p>
<ul>
<li><p>You want non-standard failure logic (for example, domain-aware errors).</p>
</li>
<li><p>You need custom recovery strategies.</p>
</li>
<li><p>You want state persisted or shared differently.</p>
</li>
<li><p>You need tight integration with business metrics.</p>
</li>
<li><p>You want to understand the internals for tuning and debugging.​</p>
</li>
</ul>
<p>More importantly, understanding the internals prevents misuse. Many production incidents stem from misconfigured circuit breakers rather than missing ones.​</p>
<h2 id="heading-design-goals-for-a-custom-circuit-breaker">Design Goals for a Custom Circuit Breaker</h2>
<p>Before writing any code, we need to be clear about what “correct” behavior looks like. A circuit breaker seems simple in theory, but subtle design mistakes can introduce race conditions, false openings, or silent failures where it stops protecting the system.</p>
<p>The following goals shape a predictable and production-safe implementation.</p>
<h3 id="heading-thread-safe-and-low-overhead">Thread-Safe and Low Overhead</h3>
<p>The breaker sits on the hot path of outbound calls, so every protected request passes through it. If it introduces lock contention or heavy synchronization, it quickly becomes a bottleneck.</p>
<p>The implementation needs to avoid coarse-grained locking, use atomic primitives carefully, and serialize state transitions without blocking execution more than necessary. Thread safety is non‑negotiable: a circuit breaker that misbehaves under concurrency is worse than having no breaker at all.</p>
<h3 id="heading-predictable-state-transitions">Predictable State Transitions</h3>
<p>Circuit breakers are state machines. If their transitions are inconsistent or prone to races, you end up with split‑brain behavior – one thread believes the breaker is OPEN while another believes it is CLOSED – and your protection becomes undefined.</p>
<p>To avoid this, every transition (CLOSED → OPEN → HALF_OPEN → CLOSED) must be explicit, atomic, and deterministic, all guarded by a single transition mechanism. In this design, predictability matters far more than cleverness.</p>
<h3 id="heading-explicit-failure-tracking">Explicit Failure Tracking</h3>
<p>Not every failure should open the breaker. If you blindly count every exception, you risk opening the breaker on client validation errors, treating business rule violations as infrastructure failures, and hiding real domain bugs behind resilience logic.</p>
<p>Failure classification has to be deliberate: the breaker should react only to infrastructure‑level problems such as timeouts, connection errors, and 5xx responses, not to domain logic errors. Keeping that separation ensures your resilience layer stays aligned with actual failure modes.</p>
<h3 id="heading-time-based-recovery-using-a-scheduler">Time-Based Recovery Using a Scheduler</h3>
<p>Some implementations check timestamps on every request to decide when to move from OPEN to HALF_OPEN, adding extra branching to the hot path.</p>
<p>Instead, this design uses a scheduler: when the breaker opens, it schedules a recovery attempt, keeps the OPEN state purely fail‑fast, and avoids request‑driven polling. That approach reduces branching and contention under load. Recovery should be controlled and predictable – not opportunistic.</p>
<h3 id="heading-framework-agnostic-core-logic">Framework-Agnostic Core Logic</h3>
<p>The breaker itself should be plain Java – no Spring annotations, no AOP, and no direct framework coupling. That choice makes unit testing easier, keeps the component portable, and preserves a clean separation of concerns with less hidden magic. Spring should wrap the breaker, not define it, so your resilience strategy is not trapped inside any one framework’s abstractions.</p>
<h3 id="heading-easy-integration-into-spring-boot">Easy Integration into Spring Boot</h3>
<p>Although the core logic is framework‑agnostic, it still needs to plug cleanly into a Spring application. That means wiring it via <code>@Configuration</code>, supporting dependency injection, and calling it from clear execution points in your service layer. Resilience behavior should be obvious in code reviews. Hiding it behind annotations often leads to confusion when you are debugging production issues.</p>
<h2 id="heading-how-to-build-a-minimal-working-circuitbreaker-class">How to Build a Minimal Working CircuitBreaker Class</h2>
<p>Now let’s turn the conceptual components into a single cohesive class. This is still a minimal implementation, but it’s complete enough to demonstrate state, failure tracking, scheduling, and execution logic in one place.</p>
<p>A minimal circuit breaker consists of:​</p>
<ol>
<li><p>State holder</p>
</li>
<li><p>Failure tracker</p>
</li>
<li><p>Transition rules</p>
</li>
<li><p>Scheduler for recovery</p>
</li>
<li><p>Execution guard</p>
</li>
</ol>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CircuitBreaker</span> </span>{

    <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">State</span> </span>{
        CLOSED,
        OPEN,
        HALF_OPEN
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ScheduledExecutorService scheduler;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> failureThreshold;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> halfOpenTrialLimit;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Duration openCooldown;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicInteger failureCount = <span class="hljs-keyword">new</span> AtomicInteger(<span class="hljs-number">0</span>);
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicInteger halfOpenTrials = <span class="hljs-keyword">new</span> AtomicInteger(<span class="hljs-number">0</span>);

    <span class="hljs-comment">// All transitions go through this field, guarded by `synchronized` blocks.</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">volatile</span> State state = State.CLOSED;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CircuitBreaker</span><span class="hljs-params">(
            ScheduledExecutorService scheduler,
            <span class="hljs-keyword">int</span> failureThreshold,
            <span class="hljs-keyword">int</span> halfOpenTrialLimit,
            Duration openCooldown
    )</span> </span>{
        <span class="hljs-keyword">this</span>.scheduler = scheduler;
        <span class="hljs-keyword">this</span>.failureThreshold = failureThreshold;
        <span class="hljs-keyword">this</span>.halfOpenTrialLimit = halfOpenTrialLimit;
        <span class="hljs-keyword">this</span>.openCooldown = openCooldown;
    }

    <span class="hljs-keyword">public</span> &lt;T&gt; <span class="hljs-function">T <span class="hljs-title">execute</span><span class="hljs-params">(Supplier&lt;T&gt; action)</span> </span>{
        <span class="hljs-comment">// 1. Guards the functionality based on its current state. </span>
        <span class="hljs-comment">//We are using synchronized block for thread safety. </span>
        <span class="hljs-comment">// Make sure another thread does not override our current state</span>
        State current;
        <span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
            current = state;

            <span class="hljs-keyword">if</span> (current == State.OPEN) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Circuit breaker is OPEN. Call rejected."</span>);
            }

            <span class="hljs-keyword">if</span> (current == State.HALF_OPEN) {
                <span class="hljs-keyword">int</span> trials = halfOpenTrials.incrementAndGet();
                <span class="hljs-keyword">if</span> (trials &gt; halfOpenTrialLimit) {
                    <span class="hljs-comment">// Too many trial requests; fail fast.</span>
                    halfOpenTrials.decrementAndGet();
                    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Circuit breaker is HALF_OPEN. Trial limit exceeded."</span>);
                }
            }
        }

        <span class="hljs-comment">// 2. Execute the business functionality here. For e.g API calls to other systems </span>
        <span class="hljs-keyword">try</span> {
            T result = action.get();
            <span class="hljs-comment">// 3. Record success</span>
            onSuccess();
            <span class="hljs-keyword">return</span> result;
        } <span class="hljs-keyword">catch</span> (Throwable t) {
            <span class="hljs-comment">// 3. Record failure</span>
            onFailure(t);
            <span class="hljs-comment">// 4. Propagate to caller</span>
            <span class="hljs-keyword">if</span> (t <span class="hljs-keyword">instanceof</span> RuntimeException re) {
                <span class="hljs-keyword">throw</span> re;
            }
            <span class="hljs-keyword">if</span> (t <span class="hljs-keyword">instanceof</span> Error e) {
                <span class="hljs-keyword">throw</span> e;
            }
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(t);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onSuccess</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
            failureCount.set(<span class="hljs-number">0</span>);

            <span class="hljs-keyword">if</span> (state == State.HALF_OPEN) {
                <span class="hljs-comment">// A successful trial closes the breaker.</span>
                transitionToClosed();
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFailure</span><span class="hljs-params">(Throwable t)</span> </span>{
        <span class="hljs-comment">// Example: only count "server-side" failures.</span>
        <span class="hljs-keyword">boolean</span> breakerRelevant = <span class="hljs-keyword">true</span>; <span class="hljs-comment">// placeholder for domain-specific checks</span>

        <span class="hljs-keyword">if</span> (!breakerRelevant) {
            <span class="hljs-keyword">return</span>;
        }

        <span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
            <span class="hljs-keyword">int</span> failures = failureCount.incrementAndGet();
            <span class="hljs-keyword">if</span> (state == State.CLOSED &amp;&amp; failures &gt;= failureThreshold) {
                transitionToOpen();
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (state == State.HALF_OPEN) {
                <span class="hljs-comment">// Any failure in HALF_OPEN sends us back to OPEN.</span>
                transitionToOpen();
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transitionToOpen</span><span class="hljs-params">()</span> </span>{
        state = State.OPEN;
        <span class="hljs-comment">// Reset counters so the next CLOSED phase starts clean.</span>
        failureCount.set(<span class="hljs-number">0</span>);
        halfOpenTrials.set(<span class="hljs-number">0</span>);
        scheduleHalfOpen();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transitionToHalfOpen</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
            state = State.HALF_OPEN;
            halfOpenTrials.set(<span class="hljs-number">0</span>);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transitionToClosed</span><span class="hljs-params">()</span> </span>{
        state = State.CLOSED;
        failureCount.set(<span class="hljs-number">0</span>);
        halfOpenTrials.set(<span class="hljs-number">0</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">scheduleHalfOpen</span><span class="hljs-params">()</span> </span>{
        scheduler.schedule(
                <span class="hljs-keyword">this</span>::transitionToHalfOpen,
                openCooldown.toMillis(),
                TimeUnit.MILLISECONDS
        );
    }
}
</code></pre>
<p>Now we’ll walk through each responsibility in that class: why the fields exist, how state transitions work, where concurrency guarantees matter, how execution is guarded, and how the scheduler drives recovery.</p>
<p>Each subsection maps directly back to part of this class – we’re not introducing new concepts, just explaining the behavior implemented within the code above.</p>
<h3 id="heading-concurrency-and-state-transition-guarantees">Concurrency and State Transition Guarantees</h3>
<p>Although the breaker uses atomic primitives for counters and a volatile state field, this only works because <strong>all state transitions are guarded consistently</strong>.​</p>
<p>In practice, every transition – CLOSED → OPEN, OPEN → HALF_OPEN, HALF_OPEN → CLOSED – must be performed under the same synchronization mechanism as shown below: either a single lock or a CAS-based state machine. Mixing unsynchronized state writes with atomic counters can lead to split-brain behavior (for example, one thread reopening the breaker while another closes it).​</p>
<pre><code class="lang-java"><span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
            current = state;

            <span class="hljs-keyword">if</span> (current == State.OPEN) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Circuit breaker is OPEN. Call rejected."</span>);
            }

            <span class="hljs-keyword">if</span> (current == State.HALF_OPEN) {
                <span class="hljs-keyword">int</span> trials = halfOpenTrials.incrementAndGet();
                <span class="hljs-keyword">if</span> (trials &gt; halfOpenTrialLimit) {
                    <span class="hljs-comment">// Too many trial requests; fail fast.</span>
                    halfOpenTrials.decrementAndGet();
                    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Circuit breaker is HALF_OPEN. Trial limit exceeded."</span>);
                }
            }
        }
</code></pre>
<p>The rule is simple: <strong>reads may be optimistic, but writes and transitions must be serialized</strong>.</p>
<h3 id="heading-explaining-the-state-model-in-the-class">Explaining the State Model in the Class</h3>
<p>At the core of the implementation is a simple but strict state machine represented by the State enum: CLOSED, OPEN and HALF_OPEN</p>
<p>The <code>state</code> field is declared <code>volatile</code> so changes are immediately visible across threads. When one thread moves the breaker to a new state, other threads see that update without delay.</p>
<p>Alongside the state, the class maintains <code>failureCount</code> and <code>halfOpenTrials</code> counters using <code>AtomicInteger</code> (<strong>Refer to the code in the above section</strong>). These track how failures accumulate and how many recovery attempts we have made, without resorting to coarse‑grained locks.</p>
<p>The key design idea is separation of responsibilities: the <code>enum</code> captures the current mode of operation, while the atomic counters hold the metrics that influence state transitions. Atomic increments alone do not guarantee safe transitions, though, so all updates to the state still follow a consistent serialization strategy to avoid race conditions.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">State</span> </span>{
        CLOSED,
        OPEN,
        HALF_OPEN
    }
</code></pre>
<p>This structure gives us a clear foundation: a small, explicit state machine with observable transition boundaries.</p>
<h3 id="heading-failure-tracking-inside-the-class">Failure Tracking Inside the Class</h3>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onFailure</span><span class="hljs-params">(Throwable t)</span> </span>{
        <span class="hljs-comment">// Example: only count "server-side" failures.</span>
        <span class="hljs-keyword">boolean</span> breakerRelevant = <span class="hljs-keyword">true</span>; <span class="hljs-comment">// placeholder for domain-specific checks</span>

        <span class="hljs-keyword">if</span> (!breakerRelevant) {
            <span class="hljs-keyword">return</span>;
        }

        <span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
            <span class="hljs-keyword">int</span> failures = failureCount.incrementAndGet();
            <span class="hljs-keyword">if</span> (state == State.CLOSED &amp;&amp; failures &gt;= failureThreshold) {
                transitionToOpen();
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (state == State.HALF_OPEN) {
                <span class="hljs-comment">// Any failure in HALF_OPEN sends us back to OPEN.</span>
                transitionToOpen();
            }
        }
    }
</code></pre>
<p>In this implementation, failure tracking is intentionally simple: we count <strong>consecutive</strong> failures. Each time a protected call throws an exception we classify as breaker‑relevant, <code>failureCount</code> is incremented. On a successful call, the counter resets.</p>
<p>I chose consecutive failures for clarity rather than sophistication. More advanced strategies, like sliding time windows or failure ratios, introduce extra state and timing complexity. When you’re learning how a breaker works, a simple counter makes the transition rules easy to reason about and easy to test.</p>
<p>Equally important, the breaker should not treat every exception the same. Domain validation errors, client misuse, and business rule violations shouldn’t affect the breaker’s state. Only infrastructure‑level problems (like timeouts, connection failures, or 5xx responses) should move the breaker toward OPEN. That separation keeps the breaker focused on dependency instability, not application bugs or bad inputs.</p>
<h3 id="heading-how-closed-state-transitions-to-open">How Closed State Transitions to Open</h3>
<p>When the breaker is in the CLOSED state, all requests flow through normally. In this phase the breaker is purely observational: it monitors outcomes and increments <code>failureCount</code> whenever a breaker‑relevant exception occurs.</p>
<p>Inside the <code>onFailure</code> method (shown in the above section), once the <code>failureCount</code> exceeds the configured threshold, the breaker transitions to OPEN. This transition must be atomic and serialized – otherwise, multiple threads could try to open the breaker at the same time, leading to inconsistent scheduling or duplicate recovery tasks.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transitionToOpen</span><span class="hljs-params">()</span> </span>{
        state = State.OPEN;
        <span class="hljs-comment">// Reset counters so the next CLOSED phase starts clean.</span>
        failureCount.set(<span class="hljs-number">0</span>);
        halfOpenTrials.set(<span class="hljs-number">0</span>);
        scheduleHalfOpen();
    }
</code></pre>
<p>Moving to OPEN immediately changes system behavior. From that point on, new requests are rejected without attempting the protected operation, which shields downstream services and preserves local resources such as threads and connection pools.</p>
<h3 id="heading-open-state-behavior-in-the-class">OPEN State Behavior in the Class</h3>
<p>The OPEN state represents pure fail‑fast behavior. While the breaker is open, no protected calls are executed. The <code>execute()</code> method immediately throws an exception indicating that the circuit is open.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> &lt;T&gt; <span class="hljs-function">T <span class="hljs-title">execute</span><span class="hljs-params">(Supplier&lt;T&gt; action)</span> </span>{
        <span class="hljs-comment">// 1. Guards the functionality based on its current state. </span>
        <span class="hljs-comment">//We are using synchronized block for thread safety. </span>
        <span class="hljs-comment">// Make sure another thread does not override our current state</span>
        State current;
        <span class="hljs-keyword">synchronized</span> (<span class="hljs-keyword">this</span>) {
            current = state;

            <span class="hljs-keyword">if</span> (current == State.OPEN) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalStateException(<span class="hljs-string">"Circuit breaker is OPEN. Call rejected."</span>);
            }
....
}
</code></pre>
<p>This behavior is not about improving latency – it is about resource protection. Letting calls continue and simply “wait for timeouts” would still tie up threads and connections. The value of the OPEN state is that it refuses to participate in propagating failure at all.</p>
<p>In this state, the breaker has a single responsibility: wait for the scheduled recovery attempt. It doesn’t check timestamps on each request or poll in the hot path. Its behavior is deterministic: reject immediately and let the scheduler decide when to try again.</p>
<h3 id="heading-schedulerdriven-recovery-entering-halfopen">Scheduler‑Driven Recovery: Entering HALF_OPEN</h3>
<p>When the breaker transitions to OPEN, it immediately schedules a delayed task using the injected ScheduledExecutorService. After the configured cooldown period elapses, that task transitions the breaker to HALF_OPEN.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Refer below methods from the main code </span>

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">transitionToOpen</span><span class="hljs-params">()</span> </span>{
        state = State.OPEN;
        <span class="hljs-comment">// Reset counters so the next CLOSED phase starts clean.</span>
        failureCount.set(<span class="hljs-number">0</span>);
        halfOpenTrials.set(<span class="hljs-number">0</span>);
        scheduleHalfOpen(); <span class="hljs-comment">// schedule a delayed task after changing the state to State.Open</span>
    }

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">scheduleHalfOpen</span><span class="hljs-params">()</span> </span>{
        scheduler.schedule(
                <span class="hljs-keyword">this</span>::transitionToHalfOpen,
                openCooldown.toMillis(),
                TimeUnit.MILLISECONDS
        );
    }
</code></pre>
<p>This design keeps time-based logic out of the request execution path. Rather than checking elapsed time on every call, the breaker delegates recovery timing to a dedicated scheduler thread. This reduces conditional logic under load and keeps the execute() method focused on guarding execution.</p>
<p>The scheduler must be reliable and isolated. A single-threaded executor is typically sufficient because transitions are rare and lightweight. More importantly, transitions should be idempotent so that unexpected rescheduling does not corrupt state.</p>
<h2 id="heading-spring-boot-scheduler-example">Spring Boot Scheduler Example</h2>
<p>In Spring Boot, you can wire a dedicated <code>ScheduledExecutorService</code> bean to drive state transitions instead of using plain Java threads.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CircuitBreakerConfig</span> </span>{

    <span class="hljs-comment">// First bean </span>
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function">ScheduledExecutorService <span class="hljs-title">circuitBreakerScheduler</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Executors.newSingleThreadScheduledExecutor();
    }

    <span class="hljs-comment">// Second bean </span>
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function">CircuitBreaker <span class="hljs-title">circuitBreaker</span><span class="hljs-params">(ScheduledExecutorService circuitBreakerScheduler)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> CircuitBreaker(
                circuitBreakerScheduler,
                <span class="hljs-number">5</span>,                     <span class="hljs-comment">// failureThreshold</span>
                <span class="hljs-number">2</span>,                     <span class="hljs-comment">// halfOpenTrialLimit</span>
                Duration.ofSeconds(<span class="hljs-number">30</span>) <span class="hljs-comment">// openCooldown</span>
        );
    }
}
</code></pre>
<p>The configuration class above wires the circuit breaker into the Spring container without introducing framework coupling into the breaker itself.</p>
<p>The first bean <code>circuitBreakerScheduler()</code> defines a dedicated <code>ScheduledExecutorService</code>. This executor is responsible exclusively for time-based state transitions. When the breaker moves to OPEN, it uses this scheduler to queue a delayed task that transitions the state to HALF_OPEN.</p>
<p>Using a single-threaded executor is intentional. Circuit breaker transitions are lightweight and infrequent, so parallel scheduling is unnecessary. A single thread guarantees serialized transition execution and avoids overlapping recovery attempts.</p>
<p>The second bean constructs the <code>CircuitBreaker</code> itself. Here we inject the scheduler and configure three things: a failure threshold of 5 consecutive errors, a half‑open trial limit of 2 test requests, and a 30‑second cooldown before we attempt recovery again. This configuration makes the breaker’s behavior explicit and easy to reason about – there are no hidden properties files or annotations, because everything that affects resilience is defined in one place.</p>
<p>At this point, the breaker is a fully managed Spring bean that you can inject into services and use programmatically.</p>
<h3 id="heading-how-this-connects-to-execution-flow">How This Connects to Execution Flow</h3>
<p>Once registered as a bean, the breaker becomes part of the application’s dependency graph. A typical service might inject it and wrap outbound calls:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExternalApiService</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> CircuitBreaker circuitBreaker;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> RestTemplate restTemplate;

    ExternalApiService(CircuitBreaker circuitBreaker, RestTemplate restTemplate) {
        <span class="hljs-keyword">this</span>.circuitBreaker = circuitBreaker;
        <span class="hljs-keyword">this</span>.restTemplate = restTemplate;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">callExternal</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> circuitBreaker.execute(() -&gt;
                restTemplate.getForObject(<span class="hljs-string">"http://external/api"</span>, String.class)
        );
    }
}
</code></pre>
<p>Every outbound call to the external system flows through the breaker’s <code>execute()</code> method, which enforces the current state rules before allowing the call to proceed. That makes resilience behavior explicit at the integration boundary: anyone reviewing the service can immediately see that the call is protected. There is no hidden interception layer and no AOP proxy quietly changing behavior at runtime.</p>
<h3 id="heading-scheduler-design-and-thread-safety">Scheduler Design and Thread Safety</h3>
<p>The scheduler’s only responsibility is delayed state transition. It doesn’t execute business logic and it doesn’t evaluate request outcomes. Its purpose is narrowly scoped: move the breaker from OPEN to HALF_OPEN after a cooldown.</p>
<p>Because the executor is single-threaded, scheduled tasks cannot overlap. But this doesn’t eliminate concurrency concerns entirely. Request threads may still attempt transitions at the same time the scheduler fires. For this reason, transition methods such as <code>transitionToHalfOpen()</code> and <code>transitionToOpen()</code> must remain serialized and idempotent.</p>
<p>In other words, even though the scheduler simplifies time-based recovery, it doesn’t replace the need for careful state management.</p>
<p>The architectural separation looks like this:</p>
<ul>
<li><p>Request threads → enforce execution rules and record outcomes</p>
</li>
<li><p>Scheduler thread → handle time-based recovery transitions</p>
</li>
</ul>
<p>Keeping these responsibilities separate reduces complexity in the hot path and improves predictability under load.</p>
<h3 id="heading-why-we-avoid-scheduled-for-this-design">Why We Avoid @Scheduled for This Design</h3>
<p>Spring provides @Scheduled as an alternative mechanism for time-based tasks. While convenient, it introduces global scheduling behavior and reduces isolation.</p>
<p>By using a dedicated <code>ScheduledExecutorService</code> for the breaker, we avoid interference with other scheduled jobs, keep lifecycle control explicit, and tie scheduling logic directly to breaker transitions.</p>
<p>This design reinforces the principle that resilience components should be isolated and predictable.</p>
<h3 id="heading-bringing-it-all-together">Bringing It All Together</h3>
<p>At this stage, the full interaction looks like this:</p>
<ol>
<li><p>A service wraps its dependency call with <code>circuitBreaker.execute()</code>.</p>
</li>
<li><p>If the breaker is CLOSED, the call proceeds and any relevant failures are counted.</p>
</li>
<li><p>When failures exceed the threshold, the breaker moves to OPEN and schedules a recovery attempt.</p>
</li>
<li><p>While OPEN, calls fail immediately without hitting the downstream system.</p>
</li>
<li><p>After the cooldown period, the scheduler transitions the breaker to HALF_OPEN.</p>
</li>
<li><p>A small number of trial calls then decide whether the breaker returns to CLOSED or goes back to OPEN.</p>
</li>
</ol>
<p>Nothing is hidden: every transition is visible in code, every configuration value is explicit, and each thread involved has a single responsibility. That clarity is what makes a custom implementation useful for learning – and safe when it is designed correctly.</p>
<h3 id="heading-observability-making-the-breaker-understandable">Observability: Making the Breaker Understandable</h3>
<p>A circuit breaker without observability is risky. At a minimum you should expose the current state, the failure count, the time of the last transition, and how long the breaker has been open.</p>
<p>On the metrics side, track how often the breaker opens, how many calls are rejected per second, and the success rate of recovery attempts.</p>
<p>Your logs should record state transitions at INFO level and failure classification decisions at DEBUG. With that level of visibility, your custom breaker is often easier to understand and tune than what many libraries provide out of the box..</p>
<h3 id="heading-handling-different-failure-types">Handling Different Failure Types</h3>
<p>Not all failures are equal.</p>
<ul>
<li><p>API Response Timeouts → breaker‑relevant</p>
</li>
<li><p>API 5xx responses → breaker‑relevant</p>
</li>
<li><p>API 4xx responses → usually not</p>
</li>
<li><p>Any data or business validation errors → never</p>
</li>
</ul>
<p>A custom breaker lets you apply this kind of <strong>business‑aware classification</strong>, which is often hard to express cleanly with generic libraries.</p>
<h2 id="heading-custom-breaker-vs-resilience4j">Custom Breaker vs Resilience4j</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><strong>Custom Breaker</strong></td><td><strong>Resilience4j</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Learning value</td><td>High</td><td>Low</td></tr>
<tr>
<td>Flexibility</td><td>High</td><td>Medium</td></tr>
<tr>
<td>Time to implement</td><td>Medium</td><td>Low</td></tr>
<tr>
<td>Operational maturity</td><td>Depends</td><td>High</td></tr>
<tr>
<td>Custom failure logic</td><td>Easy</td><td>Limited</td></tr>
<tr>
<td>Tooling / metrics</td><td>You wire metrics, logs, observability manually</td><td>Built-in metrics, logging, and integrations</td></tr>
</tbody>
</table>
</div><p>The choice is not binary. Many teams prototype with a custom breaker and later replace it with Resilience4j – now correctly configured.​</p>
<h2 id="heading-when-you-should-not-build-your-own">When You Should Not Build Your Own</h2>
<p>Do not build a custom breaker if:​</p>
<ul>
<li><p>You lack observability.</p>
</li>
<li><p>You do not understand concurrency.</p>
</li>
<li><p>You need advanced features immediately.</p>
</li>
<li><p>Your system is safety-critical.​</p>
</li>
</ul>
<p>For example, if you are building a <strong>payments platform</strong> with strict SLAs and cannot afford to battle-test a custom breaker, stick with a mature library like Resilience4j. The risk of subtle concurrency bugs, misclassified failures, or scheduler misconfigurations is too high to experiment in production.​</p>
<h2 id="heading-extending-the-design">Extending the Design</h2>
<p>Once you understand the core, you can add:​</p>
<ul>
<li><p>Sliding window metrics.</p>
</li>
<li><p>Adaptive thresholds.</p>
</li>
<li><p>Persistent breaker state.</p>
</li>
<li><p>Distributed breakers (per dependency).</p>
</li>
<li><p>Integration with feature flags.​</p>
</li>
</ul>
<p>These extensions are much easier when you control the internals.​</p>
<h2 id="heading-common-mistakes">Common Mistakes</h2>
<p>Common mistakes when working with circuit breakers include:​</p>
<ul>
<li><p>Opening the breaker on the first failure.</p>
</li>
<li><p>Blocking threads while OPEN.</p>
</li>
<li><p>Allowing unlimited HALF_OPEN requests.</p>
</li>
<li><p>Treating all exceptions equally.</p>
</li>
<li><p>Ignoring observability.​</p>
</li>
</ul>
<p>Most of these happen when using libraries without understanding them.​</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Resilience libraries are powerful, but they are not magic. A circuit breaker is fundamentally a state machine with failure tracking and time-based transitions. Building your own – even once – forces you to internalize this reality.​</p>
<p>In Spring Boot systems, a custom circuit breaker:​</p>
<ul>
<li><p>Clarifies failure semantics.</p>
</li>
<li><p>Improves debugging.</p>
</li>
<li><p>Enables domain-specific resilience.</p>
</li>
<li><p>Makes you a better user of Resilience4j.​</p>
</li>
</ul>
<p>You may never deploy your own breaker to production. But after building one, you will never configure a circuit breaker blindly again.​</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Brief Introduction to SQLite ]]>
                </title>
                <description>
                    <![CDATA[ SQLite is one of the most underappreciated tools in a developer's toolkit. It's a full-featured relational database that runs directly in your application. No server setup. No configuration files. No network protocols. Just a simple library that give... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-brief-introduction-to-sqlite/</link>
                <guid isPermaLink="false">68cd625e82b856dadd4cceba</guid>
                
                    <category>
                        <![CDATA[ SQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SQLite ]]>
                    </category>
                
                    <category>
                        <![CDATA[ C++ ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mark Mahoney ]]>
                </dc:creator>
                <pubDate>Fri, 19 Sep 2025 14:02:06 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1758290415152/439fa61c-9342-47cb-867a-0416fe6bd6cf.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://sqlite.org/">SQLite</a> is one of the most underappreciated tools in a developer's toolkit. It's a full-featured relational database that runs directly in your application. No server setup. No configuration files. No network protocols. Just a simple library that gives you the power of an ACID compliant RDBMS right where you need it.</p>
<p>SQLite powers more applications than you might think. It's in every smartphone, most web browsers, and countless desktop applications. Your phone probably has hundreds of SQLite databases on it right now. Despite handling billions of databases worldwide, many developers aren't familiar with all of the cool things that you can do with SQLite.</p>
<p>This tutorial introduces SQLite through practical examples in C/C++, Python, and Java. You can pick and choose the languages that suit your needs. No language wars here. You'll learn how to integrate SQLite into real applications. Whether you're building a desktop app, a web API, or just need local data storage without the drama of a full database server, SQLite has your back.</p>
<h2 id="heading-code-playbacks">Code Playbacks</h2>
<p>Code playbacks are a unique way to learn about programming. They are guided walkthroughs of code, allowing you to see not just the code itself but also the thought process behind it. This approach helps you understand not only what the code does, but why it was written that way. Here is a short video to show how to move through a code playback:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/uYbHqCNjVDM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>By registering on <a target="_blank" href="https://playbackpress.com/books">Playback Press</a>, you'll gain access to an AI assistant that can answer your questions about the code. This makes learning even more interactive and personalized. Watch this video to see how to work with it:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/WAPql5KZFR4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-a-brief-introduction-to-sqlite">A Brief Introduction to SQLite</h2>
<p>You can find my entire collection of SQLite code playbacks in my free book, <a target="_blank" href="https://playbackpress.com/books/sqlitebook">"Programming with SQLite"</a>.</p>
<p>Here's what you'll learn:</p>
<h3 id="heading-chapter-1-database-design-and-sql">Chapter 1: Database Design and SQL</h3>
<p>In this chapter, I cover the basics of relational database design and SQL. I keep it simple and practical. If you'd like more introductory SQL content like this go to my <a target="_blank" href="https://playbackpress.com/books/sqlbook">Intro SQL</a> book. If you'd like some SQL problems to work through, check out <a target="_blank" href="https://playbackpress.com/books/workedsqlbook">30 Worked SQL Examples</a>. If you already dream in <code>SELECT</code> statements, skip ahead to the chapter that best suits your needs.</p>
<ul>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/1/1">1.1 Database Design and Basic SQL</a></p>
</li>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/1/2">1.2 One-to-Many Relationships and More SQL</a></p>
</li>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/1/3">1.3 Many-to-Many Relationships and Even More SQL</a></p>
</li>
</ul>
<h3 id="heading-chapter-2-sqlite-in-cc">Chapter 2: SQLite in C/C++</h3>
<p>In this chapter, I discuss how to use the low level SQLite API from a C or C++ program. You have a lot of power when using the API and I cover ACID transactions. Yes, we're going to talk about pointers and memory management. Even if you're not a C/C++ programmer and haven't touched a pointer since college, I recommend looking at this chapter. Understanding what's happening under the hood will make the other chapters clearer. Plus, you can impress your friends at parties by casually mentioning you know how database transactions really work.</p>
<ul>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/2/1">2.1 Using the SQLite C/C++ API</a></p>
</li>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/2/2">2.2 An Object Oriented Auction Program</a></p>
</li>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/2/3">2.3 SQLite Transactions</a></p>
</li>
</ul>
<h3 id="heading-chapter-3-sqlite-in-python">Chapter 3: SQLite in Python</h3>
<p>Learn how to use SQLite in any Python program including Flask web apps. No ORMs hiding what's really happening. Just clean, direct database access. I cover how to query and create SQLite databases and then show how to build an API using <a target="_blank" href="https://flask.palletsprojects.com/en/stable/">Flask</a>. By the end, you'll have a working web API that didn't require installing PostgreSQL, configuring connection pools, or sacrificing a weekend to database administration.</p>
<ul>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/3/1">3.1 Using a SQLite Database in a Python Program</a></p>
</li>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/3/2">3.2 Creating SQLite Databases</a></p>
</li>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/3/3">3.3 Using SQLite in a Flask Web Application</a></p>
</li>
<li><p><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/3/4">3.4 Creating a Web API with Flask and SQLite</a></p>
</li>
</ul>
<h3 id="heading-chapter-4-sqlite-in-java">Chapter 4: SQLite in Java</h3>
<p>In this final chapter I give an example in Java using JDBC. Because sometimes you need to write enterprise code, and SQLite works there too. Who says you need Oracle for everything?</p>
<ul>
<li><a target="_blank" href="https://playbackpress.com/books/sqlitebook/chapter/4/1">4.1 Using a SQLite Database in a Java Program</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Ready to explore SQLite? Start with the first playback and see how fun database programming can be. Each example builds on the previous one, giving you practical experience with real code. Real code solving real problems.</p>
<p>I'd love to hear your thoughts! Feel free to share your comments, questions, or feedback via email: <a target="_blank" href="mailto:mark@playbackpress.com">mark@playbackpress.com</a>. Your input helps me improve and create even better content.</p>
<p>If you've found this tutorial helpful, consider supporting my work through <a target="_blank" href="https://github.com/sponsors/markm208">GitHub Sponsors</a>. Your contributions help cover hosting costs and keep Playback Press free for everyone. Thank you for helping me continue creating educational resources for the developer community!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What are Data Transfer Objects? Learn to Use DTOs in Your Java Spring-Based Projects ]]>
                </title>
                <description>
                    <![CDATA[ High performance and privacy are at the heart of most successful software systems. No one wants to use a software service that takes a ridiculous amount of time to load – and no company wants their users’ data exposed at the slightest vulnerability. ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-are-dtos-java/</link>
                <guid isPermaLink="false">68a4ba42388ce2383306b9b3</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ dto ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Augustine Alul ]]>
                </dc:creator>
                <pubDate>Tue, 19 Aug 2025 17:54:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1755626027353/feb7f6b6-4841-4559-a976-e73c708c7153.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>High performance and privacy are at the heart of most successful software systems. No one wants to use a software service that takes a ridiculous amount of time to load – and no company wants their users’ data exposed at the slightest vulnerability. This is why DTOs are a crucial topic for software engineers to understand.</p>
<p>Using DTOs is helpful when building applications that hold sensitive data like financial or health records. When used properly, DTOs can prevent sensitive fields from being exposed to the client side. In critical systems, they can further tighten security and reduce failure conditions by ensuring that only valid and required fields are accepted.</p>
<p>In this article, you’ll learn what DTOs are, why they’re important, and the best ways to create them for your Spring-based applications.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>This is a slightly more advanced tutorial. So to understand it better, you should have a sound knowledge of Java concepts like objects, getters and setters, and Spring/Spring Boot. You should also have a solid understanding of how software works in general.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-dto">What is a DTO?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-a-dto-for-a-spring-based-application">How to Create a DTO for a Spring-Based Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-dtos-from-two-or-multiple-objects">How to Create DTOs From Two or Multiple Objects</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-dto">What is a DTO?</h2>
<p>DTOs stand for Data Transfer Objects. It is a software design pattern that ensures the transfer of tailored/streamlined data objects between different layers of a software system. </p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfY0uhU1igdbtYzBocBZFOY37O2IjXOD5wCJ26DS0B3U6SZnIswn1n8kWi7ZKL5tQfSQjAZR7ecJ-5Aavop5iB3meJA5ywuKlv7fChG2Oq1_fxNtNW_8RijTFQx2d1ZG-A5y5uYag?key=3uLKQHZqj2e_zuUsBBBZwg" alt="Image showing the lifecycle of DTO in a software system" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Image <a target="_blank" href="https://www.linkedin.com/pulse/clean-spring-boot-apis-separating-entities-dtos-mappers-fabio-ribeiro-zrn9f?utm_source=share&amp;utm_medium=member_ios&amp;utm_campaign=share_via">source</a> | Fabio Ribeiro</p>
<p>The direction of data transfer with DTOs across the various layers of software is bi-directional. DTOs are either used to carry data in an inbound direction from an external client/user to the software or are constructed and used to carry data in an outbound direction from the software.</p>
<p>DTOs only hold field data, constructors, and necessary getter and setter methods. So they are Plain Old Java Objects (POJOs).</p>
<p>You can see the bi-directional flow in the image below:</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdHient8hAwmq3b3KhZi2tNuh0n_1ZuIFJxef1VnM_R5K4KoC0gjeZAF1vZ1d1_lliWKmltiNhhtlfCpadydurab8dNkfLQiru1wGcl2Egak-_3-IYI_n5adrbcrU-4ezKIVERU?key=3uLKQHZqj2e_zuUsBBBZwg" alt="Image showing the bi-directional flow of DTO in a software system, flowing from controller to Database and from Database back to the controller" width="600" height="400" loading="lazy"></p>
<p>Image <a target="_blank" href="https://www.linkedin.com/pulse/clean-spring-boot-apis-separating-entities-dtos-mappers-fabio-ribeiro-zrn9f?utm_source=share&amp;utm_medium=member_ios&amp;utm_campaign=share_via">source</a> | Fabio Ribeiro</p>
<h3 id="heading-why-use-dtos">Why Use DTOs?</h3>
<h4 id="heading-1-data-privacy">1. Data Privacy</h4>
<p>In Spring Boot, entities serve as the blueprint for creating data objects. These entities are classes annotated with <code>@Entity</code> and map to a database table. An instance of the entity class represents a database row or record, while a field in the entity class represents a database column. </p>
<p>When registering for a software service or product, the user might be asked to provide both sensitive and non-sensitive data for the proper functioning of the application. These data are held as fields by the entity class and finally mapped and persisted to the database. </p>
<p>When we need to retrieve data from the database and expose it through an API endpoint based on the query provided – say, a query to retrieve a user record or entity, Jackson (the serializer dependency commonly used in Spring-based applications) serialises all the data fields contained in the retrieved user entity. Now, imagine you have a User entity that contains fields like password, credit card details, date of birth, home address, and other sensitive data you wouldn’t want to reveal when the User entity is being serialised. Well, this is where DTOs come in. </p>
<p>With DTOs, you can retrieve the complete entity (containing both sensitive and insensitive data) from the database, create a custom class (say <code>UserDTO.java</code>) that only holds the insensitive fields that you feel are safe to expose, and finally, map the database-retrieved entity to the safe-to-expose UserDTO object. This way, the UserDTO is what gets serialised and exposed through the API endpoint and not the complete entity – keeping the sensitive data confidential.</p>
<h4 id="heading-2-improved-software-performance">2. Improved Software Performance</h4>
<p>DTOs can improve the performance of your software application by reducing the number of API calls for data retrieval. With DTOs, you can return serialized data from more than one entity in just one API call.</p>
<p>Let’s say that in your Spring Boot application, there are User and Follower entities, and you want to return user data as well as their followers. Typically, Jackson can only serialize one entity at a time, either User or Follower. But with a DTO, you can combine these two entities into one and eventually serialize and return all the data in a single request, instead of building two endpoints to return user and follower data.</p>
<p>In the next section, I’ll show you the various ways you can create DTOs for your Spring Boot project with code implementations.</p>
<h2 id="heading-how-to-create-a-dto-for-a-spring-based-application">How to Create a DTO for a Spring-Based Application</h2>
<p>There are two main approaches to creating DTOs in Spring/Spring Boot:</p>
<h3 id="heading-1-creating-custom-objects-and-handling-mapping-manually">1. Creating Custom Objects and Handling Mapping Manually</h3>
<p>This approach requires you to handle the mapping/transforming of your existing entity to the custom object (DTO) by yourself – that is to say, you write the code that creates the DTO and sets the DTO fields to the values present in the existing entity. This is common for developers who prefer fine-grained control, but it can be tedious for large-scale projects. </p>
<p>Follow the steps below to create a UserDTO from a User entity:</p>
<h4 id="heading-step-1-create-the-dto-class">Step 1: Create the DTO class</h4>
<p>Create a new file named <strong>UserDTO.java</strong> and write the code below into it:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserDTO</span> </span>{
    <span class="hljs-keyword">private</span> Long id;
    <span class="hljs-keyword">private</span> String firstName;
    <span class="hljs-keyword">private</span> String lastName;
    <span class="hljs-keyword">private</span> String email;


    <span class="hljs-comment">// No-args Constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserDTO</span><span class="hljs-params">()</span> </span>{}

    <span class="hljs-comment">// All-args constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserDTO</span><span class="hljs-params">(Long id, String firstName, String lastName, String email)</span> </span>{
        <span class="hljs-keyword">this</span>.id = id;
        <span class="hljs-keyword">this</span>.firstName = firstName;
        <span class="hljs-keyword">this</span>.lastName = lastName;
        <span class="hljs-keyword">this</span>.email = email;
    }


    <span class="hljs-comment">// Getters and Setters</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Long <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> id;
    }


    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(Long id)</span> </span>{
        <span class="hljs-keyword">this</span>.id = id;
    }


    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getFirstName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> firstName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setFirstName</span><span class="hljs-params">(String firstName)</span> </span>{
        <span class="hljs-keyword">this</span>.firstName = firstName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getLastName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> lastName;
    }


    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setLastName</span><span class="hljs-params">(String lastName)</span> </span>{
        <span class="hljs-keyword">this</span>.lastName = lastName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getEmail</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> email;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setEmail</span><span class="hljs-params">(String email)</span> </span>{
        <span class="hljs-keyword">this</span>.email = email;
    }

}
</code></pre>
<p>The defined UserDTO class can only hold four (4) fields: <code>id</code>, <code>firstName</code>, <code>lastName</code>, and <code>email</code>. It’s not capable of exposing or receiving more than this number of fields. The class also contains getter and setter methods for retrieving and assigning data to the fields.</p>
<h4 id="heading-step-2-create-mapper-methods-inside-a-utility-class">Step 2: Create Mapper Methods Inside a Utility Class</h4>
<p>Create a new file named <strong>UserMapper.java</strong> and put this piece of code into it:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserMapper</span> </span>{

    <span class="hljs-comment">// Convert Entity to DTO</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> UserDTO <span class="hljs-title">toDTO</span><span class="hljs-params">(UserEntity user)</span> </span>{

        <span class="hljs-keyword">if</span> (user == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;

        UserDTO dto = <span class="hljs-keyword">new</span> UserDTO();
        dto.setId(user.getId());
        dto.setFirstName(user.getFirstName());
        dto.setLastName(user.getLastName());
        dto.setEmail(user.getEmail());
        <span class="hljs-keyword">return</span> dto;
    }


    <span class="hljs-comment">// Convert DTO to Entity</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> UserEntity <span class="hljs-title">toEntity</span><span class="hljs-params">(UserDTO dto)</span> </span>{

        <span class="hljs-keyword">if</span> (dto == <span class="hljs-keyword">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
       UserEntity user = <span class="hljs-keyword">new</span> UserEntity(); 
        user.setFirstName(dto.getFirstName());
        user.setLastName(dto.getLastName());
        user.setEmail(dto.getEmail());

        <span class="hljs-keyword">return</span> user;
    }
</code></pre>
<p>The UserMapper class is a utility class that maps the UserEntity to a DTO and the DTO to an entity. This is where the bi-directional data transfer I talked about earlier comes into play. First, the UserEntity-DTO-direction involves retrieving the complete record from the database and transforming it into a streamlined object (void of unnecessary information) before it’s serialized and exposed to the client side through an API endpoint. </p>
<p>The DTO-UserEntity-direction involves taking the object from the client side as input into the system, but this time, to limit the client in terms of the number of data fields they can pass to the system. This object is received, mapped to an entity, and saved in the system. This is important when you don’t want the client to have access to certain critical fields (that would make your application vulnerable). That’s why software engineers always say, “Don’t trust the user”.</p>
<p>Let me give you a peek into what our UserEntity looks like:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> jakarta.persistence.*;

<span class="hljs-keyword">import</span> java.time.LocalDate;


<span class="hljs-meta">@Entity</span>

<span class="hljs-meta">@Table(name = "users")</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserEntity</span> </span>{


    <span class="hljs-meta">@Id</span>
    <span class="hljs-meta">@GeneratedValue(strategy = GenerationType.IDENTITY)</span>

    <span class="hljs-keyword">private</span> Long id;
    <span class="hljs-keyword">private</span> String firstName;
    <span class="hljs-keyword">private</span> String lastName;

    <span class="hljs-meta">@Column(unique = true)</span>
    <span class="hljs-keyword">private</span> String email;
    <span class="hljs-keyword">private</span> String password;
    <span class="hljs-keyword">private</span> String phoneNumber;
    <span class="hljs-keyword">private</span> String gender;
    <span class="hljs-keyword">private</span> LocalDate dateOfBirth;
    <span class="hljs-keyword">private</span> String address;
    <span class="hljs-keyword">private</span> String city;
    <span class="hljs-keyword">private</span> String state;
    <span class="hljs-keyword">private</span> String country;
    <span class="hljs-keyword">private</span> String profilePictureUrl;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> isVerified;
    <span class="hljs-keyword">private</span> LocalDate createdAt;
    <span class="hljs-keyword">private</span> LocalDate updatedAt;

    <span class="hljs-comment">// Constructors</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserEntity</span><span class="hljs-params">()</span> </span>{}

    <span class="hljs-comment">// Getters and Setters</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Long <span class="hljs-title">getId</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> id;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setId</span><span class="hljs-params">(Long id)</span> </span>{
        <span class="hljs-keyword">this</span>.id = id;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getFirstName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> firstName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setFirstName</span><span class="hljs-params">(String firstName)</span> </span>{
        <span class="hljs-keyword">this</span>.firstName = firstName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getLastName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> lastName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setLastName</span><span class="hljs-params">(String lastName)</span> </span>{
        <span class="hljs-keyword">this</span>.lastName = lastName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getEmail</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> email;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setEmail</span><span class="hljs-params">(String email)</span> </span>{
        <span class="hljs-keyword">this</span>.email = email;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getPassword</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> password;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setPassword</span><span class="hljs-params">(String password)</span> </span>{
        <span class="hljs-keyword">this</span>.password = password;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getPhoneNumber</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> phoneNumber;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setPhoneNumber</span><span class="hljs-params">(String phoneNumber)</span> </span>{
        <span class="hljs-keyword">this</span>.phoneNumber = phoneNumber;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getGender</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> gender;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setGender</span><span class="hljs-params">(String gender)</span> </span>{
        <span class="hljs-keyword">this</span>.gender = gender;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> LocalDate <span class="hljs-title">getDateOfBirth</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> dateOfBirth;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setDateOfBirth</span><span class="hljs-params">(LocalDate dateOfBirth)</span> </span>{
        <span class="hljs-keyword">this</span>.dateOfBirth = dateOfBirth;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getAddress</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> address;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAddress</span><span class="hljs-params">(String address)</span> </span>{
        <span class="hljs-keyword">this</span>.address = address;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getCity</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> city;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setCity</span><span class="hljs-params">(String city)</span> </span>{
        <span class="hljs-keyword">this</span>.city = city;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getState</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> state;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setState</span><span class="hljs-params">(String state)</span> </span>{
        <span class="hljs-keyword">this</span>.state = state;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getCountry</span><span class="hljs-params">()</span> </span>{
       <span class="hljs-keyword">return</span> country;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setCountry</span><span class="hljs-params">(String country)</span> </span>{
        <span class="hljs-keyword">this</span>.country = country;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getProfilePictureUrl</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> profilePictureUrl;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setProfilePictureUrl</span><span class="hljs-params">(String profilePictureUrl)</span> </span>{
        <span class="hljs-keyword">this</span>.profilePictureUrl = profilePictureUrl;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isVerified</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> isVerified;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setVerified</span><span class="hljs-params">(<span class="hljs-keyword">boolean</span> verified)</span> </span>{
        isVerified = verified;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> LocalDate <span class="hljs-title">getCreatedAt</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> createdAt;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setCreatedAt</span><span class="hljs-params">(LocalDate createdAt)</span> </span>{
        <span class="hljs-keyword">this</span>.createdAt = createdAt;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> LocalDate <span class="hljs-title">getUpdatedAt</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> updatedAt;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setUpdatedAt</span><span class="hljs-params">(LocalDate updatedAt)</span> </span>{
        <span class="hljs-keyword">this</span>.updatedAt = updatedAt;
    }

}
</code></pre>
<p>In the code snippet above, you can see that the UserDTO holds just four (4) fields, which are insensitive and safe to expose upon serialization. These fields are id, firstName, lastName, and email – unlike the UserEntity, which contains both the sensitive and insensitive fields. So, the not-safe-to-expose UserEntity maps to the safe-to-expose UserDTO. With that being done, the UserDTO object can be serialized and returned through an endpoint. You can now see why DTOs help us prevent exposing confidential information.</p>
<h3 id="heading-2-creating-custom-objects-and-handling-mapping-through-an-external-library">2. Creating Custom Objects and Handling Mapping Through an External Library</h3>
<p>Using an external library means adding a layer of abstraction to the mapping process. The library handles the stressful parts of the job for you, and it’s often a preferred choice for large-scale projects. In this article, we’re using <strong>MapStruct</strong> because it’s popular and easy to use. Maven will be our build tool. </p>
<h4 id="heading-step-1-add-the-dependency-to-your-project">Step 1: Add the dependency to your project</h4>
<p>Since you are using Maven as your build tool, open your pom.xml file and add this code:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- MapStruct API --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mapstruct<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mapstruct<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.5.5.Final<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
        <span class="hljs-comment">&lt;!-- Annotation processor plugin --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.apache.maven.plugins<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>maven-compiler-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>3.10.1<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">configuration</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">annotationProcessorPaths</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">path</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.mapstruct<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>mapstruct-processor<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.5.5.Final<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">annotationProcessorPaths</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">configuration</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>
</code></pre>
<p>This will help download the dependency during the project build. </p>
<h4 id="heading-step-2-define-your-dto">Step 2: Define your DTO</h4>
<p>Use the <code>UserDTO.java</code> file given in step 1 of the first approach.</p>
<h4 id="heading-step-3-create-the-mapstruct-mapper-interface">Step 3: Create the MapStruct Mapper Interface</h4>
<p>Create a file and name it UserMapper.java, and add the code below to it:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.mapstruct.Mapper;
<span class="hljs-keyword">import</span> org.mapstruct.factory.Mappers;

<span class="hljs-meta">@Mapper(componentModel = "spring")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserMapper</span> </span>{
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    <span class="hljs-function">UserDTO <span class="hljs-title">toDTO</span><span class="hljs-params">(UserEntity user)</span></span>;
    <span class="hljs-function">UserEntity <span class="hljs-title">toEntity</span><span class="hljs-params">(UserDTO userDTO)</span></span>;
}
</code></pre>
<p>The UserMapper interface contains the INSTANCE field and two methods, namely toDTO and toEntity, that take in objects of types UserEntity and UserDTO, respectively, as arguments. The implementations of these methods are abstracted and handled by the library for us. </p>
<p>You can now use the mapper methods (toDTO and toEntity) in your Service or Controller.</p>
<h2 id="heading-how-to-create-dtos-from-two-or-multiple-objects">How to Create DTOs From Two or Multiple Objects</h2>
<p>This is one of the most important ways to use DTOs: creating DTOs from more than one entity and combining them as one, so that they can be returned in one API call or request. </p>
<p>There are many ways you can apply this technique and create complex response DTOs, based on the requirements of your project. The form or structure of your API response object might not be the same as the example given in this tutorial – but the same principle applies, which is simply creating individual DTOs and combining them into one DTO, which eventually serves as the response DTO.  </p>
<p>The example below isn’t super complex, but it’s sufficient to help you understand how this works so you can leverage the technique in creating more complex  API response objects. This example will combine DTOs of a doctor and their appointments.</p>
<h4 id="heading-step-1-create-the-dto-classes">Step 1: Create the DTO Classes</h4>
<p>Create a file named <strong>DoctorDto.java</strong> and add this code to it:</p>
<pre><code class="lang-java">
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DoctorProfileDTO</span> </span>{
    <span class="hljs-keyword">private</span> String doctorId;
    <span class="hljs-keyword">private</span> String fullName;
    <span class="hljs-keyword">private</span> String email;
    <span class="hljs-keyword">private</span> String specialization;

   <span class="hljs-comment">// No-args constructor</span>
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">DoctorProfileDTO</span><span class="hljs-params">()</span></span>{
    }

    <span class="hljs-comment">// Getter and Setter for doctorId</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDoctorId</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> doctorId;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setDoctorId</span><span class="hljs-params">(String doctorId)</span> </span>{
        <span class="hljs-keyword">this</span>.doctorId = doctorId;
    }

    <span class="hljs-comment">// Getter and Setter for fullName</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getFullName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> fullName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setFullName</span><span class="hljs-params">(String fullName)</span> </span>{
        <span class="hljs-keyword">this</span>.fullName = fullName;
    }

    <span class="hljs-comment">// Getter and Setter for email</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getEmail</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> email;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setEmail</span><span class="hljs-params">(String email)</span> </span>{
        <span class="hljs-keyword">this</span>.email = email;
    }

    <span class="hljs-comment">// Getter and Setter for specialization</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getSpecialization</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> specialization;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSpecialization</span><span class="hljs-params">(String specialization)</span> </span>{
        <span class="hljs-keyword">this</span>.specialization = specialization;
    }
}
</code></pre>
<p>Create another one called <strong>AppointmentDto.java</strong> and include this code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppointmentDTO</span> </span>{
    <span class="hljs-keyword">private</span> String appointmentId;
    <span class="hljs-keyword">private</span> String appointmentDate;
    <span class="hljs-keyword">private</span> String status;
    <span class="hljs-keyword">private</span> String patientName;
    <span class="hljs-keyword">private</span> String patientEmail;

   <span class="hljs-comment">// No-args constructor</span>
   <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AppointmentDTO</span><span class="hljs-params">()</span></span>{
    }

    <span class="hljs-comment">// Getter and Setter for appointmentId</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getAppointmentId</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> appointmentId;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAppointmentId</span><span class="hljs-params">(String appointmentId)</span> </span>{
        <span class="hljs-keyword">this</span>.appointmentId = appointmentId;
    }

    <span class="hljs-comment">// Getter and Setter for appointmentDate</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getAppointmentDate</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> appointmentDate;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAppointmentDate</span><span class="hljs-params">(String appointmentDate)</span> </span>{
        <span class="hljs-keyword">this</span>.appointmentDate = appointmentDate;
    }

    <span class="hljs-comment">// Getter and Setter for status</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getStatus</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> status;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setStatus</span><span class="hljs-params">(String status)</span> </span>{
        <span class="hljs-keyword">this</span>.status = status;
    }

    <span class="hljs-comment">// Getter and Setter for patientName</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getPatientName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> patientName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setPatientName</span><span class="hljs-params">(String patientName)</span> </span>{
        <span class="hljs-keyword">this</span>.patientName = patientName;
    }

    <span class="hljs-comment">// Getter and Setter for patientEmail</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getPatientEmail</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> patientEmail;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setPatientEmail</span><span class="hljs-params">(String patientEmail)</span> </span>{
        <span class="hljs-keyword">this</span>.patientEmail = patientEmail;
    }
}
</code></pre>
<h4 id="heading-step-2-create-a-composite-dto-combining-both-entities">Step 2: Create a Composite DTO Combining both Entities</h4>
<p>Create a file named <strong>DoctorWithAppointmentsDTO.java</strong>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DoctorWithAppointmentsDTO</span> </span>{
    <span class="hljs-keyword">private</span> DoctorProfileDTO doctorProfile;
    <span class="hljs-keyword">private</span> List&lt;AppointmentDTO&gt; appointments;

    <span class="hljs-comment">// No-args constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">DoctorWithAppointmentsDTO</span><span class="hljs-params">()</span> </span>{
    }

    <span class="hljs-comment">// Getter and Setter for doctorProfile</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> DoctorProfileDTO <span class="hljs-title">getDoctorProfile</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> doctorProfile;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setDoctorProfile</span><span class="hljs-params">(DoctorProfileDTO doctorProfile)</span> </span>{
        <span class="hljs-keyword">this</span>.doctorProfile = doctorProfile;
    }

    <span class="hljs-comment">// Getter and Setter for appointments</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;AppointmentDTO&gt; <span class="hljs-title">getAppointments</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> appointments;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAppointments</span><span class="hljs-params">(List&lt;AppointmentDTO&gt; appointments)</span> </span>{
        <span class="hljs-keyword">this</span>.appointments = appointments;
    }
}
</code></pre>
<h4 id="heading-step-3-create-a-mapper-class">Step 3: Create a Mapper Class</h4>
<p>Create a mapper class <strong>DoctorMapper.java</strong> containing the logic to map to the <strong>DoctorWithAppointmentsDTO</strong> class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MapperClass</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> DoctorWithAppointmentsDTO <span class="hljs-title">toDTO</span><span class="hljs-params">(Doctor doctor, List&lt;Appointment&gt; appointments)</span> </span>{

        DoctorProfileDTO doctorProfile = <span class="hljs-keyword">new</span> DoctorProfileDTO();
        doctorProfile.setDoctorId(doctor.getId());
        doctorProfile.setFullName(doctor.getFullName());
        doctorProfile.setEmail(doctor.getEmail());
        doctorProfile.setSpecialization(doctor.getSpecialization());

        List&lt;AppointmentDTO&gt; appointmentDTOs = appointments.stream().map(appt -&gt; {
            AppointmentDTO dto = <span class="hljs-keyword">new</span> AppointmentDTO();
            dto.setAppointmentId(appt.getId());
            dto.setAppointmentDate(appt.getDate().toString()); 
            dto.setStatus(appt.getStatus().name());
            dto.setPatientName(appt.getPatient().getName());
            dto.setPatientEmail(appt.getPatient().getEmail());
            <span class="hljs-keyword">return</span> dto;
        }).toList();

        DoctorWithAppointmentsDTO doctorWithAppointment = <span class="hljs-keyword">new</span> DoctorWithAppointmentsDTO();
        doctorWithAppointment.setDoctorProfile(doctorProfile);
        doctorWithAppointment.setAppointments(appointmentDTOs);

        <span class="hljs-keyword">return</span> doctorWithAppointment;
    }
}
</code></pre>
<p>From the example above, you can see that two separate DTOs (AppointmentDTO and DoctorProfileDTO) were created before the composite DTO, DoctorWithAppointmentsDTO was created. The composite DTO class (DoctorWithAppointmentsDTO) contains fields that hold the instances of the Appointment and DoctorProfile DTOs. The mapper class takes in the Doctor and a list of Appointment entities as arguments, maps them to DoctorProfileDTO and AppointmentDTO, respectively. Finally, the fields for the composite DTO class are set using the DTO objects mapped from the entities.</p>
<p>The <strong>DoctorWithAppointmentsDTO,</strong> when serialised and returned through an endpoint, should give you an output like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"doctorProfile"</span>: {
    <span class="hljs-attr">"doctorId"</span>: <span class="hljs-string">"abc123"</span>,
    <span class="hljs-attr">"fullName"</span>: <span class="hljs-string">"Dr. Susan Emeka"</span>,
    <span class="hljs-attr">"email"</span>: <span class="hljs-string">"suzan.emeka@example.com"</span>,
    <span class="hljs-attr">"specialisation"</span>: <span class="hljs-string">"Cardiology"</span>
  },
  <span class="hljs-attr">"appointments"</span>: [
    {
      <span class="hljs-attr">"appointmentId"</span>: <span class="hljs-string">"appt001"</span>,
      <span class="hljs-attr">"appointmentDate"</span>: <span class="hljs-string">"2025-07-10T09:00:00"</span>,
      <span class="hljs-attr">"status"</span>: <span class="hljs-string">"CONFIRMED"</span>,
      <span class="hljs-attr">"patientName"</span>: <span class="hljs-string">"James Agaji"</span>,
      <span class="hljs-attr">"patientEmail"</span>: <span class="hljs-string">"james.agaji@example.com"</span>
    },
 {
      <span class="hljs-attr">"appointmentId"</span>: <span class="hljs-string">"appt002"</span>,
      <span class="hljs-attr">"appointmentDate"</span>: <span class="hljs-string">"2025-08-12T07:05:08"</span>,
      <span class="hljs-attr">"status"</span>: <span class="hljs-string">"CONFIRMED"</span>,
      <span class="hljs-attr">"patientName"</span>: <span class="hljs-string">"Jane Augustine"</span>,
      <span class="hljs-attr">"patientEmail"</span>: <span class="hljs-string">"jane.augustine@example.com"</span>
    }
  ]
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you’re a software engineer who’s concerned with privacy and efficiency, using DTOs in your applications is a must.</p>
<p>In this article, you’ve learned what DTOs are as well as the main approaches for creating and using them. Take the time to go through the code snippets given in this article and practice with them until you’re comfortable implementing them yourself. Thanks for reading.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Object-Oriented Design Patterns with Java ]]>
                </title>
                <description>
                    <![CDATA[ In this article I will introduce some of the most useful object-oriented design patterns. Design patterns are solutions to common problems that show up over and over again. These problems will show up in many different contexts but always have the sa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/object-oriented-design-patterns-with-java/</link>
                <guid isPermaLink="false">6887df408810970f0e04fae6</guid>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mark Mahoney ]]>
                </dc:creator>
                <pubDate>Mon, 28 Jul 2025 20:36:16 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753734965769/4d53f28e-7d85-4571-831f-1760490e06dc.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article I will introduce some of the most useful object-oriented <a target="_blank" href="https://www.freecodecamp.org/news/javascript-design-patterns-explained/">design patterns</a>. Design patterns are solutions to common problems that show up over and over again. These problems will show up in many different contexts but always have the same problem at the root.</p>
<p>A design pattern attempts to describe an effective solution to the problem in a generic way so that it can be applied to a specific set of circumstances.</p>
<p>I will use Java to build an example of each pattern. I’m assuming that you have some programming experience in Java. In particular, you should be (at least somewhat) familiar with the concepts of inheritance and polymorphism. These design patterns really show the power of inheritance and polymorphism, so if you are just learning about these topics this is a great opportunity to dig deeper.</p>
<p>What if you not a Java programmer? If you are familiar with any Object-Oriented language you will probably still get a lot out of the examples. Give it a shot!</p>
<h2 id="heading-code-playbacks"><strong>Code Playbacks</strong></h2>
<p>To make design patterns more approachable, I developed an interactive tutorial that uses annotated <a target="_blank" href="https://markm208.github.io/"><strong>code playbacks</strong></a> to walk through key design pattern features step-by-step.</p>
<p>Each design pattern is presented as a code playback that shows how a program changes over time along with my explanation about what's happening. This format helps you focus on the reasoning behind the code changes.</p>
<p>You can access the free 'book' of code playbacks here:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook">OO Design Patterns with Java</a>, by Mark Mahoney (that’s me)</p>
</blockquote>
<p>To view a code playback, click on the comments in the left panel. Each comment updates the code in the editor and highlights any changes. Read the explanation and study the code. If you get stuck, use the AI assistant like a tutor to help explain what is happening in the code.</p>
<p>For more information about code playbacks, you can watch a short demo here.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/uYbHqCNjVDM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-key-design-patterns-you-should-know">Key Design Patterns You Should Know</h2>
<h3 id="heading-strategy-pattern"><strong>Strategy Pattern</strong></h3>
<p>The <a target="_blank" href="https://www.freecodecamp.org/news/a-beginners-guide-to-the-strategy-design-pattern/"><strong>Strategy Pattern</strong></a> is used to define a 'family' of algorithms, encapsulate each one, and make them interchangeable. Software developers use the Strategy pattern when they know there are many different ways of accomplishing some behavior. Rather than include all the different ways in a single class, they separate them out into individual classes and plug them in when necessary.</p>
<p>This program creates some classes to hold student grades. Some instructors like to adjust the entire course’s grades to make them higher. Some instructors do this by dropping every student's lowest grade. Other instructors 'curve' each assignment. Since there are several different options, I will use the <strong>Strategy Pattern</strong> to isolate them and let the client choose which one they prefer.</p>
<p>Start by looking at the <code>Assignment</code>, <code>Student</code>, and <code>Course</code> classes. Once you are familiar with the core classes, watch as I change the code to implement two different approaches to <em>curving</em> the grades using the <strong>Strategy Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/1"><strong>Strategy Pattern</strong> Adjusting Grades in a Course</a></p>
</blockquote>
<h3 id="heading-singleton-pattern"><strong>Singleton Pattern</strong></h3>
<p>There are times when you need to make sure there is only one instance of a class and it is accessible everywhere in your code. This is the problem that the <a target="_blank" href="https://en.wikipedia.org/wiki/Singleton_pattern"><strong>Singleton Pattern</strong></a> solves.</p>
<p>In this program, I will create a class that generates random numbers. I will rely on Java's built-in <code>Random</code> class but will be able to reproduce the exact same sequence of random numbers when in 'test mode'. I'll make sure that there is only one instance of this random number generator using the <strong>Singleton Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/2"><strong>Singleton Pattern</strong> A Testable Random Number Class</a></p>
</blockquote>
<h3 id="heading-composite-pattern"><strong>Composite Pattern</strong></h3>
<p>Often, we’ll create whole/part containment tree structures. For example, in a file system there are simple files. I call these simple elements, <em>primitives</em>. We can group primitives together to form larger <em>composites</em>. Files can be grouped into directories. These composites (directories) can be grouped into still larger composites, and so on.</p>
<p>We could treat composites and primitives differently. But it often makes sense to treat them the same. Having to distinguish between the object types makes the application more complex.</p>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Composite_pattern"><strong>Composite Pattern</strong></a> describes how to use recursive composition so that clients don't need to make this distinction.</p>
<p>This program creates classes for printing a hierarchical collection of files and directories using the <strong>Composite Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/3"><strong>Composite Pattern</strong> Displaying a Hierarchical File System</a></p>
</blockquote>
<h3 id="heading-decorator-pattern"><strong>Decorator Pattern</strong></h3>
<p>Sometimes we want to add responsibilities to individual objects, not an entire class. The <a target="_blank" href="https://en.wikipedia.org/wiki/Decorator_pattern"><strong>Decorator Pattern</strong></a> allows us to create <em>decorators</em> to provide a flexible alternative to inheritance for extending a class.</p>
<p>In this program, I create an interface for logging messages while a program is running. I use the interface to create a <code>ConsoleLogger</code> that prints the log messages to the screen. Then I start to add decorator objects that surround, or wrap, the <code>ConsoleLogger</code>. I add decorators to attach the date, author name, and time to the log messages using the <strong>Decorator Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/4"><strong>Decorator Pattern</strong> Logging with Decorators</a></p>
</blockquote>
<h3 id="heading-state-pattern"><strong>State Pattern</strong></h3>
<p>Sometimes there are systems that react differently based on the 'state' that they are in. A state is a period of time during which a system will react to events according to certain rules. This state-based behavior is implemented using the <a target="_blank" href="https://en.wikipedia.org/wiki/State_pattern"><strong>State Pattern</strong></a>.</p>
<p>I’ll show you how to move through the characters in a string and parse it to account for quotes within it. For example, the following string:</p>
<p><code>"hamburgers chips 'hot dogs' pickles 'french fries'"</code></p>
<p>can be split into a collection like this:</p>
<p><code>["hamburgers", "chips", "hot dogs", "pickles", "french fries"]</code></p>
<p>There are may ways to accomplish this in Java, but I’ll show a state-based approach. When a single quote is encountered within a string I will use that as an event and move between different states using the <strong>State Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/5"><strong>State Pattern</strong> String Splitting for Search Bars</a></p>
</blockquote>
<h3 id="heading-observer-pattern"><strong>Observer Pattern</strong></h3>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Observer_pattern"><strong>Observer Pattern</strong></a> is used when the update of a single piece of data in one object needs to be propagated to a collection of other objects.</p>
<p>For example, when the value of a cell in a spreadsheet changes, several other cells may need to be notified of that change so that they can update themselves. Similarly, in a social network application when a user makes a post, all of their friends need to be notified so that their feeds can be updated. Both of these are essentially the same problem that the <strong>Observer Pattern</strong> solves.</p>
<p>This program creates a class to hold a time in a day called <code>MyTime</code>. Then I create two different types of <code>Observers</code> that will be notified when the time changes. The two observers will re-display the time every time it changes using the <strong>Observer Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/6"><strong>Observer Pattern</strong> Observing the Time Change</a></p>
</blockquote>
<h3 id="heading-proxy-pattern"><strong>Proxy Pattern</strong></h3>
<p>Sometimes we design a set of objects that have a client/server relationship but later decide that the two objects should not interact directly. This program shows how to use the <a target="_blank" href="https://en.wikipedia.org/wiki/Proxy_pattern"><strong>Proxy Pattern</strong></a> to place some new functionality in between two previously cooperating classes.</p>
<p>I create a <code>Card</code> and <code>Deck</code> class for card games. The <code>Deck</code> starts out being hosted on the same machine as the <code>Driver</code>. Then I split the <code>Driver</code> and the <code>Deck</code> class so that they can be run on different machines using the <strong>Proxy Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/7"><strong>Proxy Pattern</strong> Dealing Cards from a Remote Deck</a></p>
</blockquote>
<h3 id="heading-factory-pattern"><strong>Factory Pattern</strong></h3>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Factory_method_pattern"><strong>Factory Pattern</strong></a> provides a mechanism for creating 'families' of related objects without specifying their concrete classes. Instantiating concrete objects in an application makes it hard to change those objects later.</p>
<p>In this program, I will create two different families of classes for a help system for two different computing platforms using the <strong>Factory Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/8"><strong>Factory Pattern</strong> Getting Help in Mac and Windows</a></p>
</blockquote>
<h3 id="heading-visitor-pattern"><strong>Visitor Pattern</strong></h3>
<p>The <a target="_blank" href="https://en.wikipedia.org/wiki/Visitor_pattern"><strong>Visitor Pattern</strong></a> lets you add functionality to a hierarchy of classes without changing its interface.</p>
<p>The reason why this is important is that there are times when we cannot change an existing hierarchy of classes. Perhaps I am using a hierarchy of classes that I am not in control of but I want to add some new functionality to it anyway. This is where the <strong>Visitor Pattern</strong> comes in.</p>
<p>In this program, I’ll add functionality to the <code>File</code> and <code>Directory</code> classes from the <em>Composite</em> program that I wrote earlier with minimal changes to those classes.</p>
<p>I create a <em>visitor</em> to count the number of files and directories in a topmost directory. Then I write a <em>visitor</em> to collect only the filenames in a directory including its sub-directories using the <strong>Visitor Pattern</strong>:</p>
<blockquote>
<p><a target="_blank" href="https://playbackpress.com/books/patternsbook/chapter/1/9"><strong>Visitor Pattern</strong> Adding Functionality to a Hierarchy of Classes (File and Directory)</a></p>
</blockquote>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>I hope you enjoyed learning about object-oriented design patterns. If you are interested in other programming paradigms, you can check out some of my other 'books' <a target="_blank" href="https://playbackpress.com/books">here</a>.</p>
<p>Questions and feedback are always welcome here: <a target="_blank" href="mailto:mark@playbackpress.com">mark@playbackpress.com</a></p>
<p>If you'd like to support my work and help keep Playback Press free for all, consider donating using <a target="_blank" href="https://github.com/sponsors/markm208">GitHub Sponsors</a>. I use all of the donations for hosting costs. Your support helps me continue creating educational content like this. Thank you!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Spring vs Spring Boot: How to Choose the Right Java Framework ]]>
                </title>
                <description>
                    <![CDATA[ The Java programming language is a favourite among solo devs and large teams alike. It’s popular for many reasons and use cases, including its mature ecosystem, stable support, efficiency, and reliability. If you’re learning Java with the end goal of... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/spring-vs-spring-boot-choosing-a-java-framework/</link>
                <guid isPermaLink="false">687ecc61edf675fee8ff0271</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Spring ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Augustine Alul ]]>
                </dc:creator>
                <pubDate>Mon, 21 Jul 2025 23:25:21 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753140286088/7294bd87-8940-450f-aa05-cef68a1c2604.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>The Java programming language is a favourite among solo devs and large teams alike. It’s popular for many reasons and use cases, including its mature ecosystem, stable support, efficiency, and reliability.</p>
<p>If you’re learning Java with the end goal of building applications, you’ll need to be able to choose a suitable Java framework (a collection of necessary pre-built tools and libraries) to make development easier once you know the fundamentals. </p>
<p>There are many Java frameworks out there that help you complete different tasks, such as Jakarta EE (formerly Java EE, an enterprise-level framework, used for large-scale applications), JSF (or JavaServer Faces, a UI framework for developing Java web interfaces), Spring, Spring Boot, and others. </p>
<p>You may have heard of Spring and Spring Boot by now, as they are very popular and commonly used by Java devs. In this article, you will learn:</p>
<ul>
<li><p>What the Spring and Spring Boot frameworks are.</p>
</li>
<li><p>Their real-world use cases and how to get started building with them.</p>
</li>
<li><p>The key differences between Spring and Spring Boot.</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To fully understand the content of this article, you should have a good working knowledge of the Java programming language, be familiar with the concept of APIs (<strong>Application Programming Interfaces</strong>), and know how to use Java project build tools – especially Maven, as it’s the build tool we’ll use for this article’s code examples.</p>
<h3 id="heading-table-of-contents">Table of Contents</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-the-spring-framework">What is the Spring Framework?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-spring-boot-framework">What is the Spring Boot Framework?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-core-differences-between-spring-and-spring-boot">Core Differences Between Spring and Spring Boot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-example">Real World Example</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-choose-between-spring-and-spring-boot">How to Choose Between Spring and Spring Boot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-the-spring-framework">What is the Spring Framework?</h2>
<p>Spring is a framework used for building modern enterprise-grade applications. It’s primarily used for Java, but it’s also compatible with the Kotlin and Groovy programming languages, too. This means that you can use Kotlin and Groovy to develop applications in Spring.</p>
<p>Spring provides a clear paradigm you can follow for building and configuring applications for easy deployment on any platform you choose.</p>
<p>At the core of the Spring framework is its robust infrastructure support. It internally handles implementing key components that are required for the safety and overall functionality of enterprise applications. It does this using modules such as:</p>
<ul>
<li><p>Spring JDBC</p>
</li>
<li><p>Spring MVC</p>
</li>
<li><p>Spring Security</p>
</li>
<li><p>Spring AOP</p>
</li>
<li><p>Spring ORM and </p>
</li>
<li><p>Spring Test</p>
</li>
</ul>
<p>These let developers focus on the business logic of the application instead of worrying about implementing or writing the code for the components/modules from scratch. This saves significant development time.</p>
<h3 id="heading-why-use-spring">Why use Spring?</h3>
<p>Spring does a lot of heavy lifting in terms of reducing excessive infrastructure code through its modules compared to legacy Java frameworks. This is one of the reasons it’s so popular.</p>
<p>For instance, when it comes to handling dependencies in Spring, you just have to define the dependency using the <code>@Bean</code> annotation in a configuration class, replacing the older approach of adding the dependency in an XML file.</p>
<p>Spring then adds the bean to an IoC (Inversion of Control) container, and makes the bean available to be utilised during runtime, also handling the lifecycle and wiring automatically.</p>
<p>Here is a simple code illustration of the configuration class below:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppConfig</span></span>{

<span class="hljs-meta">@Bean</span>

<span class="hljs-function"><span class="hljs-keyword">public</span> DataSource <span class="hljs-title">dataSource</span><span class="hljs-params">()</span> </span>{

    DriverManagerDataSource ds = <span class="hljs-keyword">new</span> DriverManagerDataSource();

    ds.setUrl(<span class="hljs-string">"jdbc:mysql://localhost:3306/mydb"</span>);

    ds.setUsername(<span class="hljs-string">"user"</span>);

    ds.setPassword(<span class="hljs-string">"pass"</span>);

    <span class="hljs-keyword">return</span> ds;

  }


}
</code></pre>
<p>Here’s the class where the resource/dependency is utilised:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Component</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserRepository</span> </span>{

<span class="hljs-keyword">private</span> DataSource dataSource;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserRepository</span><span class="hljs-params">(DataSource dataSource)</span></span>{

      <span class="hljs-keyword">this</span>.dataSource = dataSource;

}

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">connectToDb</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> SQLException </span>{

        Connection conn = dataSource.getConnection();

        System.out.println(<span class="hljs-string">"Connected to DB via Spring!"</span>);

        conn.close();

    }

}
</code></pre>
<p>These code snippets demonstrate how dependency injection is implemented using Spring’s <code>@Bean</code> and <code>@Component</code> annotations. In the code is a configuration class and a second class where the <code>DataSource</code> is injected and used. This shows a simplistic approach to dependency management in Spring.</p>
<h3 id="heading-key-components-of-the-spring-framework">Key Components of the Spring Framework</h3>
<p>Spring is made up of several components, each serving distinct roles (as shown in the image below):</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdVmXBnm1fS-t0pN7w-zAglYvKrx37zoEZ4HdeszACcU8Ig4PFs_mKlfU49SALDAtrWUE1bj8bZ6lnvDoc4SoM_VxH5Nerime9uuNlIc5S6picvT3ho6Jv8dEmFTv7zrOKFNVDMxg?key=Zq-Isk9ZAG_nIZ1YfHDMRfMs" alt="Image containing the Spring Framework Runtime Components" width="581" height="448" loading="lazy"></p>
<p>Image <a target="_blank" href="https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/overview.html">source</a> | Overview of the Spring Framework</p>
<p>These components collectively provide useful functionalities that make Spring a robust framework. Think of them as parts that make up a whole. Let me briefly explain each of the components and their various roles for easy understanding.</p>
<h4 id="heading-data-accessintegration">Data Access/Integration:</h4>
<p>This component enables easy interaction with databases and other data sources. It contains several modules (JDBC, ORM, OXM, JMS and Transaction Management), each performing unique functions.</p>
<p>These modules provide fine-grained abstraction for tasks like executing SQL queries, integrating with ORM frameworks (for example, Hibernate), handling XML data binding, messaging, and managing transactions, while working in a Spring-based application<strong>.</strong> </p>
<h4 id="heading-web">Web:</h4>
<p>The Web component makes interaction between the client side (through HTTP request) and the core business logic possible in a Spring application. It consists of four modules (Web, Web-Servlet, Web-Struts, and Web-Portlet), each serving a specific function:</p>
<ul>
<li><p>The <strong>Web</strong> module enables multipart file upload functionality and initialization of the IoC container.</p>
</li>
<li><p><strong>Web-Servlet</strong> module provides an MVC (Model View Controller) Implementation for web applications.</p>
</li>
<li><p>The <strong>Web-Struts</strong> module integrates Struts into Spring by using support classes.</p>
</li>
<li><p>The <strong>Web-Portlet</strong> module supports MVC implementation for use in a portlet environment.</p>
</li>
</ul>
<h4 id="heading-aop-and-instrumentation">AOP and Instrumentation:</h4>
<p>AOP provides the implementation that makes it possible to ensure the separation of “cross-cutting concerns” in your application from the business logic, leading to cleaner and more organized code that’s free from clutter and repetition.</p>
<p>Instead of writing these <strong>concerns</strong> everywhere in your classes, you just define them in <strong>aspects</strong> and they are injected for you by Spring when the program needs them. These <strong>concerns</strong> could be logging, security, or transactions.</p>
<h4 id="heading-instrumentation">Instrumentation:</h4>
<p>This enables class instrumentation support, which ensures class bytecode modification.</p>
<h4 id="heading-core-container">Core Container:</h4>
<p>Core Container as the name implies, is a crucial part of Spring. It is responsible for some of the unique features that make the Spring Framework desired and popular: IoC (Inversion of Control) and dependency injection.</p>
<p>Core Container is made of Beans, Core, Context and Expression Language modules. These modules all have unique, yet complementary properties.</p>
<h4 id="heading-test">Test:</h4>
<p>The Test component provides a suitable approach to testing Spring applications, and it integrates smoothly with JUnit or TestNG. It goes as far as providing mock objects that can be used to test different components of your application in either an isolated or Spring-managed environment, helping you achieve a robust and reliable software application.</p>
<h2 id="heading-what-is-the-spring-boot-framework">What is the Spring Boot Framework?</h2>
<p>Spring Boot is an open-source framework built on top of Spring for developing robust stand-alone applications that you can “easily run”. The major purpose for which Spring Boot was created was to further simplify the process of configuring and running Spring applications. </p>
<p>Spring Boot enforces an opinionated approach to development and provides extra useful features not contained in Spring. Let’s learn a bit more about how it works.</p>
<h3 id="heading-key-features-of-the-spring-boot-framework">Key Features of the Spring Boot Framework</h3>
<p>Spring Boot, being part of the Spring ecosystem, inherits most Spring functionalities, but contains additional features not included in Spring. Let me explain these unique features briefly: </p>
<h4 id="heading-auto-configuration">Auto-configuration</h4>
<p>Spring Boot automatically configures dependencies present in the classpath (location where the Java runtime looks for classes/resources during compilation) through the <code>@SpringBootApplication</code> annotation. This is a combination of <code>@EnableAutoConfiguration</code>, <code>@Configuration</code>, and <code>@ComponentScan</code>. This auto-configuration saves effort in writing boilerplate code for configuring dependencies/beans (as you have to do with Spring). </p>
<p>Here’s how you can use the <code>@SpringBootApplication</code> annotation for auto-configuration in Spring Boot applications:</p>
<pre><code class="lang-java">      <span class="hljs-meta">@SpringBootApplication</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

        SpringApplication.run(MyApp.class, args);

    }

}
</code></pre>
<h4 id="heading-starter-dependencies">Starter dependencies</h4>
<p>Starter dependencies provide a cleaner and less verbose way of managing dependencies in Spring Boot. Essentially, it bundles a set of complementary dependencies that perform a common task into one, meaning you don’t need to manually declare every single dependency that is part of the starter bundle.</p>
<p>Starter dependencies in Spring Boot follow the naming convention spring-boot-starter-*, where the asterisk represents the name of the particular dependency.</p>
<p>Some common starter dependencies in Spring Boot are: </p>
<ul>
<li><p>spring-boot-starter-web</p>
</li>
<li><p>spring-boot-starter-aop</p>
</li>
<li><p>spring-boot-starter-data-jdbc</p>
</li>
<li><p>spring-boot-starter-data-jpa</p>
</li>
<li><p>spring-boot-starter-data-rest</p>
</li>
</ul>
<h4 id="heading-actuator">Actuator</h4>
<p>Actuator is a module in the Spring Boot framework that lets you monitor Spring Boot applications after/during development. It provides both inbuilt and customizable endpoints you can use for application health checks, metrics, and diagnostics.</p>
<p>These are some of the commonly used endpoints:</p>
<ul>
<li><p>/actuator/health: Provides health status. </p>
</li>
<li><p>/actuator/metrics: Displays various application metrics. </p>
</li>
<li><p>/actuator/info: Shows general application information. </p>
</li>
<li><p>/actuator/env: Exposes environment properties. </p>
</li>
<li><p>/actuator/beans: Lists all Spring beans. </p>
</li>
<li><p>/actuator/threaddump: Performs a thread dump. </p>
</li>
<li><p>/actuator/shutdown: Allows graceful shutdown (disabled by default).</p>
</li>
</ul>
<h4 id="heading-command-line-tool">Command line tool</h4>
<p>The Spring Boot command line tool is an interface that helps you rapidly develop and test your Spring Boot applications. It contains commands you can use to:</p>
<ul>
<li><p>Run Spring Boot applications from the terminal directly (spring run).</p>
</li>
<li><p>Manage application dependencies and versions</p>
</li>
<li><p>Initialize a new Spring Boot project</p>
</li>
<li><p>Compile and test Java/Groovy scripts.</p>
</li>
</ul>
<h4 id="heading-additional-configuration-through-applicationproperties-and-applicationyml-files">Additional configuration (through application.properties and application.yml files)</h4>
<p><code>application.properties</code> and <code>application.yml</code> files are two formats you can use to configure your Spring Boot application settings. They are in key-value and YAML formats, respectively. They let you configure ports, data source, logging, caching, and so on.</p>
<pre><code class="lang-plaintext"> server.port=8081
 spring.datasource.url=jdbc:mysql://localhost:3306/mydb

spring.datasource.username=root

spring.datasource.password=secret

logging.level.org.springframework=DEBUG
</code></pre>
<p>This is an example of an <code>application.properties</code> file for a Spring Boot project. You can see that the port, datasource and logging credentials have been configured.</p>
<h4 id="heading-embedded-web-server">Embedded Web Server</h4>
<p>Spring Boot comes with embedded web servers (Tomcat, Jetty, and Undertow) that are used to easily serve compiled Spring Boot applications in the form of jar files without needing to deploy them to an external, dedicated web server. This simplifies deployment, especially in a microservice architecture and containerised environments, as applications can be easily run using the command:</p>
<pre><code class="lang-java">java -jar my-springboot-app.jar
</code></pre>
<p>Note that Spring Boot cannot exist without Spring (but Spring can exist without Jakarta EE and other Java legacy frameworks created before it). Spring Boot is part of the Spring platform. It is like the extra icing on top of the cake that makes it sweeter.</p>
<p>Of course, you can still have your cake without the icing. Technically, you can say Spring Boot is an additional layer that still needs Spring to run as its underlying infrastructure.</p>
<h2 id="heading-core-differences-between-spring-and-spring-boot">Core Differences Between Spring and Spring Boot</h2>
<p>You should now be familiar with the fundamentals of the Spring and Spring Boot frameworks. So let’s talk a bit more about how they differ, x-raying their strengths and areas of weakness.</p>
<h3 id="heading-configuration">Configuration</h3>
<p>Configuration in Spring is more tedious when compared to Spring Boot, since you’ll need to manually add the configurations for your project in Spring. This requires more code for setting up the various components you need for a project.</p>
<p>Meanwhile, configuration in Spring Boot is easier as you can use the <a target="_blank" href="https://start.spring.io/">Spring Initializr website</a>. There, you just have to select the dependencies for the project, add a little more setup, and then download the zip file that contains the configuration for the project. It requires minimal steps to do this, which improves your productivity and makes the learning curve easier.</p>
<h3 id="heading-external-server-and-deployment">External Server and Deployment</h3>
<p>Spring requires that you deploy your applications to an external server like Tomcat in the form of a WAR (<strong>Web Application Archive</strong> or <strong>Web Application Resource</strong>) file.</p>
<p>Spring Boot, on the other hand, comes with an embedded server like Tomcat, which you can use for running/deploying stand-alone executable applications as JAR (or <strong>Java ARchive</strong>) files. This is why Spring Boot is highly preferred for developing microservices since it is relatively easy to build applications and run them.</p>
<h3 id="heading-level-of-control">Level of Control</h3>
<p>Both Spring and Spring Boot utilise the Inversion of Control (or IoC) paradigm for managing dependencies. Spring gives you more control over the application because you have the flexibility to initiate configurations as needed. But Spring Boot handles more of the application management internally, giving you little room for control over the application configuration, as it auto-generates configurations that may not be needed for a particular project. This can lead to redundant code. </p>
<h3 id="heading-suitability-for-development">Suitability for Development</h3>
<p>Spring, like Java EE, is preferred for large-scale enterprise applications due to its fine-grained configuration control that is invaluable, especially for complex and critical performance applications like banking, healthcare, and e-commerce. It provides great flexibility, which makes it suitable for integrating with Java EE components and other enterprise-grade technologies and legacy systems. </p>
<p>Spring Boot is not a common choice for large-scale monolithic applications, even though it can be used in these cases. It is more suitable for developing stand-alone applications or microservices where rapid development with embedded server support is prioritized over granular configuration and control.</p>
<h3 id="heading-production-ready-features">Production-ready features</h3>
<p>In Spring, extra effort is needed to manually set up health checks, metrics and monitoring of your application. Whereas, Spring Boot comes with the <strong>actuator</strong>, which is a built-in tool that is useful for metrics, application monitoring, and for carrying out health checks. You just need to add this dependency to your <strong>pom.xml</strong> file</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-actuator<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</code></pre>
<p>After that, you can monitor your application by visiting the desired actuator endpoint that exposes the needed information. Find a list of the common actuator endpoints you can visit under the <strong>Actuator</strong> subsection of the <strong>What is Spring Boot</strong> section above. </p>
<h2 id="heading-real-world-example">Real World Example</h2>
<p>Let’s look at an example of how to build a simple REST API endpoint in both Spring and Spring Boot frameworks:</p>
<h3 id="heading-building-with-the-spring-framework">Building with the Spring Framework</h3>
<p>In this API example, the technologies/dependencies we’ll use are:</p>
<ul>
<li><p>Java (Programming Language)</p>
</li>
<li><p>Maven (the build tool for the project)</p>
</li>
<li><p>Tomcat (servlet container)</p>
</li>
<li><p>Operating System (Mac/Linux/Windows)</p>
</li>
<li><p>Core Spring framework with the Spring MVC module</p>
</li>
<li><p>Jackson Databind: for JSON serialisation</p>
</li>
</ul>
<p>Note that we’ll be using Maven here as our build tool (and for the Spring Boot example that follows, too) because of its simplicity and beginner friendliness.</p>
<h4 id="heading-step-1-create-appconfigjava-file">Step 1: Create AppConfig.java file</h4>
<p>This is the configuration class that sets on Spring MVC properties through the <code>@EnableWebMvc</code> annotation, scans for the controllers in their packages through the <code>@ComponentScan</code> annotation, and configures other needed defaults automatically.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>

<span class="hljs-meta">@EnableWebMvc</span>

<span class="hljs-meta">@ComponentScan(basePackages = "com.example.controller")</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppConfig</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">WebMvcConfigurer</span> </span>{

}
</code></pre>
<h4 id="heading-step-2-create-webappinitializerjava">Step 2: Create WebAppInitializer.java</h4>
<p>This is the class that replaces <code>web.xml</code> (That was used in older versions.) It creates the Spring application context and connects to the <code>AppConfig</code> file for configuration. </p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WebAppInitializer</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">WebApplicationInitializer</span> </span>{  
  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onStartup</span><span class="hljs-params">(ServletContext servletContext)</span> </span>{

    <span class="hljs-comment">// Create annotation-based web context</span>

    AnnotationConfigWebApplicationContext context = 

      <span class="hljs-keyword">new</span> AnnotationConfigWebApplicationContext();

    context.register(AppConfig.class);

    // Register DispatcherServlet

    DispatcherServlet servlet = <span class="hljs-keyword">new</span> DispatcherServlet(context);

    ServletRegistration.Dynamic registration = 

      servletContext.addServlet(<span class="hljs-string">"dispatcher"</span>, servlet);

    registration.setLoadOnStartup(<span class="hljs-number">1</span>);

    registration.addMapping(<span class="hljs-string">"/"</span>);

  }

}
</code></pre>
<h4 id="heading-step-3-add-the-controller-logic">Step 3: Add the <strong>controller</strong> logic</h4>
<p>Create a <code>HelloController.java</code> file and add the controller logic. It receives a <strong>GET</strong> request and returns “Hello from Spring Framework!” </p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span> <span class="hljs-comment">// Combines @Controller + @ResponseBody</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloController</span> </span>{

  <span class="hljs-meta">@GetMapping("/hello")</span>

  <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">()</span> </span>{

    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello from Spring Framework!"</span>;

  }

}
</code></pre>
<h4 id="heading-step-4-add-dependencies">Step 4: Add Dependencies</h4>
<p>Include all the dependencies for the project in a <strong>pom.xml</strong> file, since we’re using Maven as the build tool.</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-webmvc<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>6.1.6<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span> <span class="hljs-comment">&lt;!-- Latest Spring 6.x --&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.fasterxml.jackson.core<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>jackson-databind<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>2.17.0<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span> <span class="hljs-comment">&lt;!-- For JSON support --&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
</code></pre>
<h4 id="heading-step-5-build-and-deploy-the-api">Step 5: Build and Deploy the API</h4>
<p>Lastly, you have to build the application into a WAR (Web Archive) file and deploy it to a servlet container (like Tomcat, Jetty, or whichever is suitable) before the application can be made accessible.</p>
<p>Follow the steps given below to deploy to a Tomcat server:</p>
<ol>
<li><h4 id="heading-package-the-app-as-a-war-file">Package the app as a WAR file</h4>
</li>
</ol>
<p>If Maven is your build tool for the project, add this configuration code to your Pom.xml file:</p>
<p><code>&lt;packaging&gt;war&lt;/packaging&gt;</code></p>
<p>Then, build using the command:</p>
<p><code>./mvnw clean package</code> </p>
<p>After this, your WAR file will be created and stored in <code>target/yourapp.war</code></p>
<ol start="2">
<li><h4 id="heading-deploy-your-war-file-to-a-servlet-container-in-this-case-tomcat">Deploy your WAR file to a servlet container (in this case, Tomcat)</h4>
</li>
</ol>
<p>At this point, you can choose to either deploy your WAR file to a remote or local servlet container on your machine. Let’s deploy to a local servlet container since you can easily practice this on your own.</p>
<ul>
<li><p>Download and install Apache Tomcat from the official website https://tomcat.apache.org/</p>
</li>
<li><p>Enter the <strong>webapps</strong> directory by entering the command <strong>cd path-to-tomcat/webapps/</strong></p>
</li>
<li><p>Copy your WAR file into the folder </p>
</li>
</ul>
<p>           <code>cp /path-to-your/target/yourapp.war</code> </p>
<ul>
<li>Start the Tomcat web server. </li>
</ul>
<p>On Linux/Mac OS, run:</p>
<p><code>./bin/startup.sh</code> </p>
<p>On Windows, do:</p>
<p><code>startup.bat</code>.</p>
<p>You should see a link similar to this on your terminal window:</p>
<p><code>http://localhost:8080/yourapp</code></p>
<p>Go ahead and click on it. And there you go!</p>
<h3 id="heading-building-with-the-spring-boot-framework">Building with the Spring Boot Framework</h3>
<p>The different technologies from the Spring example that I will use are simply the Embedded Tomcat server over the Tomcat servlet container. And here, of course, we’ll be using Spring Boot as the development framework instead of Spring.</p>
<p>In Spring Boot, you can either go straight into your IDE and start creating the needed files and configurations for your project, or you can choose to use the <a target="_blank" href="https://start.spring.io/">Spring initializr</a> to select dependencies and generate the base files and configurations for your project. The second option is preferred since it is less tedious.</p>
<h4 id="heading-step-1-choose-necessary-dependencies-for-your-project-and-download-the-zip-file">Step 1: Choose Necessary Dependencies for Your Project and Download the Zip File</h4>
<p>Open the <a target="_blank" href="https://start.spring.io/">Spring initializr</a> website, choose the project as Maven, language as Java, and fill in the project metadata. For this project, fill in the Artifact as Hello. </p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe41zF3IjWT8f8yW1kNlD4in3jhPev8DAm6lrIXf1anqZiZnCQtHfEavLP1u0DxMJ-h8crZVfsVcAdrEYxFHxuGmHF5PyjOEblTJEEL5vKx3XY1LYYbwY3CSyZAUfD7yv4nNpud7g?key=Zq-Isk9ZAG_nIZ1YfHDMRfMs" alt="Image showing how to correctly fill the metadata for a Spring Boot project from the Spring initializer website" width="1285" height="511" loading="lazy"></p>
<p>Choose jar for packaging, and then select the dependencies for the project. For this article, we will use only the Spring Web. Then click on the generate button. </p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc_5puGjgNKRvgAp4MrC_J_8o4ZMmJ4ozms6WDCJbsboF5oC7YarspzS65qXfFfSZtSkPJxLEcY11Or64irPvWnkmz9A0vxIh5BdFMJw_7lISxBqPyU78Uxa-s23AlbXKWIYIPLHw?key=Zq-Isk9ZAG_nIZ1YfHDMRfMs" alt="Image showing how to choose dependencies for a Spring Boot project from the Spring Initializer website" width="1600" height="739" loading="lazy"></p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcAi17ltnglcLuD6iDy0MLb6j2ANa4ssJKD6WdaPyQ0RERpOazdOcBfTWwFxix6U2Om9UPOxH-qy3k5gm6BbFTBdGf0PR9KH3EQvWfYucfpFBMM2EKb5DfMB8jcdj0xqYHfYbvOfg?key=Zq-Isk9ZAG_nIZ1YfHDMRfMs" alt="Image showing how to generate and download the files containing the configuration and dependencies for the Spring Boot project" width="828" height="683" loading="lazy"></p>
<p>This downloads a zip file to your machine containing the boilerplate code with which you can build your application.</p>
<h4 id="heading-step-2-create-the-controller-hellocontrollerjava">Step 2: Create the <strong>Controller (HelloController.java)</strong></h4>
<p>Unzip the downloaded file from step 1, and open it in your preferred IDE (or Integrated Development Environment). Navigate to the Hello/src/main/java/com/example/Hello directory, where you should already have the HelloApplication.java file, and add the HelloController.java file: </p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloController</span> </span>{

  <span class="hljs-meta">@GetMapping("/hello")</span>

  <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">()</span> </span>{

    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello from Spring Boot!"</span>;

  }

}
</code></pre>
<h4 id="heading-step-3-build-and-run-the-application">Step 3: Build and run the application</h4>
<p>On your terminal, run the following commands: <code>mvn clean package &amp;&amp; java -jar target/your-app.jar</code>. You can then access the endpoint on http://localhost:8080/hello. When you click on the link, you should see <code>Hello from Spring Boot!</code> on your screen.</p>
<h2 id="heading-how-to-choose-between-spring-and-spring-boot">How to Choose Between Spring and Spring Boot</h2>
<p>Spring and Spring Boot are both popular Java frameworks for building robust software solutions. And as you have learned from the earlier part of this tutorial, they have many common features (since Spring Boot is built atop Spring). </p>
<p>But there are a few key areas where they differ. First is the format of their packaged files: Spring is packaged to WAR, and Spring Boot to JAR. Also, Spring Boot comes with an embedded web server while Spring requires an external servlet container.</p>
<p>The embedded web server that comes with Spring Boot makes it easy to run Spring Boot applications during development and in production without needing an external servlet container. Meanwhile, traditional Spring requires developers to deploy to an external servlet container. This makes Spring Boot suitable for rapid development and deployment of stand-alone applications or microservices, as it not only saves time but also reduces setup complexity and infrastructure requirements.</p>
<p>Furthermore, Spring’s fine-grained configuration and ease of integration with legacy systems and tools make it the desired choice for developing highly customizable enterprise-grade applications. This is unlike Spring Boot, which relies on the convention-over-configuration philosophy, providing auto-configuration for reduced development time.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Building enterprise-grade and microservices applications with Java is much easier using the Spring and Spring Boot frameworks. </p>
<p>In this article, you’ve learned how these two frameworks work, along with their areas of strength and drawbacks.</p>
<p>This article doesn’t intend to favour one framework over the other, but rather to show in detail how they differ and their unique characteristics. </p>
<p><strong>But to summarize:</strong></p>
<ul>
<li><p>Use Spring when building highly customized legacy-integrated enterprise systems.</p>
</li>
<li><p>Use Spring Boot for REST APIs, microservices, or cloud-native apps.</p>
</li>
</ul>
<p>The next time you are faced with a project requiring you to choose a similar framework, it is imperative to carefully weigh your choices and select the framework that closely fits your task. Happy coding!</p>
<h3 id="heading-references">References</h3>
<ol>
<li><p><a target="_blank" href="https://spring.io/projects/spring-framework/">Spring Framework Official Documentation</a> </p>
</li>
<li><p><a target="_blank" href="https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/overview.html">Baeldung – Introduction to Spring Framework</a></p>
</li>
<li><p><a target="_blank" href="https://ellow.io/spring-vs-spring-boot/">Ellow. Spring vs Spring Boot: An In-depth Comparison</a></p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Constructors in Java: A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ Java is an object-oriented programming language that is centred around the concept of objects. Objects are like real-world entities that are created with the new keyword and occupy memory. But all this happens in the front-end code – so what about th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-constructors-in-java-a-beginners-guide/</link>
                <guid isPermaLink="false">686d6044aa83d1a2c46d6160</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ constructors ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ateev Duggal ]]>
                </dc:creator>
                <pubDate>Tue, 08 Jul 2025 18:15:32 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751998519087/7808c004-c8e5-4e63-b293-10fa479a179f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Java is an object-oriented programming language that is centred around the concept of objects. Objects are like real-world entities that are created with the new keyword and occupy memory. But all this happens in the front-end code – so what about the back-end? How are objects created and initialised with values?</p>
<p>This is where constructors come into play. Constructors are special types of methods with no return type. They are basically used to initialise the object, to set up its internal state, or to assign default values to its attributes.</p>
<p>In this tutorial, we will go deep into the topic of constructors in Java. You’ll learn how they work and why they are essential in object creation and Java programming. By the end, I hope you’ll understand why they’re one of the core concepts of OOP.</p>
<p>Let’s start…</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>You don’t need to know anything too advanced to start learning about constructors in Java. Just a basic understanding of Java syntax, classes, objects, methods, parameters, arguments, and access modifiers is enough to get started.</p>
<h2 id="heading-what-well-cover">What we’ll cover:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-are-constructors-in-java">What are Constructors in Java?</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-constructor-syntax">Constructor syntax:</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-types-of-constructors">Types of Constructors</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-default-constructor">Default Constructor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-no-argument-constructor">No Argument constructor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-parameterised-constructor">Parameterised Constructor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-copy-constructor">Copy Constructor</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-what-happens-behind-the-scenes-when-a-constructor-is-called-in-java">What Happens Behind the Scenes When a Constructor Is Called in Java?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-the-return-keyword-in-constructors">How to Use the return Keyword in Constructors</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-sample-code">Sample Code:</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-example-4">Example:</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-frequently-asked-questions">Frequently Asked Questions</a></p>
</li>
</ul>
<h2 id="heading-what-are-constructors-in-java"><strong>What are Constructors in Java?</strong></h2>
<p>As mentioned above, constructors are special types of methods that:</p>
<ol>
<li><p>do not have a return type (not even void), </p>
</li>
<li><p>have the same name as the class</p>
</li>
<li><p>are called automatically when an object is created using the new keyword. </p>
</li>
</ol>
<p>A constructor’s main purpose is to initialise a newly created object, to set up its internal state, or to assign default values to its attributes.</p>
<p>Constructors can also be understood as a special block of code which is called when an object is created – either automatically or manually by hard-coding it – with the values we want to initialise the object with.</p>
<p>If we’re okay with the object using default values (like 0 for numbers or null for objects), Java will handle that for us automatically. But if we want to give the object specific values when it's created, we need to write a constructor that takes those values as parameters and uses them to set up the object.</p>
<h3 id="heading-constructor-syntax"><strong>Constructor syntax:</strong></h3>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassName</span> </span>{

    <span class="hljs-comment">// Default constructor with access modifier</span>
    [access_modifier] ClassName(parameters...) {
        <span class="hljs-comment">// constructor body</span>
    }

}
</code></pre>
<h3 id="heading-examples">Examples</h3>
<p><strong>When the constructor is not defined explicitly</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{

    String brand;
    <span class="hljs-keyword">int</span> year;

    <span class="hljs-comment">// No constructor is defined, so Java provides a default one</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

        Car car1 = <span class="hljs-keyword">new</span> Car();  <span class="hljs-comment">// Java calls the default constructor</span>

        <span class="hljs-comment">// Default values: brand = null, year = 0</span>
        System.out.println(<span class="hljs-string">"Brand: "</span> + car1.brand);
        System.out.println(<span class="hljs-string">"Year: "</span> + car1.year);
    }
}
</code></pre>
<p>Output:</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcTW6FYYmq8kB1QL_vSBNqbaVBgo7hLXvqmA3l52HBh9Yvq4AN1aLIAKRqqiOz_tDcCFOTWBVoO1bgjWOD2yyt1nykuobAPQTWRayjqK0jDu2COmPxqI5AaapIyFzDbkrvreV-qyw?key=-LGNq3k7xufJJBHkVFXMZw" alt="output of the code in which there is no constructor" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In the above code, we have a <strong>Car</strong> class with two variables:</p>
<ol>
<li><p>brand of type <code>String</code></p>
</li>
<li><p>year of type <code>int</code></p>
</li>
</ol>
<p>Since a class is just a blueprint, we need to create an object to actually use it. This is done in the <code>Main</code> class. When we create a Car object using <code>new</code> Car(), Java looks for a constructor. Because we didn’t define one, the compiler automatically provides a default constructor (one with no arguments).</p>
<p>This allows us to create the object and print its variables without any errors. The values printed will be the default ones — <code>null</code> <strong>for the</strong> <code>String</code><strong>, and</strong> <code>0</code> <strong>for the</strong> <code>int</code><strong>.</strong></p>
<p>We'll dive deeper into how this works behind the scenes later, step by step, so it becomes easier to understand.</p>
<p><strong>When we have defined a constructor</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{

    String brand;
    <span class="hljs-keyword">int</span> year;

    <span class="hljs-comment">// Constructor with parameters to initialize custom values</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Car</span><span class="hljs-params">(String brandName, <span class="hljs-keyword">int</span> modelYear)</span> </span>{
        brand = brandName;
        year = modelYear;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

        Car car2 = <span class="hljs-keyword">new</span> Car(<span class="hljs-string">"Toyota"</span>, <span class="hljs-number">2022</span>);  <span class="hljs-comment">// Custom values</span>

        System.out.println(<span class="hljs-string">"Brand: "</span> + car2.brand);
        System.out.println(<span class="hljs-string">"Year: "</span> + car2.year);
    }
}
</code></pre>
<p><strong>Output</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751864448284/2cbb8360-1c6d-42b8-811f-b7603625288d.png" alt="Output of the code which has a constructor." class="image--center mx-auto" width="201" height="156" loading="lazy"></p>
<p>This is the same code as before, with one key difference: this time, we’ve explicitly defined a constructor. Because of this, the output we see isn’t the default values (<code>null</code> for <code>String</code>, <code>0</code> for <code>int</code>), but the custom values we provided.</p>
<p>How does that happen? Simple – we pass values as arguments when creating the object:</p>
<p><code>Car car2 = new Car("Toyota", 2022);</code></p>
<p>These values are received by the constructor as parameters and are then used to initialize the object’s variables. As a result, instead of default values, we get the brand and year we specified.</p>
<h2 id="heading-types-of-constructors"><strong>Types of Constructors</strong></h2>
<p>There are mainly four types of constructors:</p>
<ol>
<li><p>Default Constructors</p>
</li>
<li><p>No-Arguments Constructor</p>
</li>
<li><p>Parameterised Constructor</p>
</li>
<li><p>Copy Constructor</p>
</li>
</ol>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfafO5dDmX5UA0ADQI5Q8DZSU2H_bVlHjmtKdDpMkmWB4Rhui1kR4w_BP_7-mPz6eb9KdGkVmYxYsZHa4HI044mz3O0CXtXJZBhpJr_wCqWgLO6U0BDUNzm_C9piUHfyXr84xEsoQ?key=-LGNq3k7xufJJBHkVFXMZw" alt="Types of constructors" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-default-constructor"><strong>Default Constructor</strong></h3>
<p>A type of no-argument constructor that is added by the compiler during the compilation process so that the values of the object can be initialised. It’s only added by the compiler if you don’t add one explicitly.</p>
<h4 id="heading-syntax"><strong>Syntax:</strong></h4>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Constructor body</span>
    }

}
</code></pre>
<h4 id="heading-example"><strong>Example</strong></h4>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    <span class="hljs-comment">// No constructor defined here</span>
    <span class="hljs-comment">// Compiler will automatically add a default constructor</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Bike myBike = <span class="hljs-keyword">new</span> Bike();  <span class="hljs-comment">// Calls the compiler-provided default constructor</span>
        System.out.println(<span class="hljs-string">"Bike object created!"</span>);
    }

}
</code></pre>
<p>The code becomes the following after the compiler adds a default constructor during the compilation process:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    <span class="hljs-comment">// Compiler-added default constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Bike</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">super</span>();  <span class="hljs-comment">// Calls Object class constructor</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Bike myBike = <span class="hljs-keyword">new</span> Bike();  <span class="hljs-comment">// Now calls this explicit default constructor</span>
        System.out.println(<span class="hljs-string">"Bike object created!"</span>);
    }

}
</code></pre>
<h4 id="heading-output"><strong>Output</strong></h4>
<p>Bike object created!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751867033814/3296a90c-3576-4a57-a863-fe0d1acfafa2.png" alt="Default Constructor" class="image--center mx-auto" width="524" height="287" loading="lazy"></p>
<h3 id="heading-no-argument-constructor"><strong>No Argument constructor</strong></h3>
<p>No-argument constructor is a type of constructor that you explicitly write in your code and that does not contain any parameters.</p>
<p>Now, you may be wondering…Isn't it the same as the default constructor? The answer is both yes and no.</p>
<p>There isn’t much difference between the default constructor and the no-argument constructor, as both do not take any parameters. But there is one key difference.</p>
<p>The default constructor, as we have already discussed, is a type of no-argument constructor that is automatically added by the compiler when it doesn’t find one in our code. In contrast, a no-argument constructor is a type of constructor that we write in our code. </p>
<p>In short, if the compiler is the one that is adding a constructor during the compilation process, it's called a default constructor. But if we are the ones adding the constructor, it’s called a no-argument constructor. </p>
<p>The main difference between a default constructor and a user-defined constructor is <strong>how they are created and what they do</strong>.</p>
<ul>
<li><p>A <strong>default constructor</strong> is automatically added by the compiler <strong>if we don’t add one ourselves</strong>. It doesn’t do much – it just calls the parent class (usually the <code>Object class</code>) and sets all variables to their default values. For example, <code>int</code> becomes <code>0</code>and objects become <code>null</code>.</p>
</li>
<li><p>A <strong>user-defined constructor</strong> is one that <strong>we write ourselves</strong>. We can add custom logic inside it, set custom values to variables, and use access modifiers like <code>public</code>, <code>private</code>, or <code>protected</code>. This means we can decide how the object should be set up when it is created.</p>
</li>
</ul>
<p>Note that even if we don’t write <code>super()</code> in our constructor, Java still adds it automatically unless we call another constructor with <code>this()</code> or call a different <code>super(...)</code> with parameters.</p>
<p>We will understand this deeply in the next section.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><strong>Default Constructor</strong></td><td><strong>No-Argument Constructor</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Definition</strong></td><td>A constructor is automatically provided by the compiler when no other constructors exist.</td><td>A constructor explicitly written by the programmer that takes no arguments.</td></tr>
<tr>
<td><strong>Defined By</strong></td><td>Compiler</td><td>Programmer</td></tr>
<tr>
<td><strong>Custom Logic</strong></td><td>Not possible – does only basic, default initialization</td><td>Yes – can contain any initialization logic</td></tr>
<tr>
<td><strong>When Available</strong></td><td>Only if the class has no constructors defined at all</td><td>When explicitly written by the programmer</td></tr>
<tr>
<td><strong>Purpose</strong></td><td>To allow object creation with default initialization</td><td>To allow object creation with programmer-defined behavior</td></tr>
</tbody>
</table>
</div><h4 id="heading-syntax-1"><strong>Syntax:</strong></h4>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassName</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ClassName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Body (optional)</span>
    }

}
</code></pre>
<h4 id="heading-example-1"><strong>Example</strong></h4>
<p>Let's use the same Bike example we used to explain the default constructor.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Bike</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Bike object created!"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Bike myBike = <span class="hljs-keyword">new</span> Bike();
    }
}
</code></pre>
<h4 id="heading-output-1"><strong>Output:</strong></h4>
<p>Bike object created!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751868234945/565ec06d-7e4d-4415-b983-f517c721d0b9.png" alt="No Argument Construment" class="image--center mx-auto" width="650" height="277" loading="lazy"></p>
<p>In the above code, we have defined a constructor in our code while writing it. This means that it is an example of a no-argument constructor.</p>
<p>We know that both types of constructors are defined without any parameters, but what about the body? We haven’t said anything about it. Let’s see what happens if we write code with a no-argument constructor without a body:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    Bike() {
        <span class="hljs-comment">// No body</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Bike myBike = <span class="hljs-keyword">new</span> Bike(); <span class="hljs-comment">// Calls the user-defined no-argument constructor</span>
        System.out.println(<span class="hljs-string">"Bike object created!"</span>);
    }
}
</code></pre>
<h4 id="heading-output-2"><strong>Output:</strong></h4>
<p>Bike object created!</p>
<p>The code still gets compiled because the compiler adds the <code>super()</code> keyword during the compilation process, which initialises the object using the object class.</p>
<h3 id="heading-parameterised-constructor"><strong>Parameterised Constructor</strong></h3>
<p>A constructor that accepts parameters is called a parameterised constructor and is only used when we have to initialise an object’s attributes with custom values. </p>
<ul>
<li><p>Parameter refers to the variable listed in the constructor or method definition.</p>
</li>
<li><p>Argument is the actual value passed when calling the constructor or method.</p>
</li>
</ul>
<p>It gives us the flexibility of initiating our object with custom values given at the time of object creation.</p>
<h4 id="heading-syntax-2"><strong>Syntax</strong></h4>
<p>Below is the syntax for a parameterised constructor that takes one parameter:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassName</span> </span>{

    <span class="hljs-comment">// Data members (instance variables)</span>
    DataType variable1;

    <span class="hljs-comment">// Parameterized constructor</span>
    ClassName(DataType param1) {
        variable1 = param1;
    }

    <span class="hljs-comment">// Main method to create objects</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Creating object using parameterized constructor</span>
        ClassName obj = <span class="hljs-keyword">new</span> ClassName(value1);
    }
}
</code></pre>
<h4 id="heading-example-2"><strong>Example</strong></h4>
<p>We will again use the Bike example for this.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    String modelName;  <span class="hljs-comment">// instance variable</span>

    <span class="hljs-comment">// Parameterized constructor</span>
    Bike(String model) {
        modelName = model;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Pass parameter while creating the Bike object</span>
        Bike myBike = <span class="hljs-keyword">new</span> Bike(<span class="hljs-string">"Mountain Bike"</span>);
        System.out.println(<span class="hljs-string">"Bike object created! Model: "</span> + myBike.modelName);
    }
}
</code></pre>
<h4 id="heading-output-3">Output:</h4>
<p>Bike object created! Model: Mountain Bike</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751870395133/72bcbe0c-3a7c-4cc1-87d4-1ae9106b21d9.png" alt="Parameterized Constructor" class="image--center mx-auto" width="706" height="349" loading="lazy"></p>
<p>In this example, we’re working with a Bike class that has an instance variable of String data type called modelName, and a constructor to set the value of that variable.</p>
<p>The constructor takes a parameter called model and assigns it to modelName. So, when we create a new Bike object and pass in the string "Mountain Bike", the constructor stores that value in the modelName variable.</p>
<p>Because of this, when we print out the model name, we see "Mountain Bike" instead of null, which is the default value of the String data type, as now the value of the modelName has been updated.</p>
<h3 id="heading-copy-constructor"><strong>Copy Constructor</strong></h3>
<p>A copy constructor is used to create a new object as a copy of the existing object. Unlike C++, Java doesn’t have a default copy constructor. Instead, we have to create our own by creating a constructor that takes an object of the same class as a parameter and copies its fields.</p>
<h4 id="heading-syntax-3"><strong>Syntax</strong></h4>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ClassName</span> </span>{

    <span class="hljs-comment">// Fields</span>
    DataType1 field1;
    DataType2 field2;
    <span class="hljs-comment">// ... other fields</span>

    <span class="hljs-comment">// Normal constructor</span>
    ClassName(DataType1 f1, DataType2 f2) {
        field1 = f1;
        field2 = f2;
        <span class="hljs-comment">// ... initialize other fields</span>
    }

    <span class="hljs-comment">// Copy constructor </span>
    ClassName(ClassName other) {
        field1 = other.field1;
        field2 = other.field2;
        <span class="hljs-comment">// ... copy other fields</span>
    }
}
</code></pre>
<h4 id="heading-example-3"><strong>Example</strong></h4>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    String modelName;  <span class="hljs-comment">// instance variable</span>

    <span class="hljs-comment">// Parameterized constructor</span>
    Bike(String model) {
        modelName = model;
    }

    <span class="hljs-comment">// Copy constructor</span>
    Bike(Bike otherBike) {
        modelName = otherBike.modelName;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create a Bike object using the parameterized constructor</span>
        Bike myBike = <span class="hljs-keyword">new</span> Bike(<span class="hljs-string">"Mountain Bike"</span>);
        System.out.println(<span class="hljs-string">"Bike object created! Model: "</span> + myBike.modelName);

        <span class="hljs-comment">// Create a copy of the existing Bike object using the copy constructor</span>
        Bike copiedBike = <span class="hljs-keyword">new</span> Bike(myBike);
        System.out.println(<span class="hljs-string">"Copied Bike object created! Model: "</span> + copiedBike.modelName);
    }
}
</code></pre>
<h4 id="heading-output-4"><strong>Output:</strong></h4>
<p>Bike object created! Model: Mountain Bike</p>
<p>Copied Bike object created! Model: Mountain Bike</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751874707838/772bdc8a-75d7-437d-a296-7f472fe5c764.png" alt="Copy Constructor" class="image--center mx-auto" width="435" height="289" loading="lazy"></p>
<p>In the above code, we have created a copy constructor to copy the values of the object (myBike) into a new object (copiedBike), which we have defined in the main class.</p>
<p>But the way the new object is called is a little different. Instead of passing arguments for the constructor, we have passed the original object.</p>
<h4 id="heading-why-copy-constructors"><strong>Why Copy Constructors?</strong></h4>
<p>A copy constructor is used to make a copy of the object, but you can also make a copy using the clone() method or the object.clone() method. So why do we use a copy constructor?</p>
<p>The copy constructor makes a deep copy, while the clone method makes a shallow copy of the object. There are various things that you should know before using cloning techniques, like <a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/lang/CloneNotSupportedException.html">CloneNotSupportedException</a><strong>.</strong></p>
<p>On the other hand, copy constructors are clear and easy to understand, and work well with final fields. We can control how the copy happens (deep vs. shallow) and especially when we are dealing with mutable objects.</p>
<h2 id="heading-what-happens-behind-the-scenes-when-a-constructor-is-called-in-java"><strong>What Happens Behind the Scenes When a Constructor Is Called in Java?</strong></h2>
<p>So, just to recap: when we create an object using the <code>new</code> keyword, a constructor is automatically called. If we haven't defined any constructors in our class, Java automatically defines a constructor for us. </p>
<p>But while writing and running our code, we mostly focus on what’s visible in our editor, as in what we can see. Let’s dive a little deeper and explore what happens behind the scenes – at the compiler and JVM level – when an object is created and executed.</p>
<ul>
<li><p><strong>Step 1: Memory Allocation</strong> – When we create an object using a new keyword, Java allocates memory for that object in the heap. This memory is where the object’s fields (also called attributes) will be placed.</p>
</li>
<li><p><strong>Step 2: Reference Creation</strong> – A reference to this object is stored on the stack, which lets our program interact with the object that lives in the heap.</p>
</li>
<li><p><strong>Step 3: Constructor Creation</strong> – Java then determines which constructor to call. If no constructor is explicitly defined in our class, the compiler automatically inserts a constructor with no parameters.</p>
</li>
<li><p><strong>Step 4: Superclass Constructor Call</strong> – Before executing the constructor’s body, Java first calls the constructor of the superclass using the <code>super()</code> keyword. This ensures that the fields inherited from the parent class are properly initialised. If you don’t explicitly write <code>super()</code>, the compiler adds it automatically in the first line of the code, but only if the superclass has a no-argument constructor, unless we're already calling another constructor via <code>this()</code>.</p>
</li>
</ul>
<p>But don’t use both the <code>super()</code> and <code>this()</code> keywords in the same constructor (you can use them in separate constructors.</p>
<p>Let’s say that it doesn’t have a super class – then what? </p>
<p>The answer is simple: Java has an in-built Object class that has a no-argument constructor by default.  This is why our classes run smoothly even if we don’t write super() ourselves, as Java calls it in the background. </p>
<p>That means every class we create is a subclass of the object class:</p>
<h4 id="heading-attribute-initialisation">Attribute Initialisation:</h4>
<p>At this point, fields get initialised:</p>
<ul>
<li><p>First, with default values (for example, 0 for int, null for objects),</p>
</li>
<li><p>Then, with any explicit initialisations we've written (for example, int x = 10), the default values will get replaced by them.</p>
</li>
</ul>
<h4 id="heading-constructor-execution">Constructor Execution:</h4>
<p>And finally, the logic runs. This is where all or some of the attributes defined in the class for object creation are initialised by the parameters used during object creation, with the help of constructors. </p>
<p>But not every field may get initialised. Fields that are not updated by the constructor will keep the values they already have (either the default value or the explicitly initialised values). </p>
<p>In short, the constructor gives us the flexibility to customise our object at the time of creation, but it doesn't automatically set every field unless we explicitly write the logic for it.</p>
<p>Check the code below to understand better:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Example</span> </span>{

    <span class="hljs-keyword">int</span> a;           <span class="hljs-comment">// default 0</span>
    <span class="hljs-keyword">int</span> b = <span class="hljs-number">10</span>;      <span class="hljs-comment">// explicitly initialized to 10</span>
    String name;     <span class="hljs-comment">// default null</span>

    Example(<span class="hljs-keyword">int</span> x) {
        a = x;       <span class="hljs-comment">// only 'a' is set through constructor</span>
        <span class="hljs-comment">// 'b' is not changed, stays 10</span>
        <span class="hljs-comment">// 'name' is not changed, stays null</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">display</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"a = "</span> + a);
        System.out.println(<span class="hljs-string">"b = "</span> + b);
        System.out.println(<span class="hljs-string">"name = "</span> + name);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Example obj = <span class="hljs-keyword">new</span> Example(<span class="hljs-number">5</span>);
        obj.display();
    }
}
</code></pre>
<p><strong>Output:</strong></p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfRr6j8-QeGffPm7DYMImJL5s9X-apEGhLzXAv_cNw2CcwONejKxd4-_xKbmdKGSW1w09lt3Pib_psv7RLkd5LJ1uUxd9LSU2KOcDU9kYeqjYbZWS-qUN1PuLbNV8uF0M373kl7Cw?key=-LGNq3k7xufJJBHkVFXMZw" alt="Output of the code explaining how constructor work." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>In the above example, we have three data members – a, b, and name. We have already done the declaration and initialisation of the variable b at the beginning and given a value to a at the time of object creation.</p>
<p>So we can see that:</p>
<ol>
<li><p>‘<strong>a</strong>’, whose value has been updated by the constructor with the value given at the time of object creation, has the same value</p>
</li>
<li><p><strong>‘b’,</strong> which already had a value and does not get updated by the constructor, prints the same value </p>
</li>
<li><p>the string <strong>‘name’</strong> didn’t have a value, so null was printed instead, as it is the default value of the String data type.</p>
</li>
</ol>
<h2 id="heading-how-to-use-the-return-keyword-in-constructors"><strong>How to Use the</strong> <code>return</code> <strong>Keyword in Constructors</strong></h2>
<p>We know that constructors are defined without a return type, but we can use the return keyword in the constructor only to exit the constructor early, not to return a value. Check out the code below.</p>
<h3 id="heading-sample-code"><strong>Sample Code:</strong></h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    String modelName;  <span class="hljs-comment">// instance variable</span>
    <span class="hljs-keyword">int</span> speed;

    <span class="hljs-comment">// Parameterized constructor</span>
    Bike(String model, <span class="hljs-keyword">int</span> sp) {
        modelName = model;
        <span class="hljs-keyword">return</span>;
        speed = sp;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Pass parameter while creating the Bike object</span>
        Bike myBike = <span class="hljs-keyword">new</span> Bike(<span class="hljs-string">"Mountain Bike"</span>, <span class="hljs-number">20</span>);
        System.out.println(<span class="hljs-string">"Bike object created! Model: "</span> + myBike.modelName);
        System.out.println(<span class="hljs-string">"Speed of the Bike is "</span> + myBike.speed);
    }
}
</code></pre>
<p>Let’s try to understand the above code and the use of the return keyword along with it. We will start with what would happen if the return keyword wasn’t here. The code would have executed without any errors and would have received an output.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdRpxqN-7mjbNNenChHDcIxtufG5P4LQOG1GXo4L7_kFz955k-YF2HJfy96ZoIbPtxy3flUKiw4Mq6C8qSdZEnw3bzg5rbAy3BR4Q4x7uO2EjZfN7zFGDRlCWbAth_s97TGvoHpCQ?key=-LGNq3k7xufJJBHkVFXMZw" alt="code without the return keyword" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Now, what will happen if we add the return keyword? As we have discussed above, the return keyword will tell the compiler not to go beyond this point in the constructor. </p>
<p>So whatever we have written in the constructor after the return keyword will not be compiled, and if that had any value and was necessary for the proper execution of our code, the compiler will throw an error.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc63VgyWkEdvcPr8x9TkVb-ZJKuPO2Z-ips_sNT70zGwFYRRdzfYYWG1Bfwnjmdypz-Pt8YS6SwQGBKMNrNhz4J27psGuOxz9Fs0gLVpM0oHzn5N1J0w3wgL7HU7rUQlB200qoRoA?key=-LGNq3k7xufJJBHkVFXMZw" alt="code with the return keyword" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The error says it clearly ‘unreachable statement’, which means that the compiler was not allowed to go beyond the return keyword. </p>
<p>Now that you understand the return keyword, let’s see when you can use it.</p>
<h3 id="heading-example-4"><strong>Example:</strong></h3>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bike</span> </span>{

    <span class="hljs-comment">// Constructor with a condition to exit early</span>
    Bike(<span class="hljs-keyword">boolean</span> skip) {
        <span class="hljs-keyword">if</span> (skip) {
            System.out.println(<span class="hljs-string">"Constructor exited early"</span>);
            <span class="hljs-keyword">return</span>; <span class="hljs-comment">// Ends constructor execution here</span>
        }

        System.out.println(<span class="hljs-string">"Constructor continues..."</span>);
        <span class="hljs-comment">// More initialization logic can go here</span>
        System.out.println(<span class="hljs-string">"Bike object initialized successfully"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        System.out.println(<span class="hljs-string">"Creating first bike (skip = true):"</span>);
        Bike bike1 = <span class="hljs-keyword">new</span> Bike(<span class="hljs-keyword">true</span>);  <span class="hljs-comment">// Constructor will exit early</span>

        System.out.println(<span class="hljs-string">"\nCreating second bike (skip = false):"</span>);
        Bike bike2 = <span class="hljs-keyword">new</span> Bike(<span class="hljs-keyword">false</span>); <span class="hljs-comment">// Constructor will continue</span>
    }
}
</code></pre>
<p>We’ve defined a Bike class that has a constructor with one boolean parameter called skip. Inside the constructor, there's an if statement that checks if skip is true. If it is, the constructor prints a message and uses the return keyword to exit early. This means the rest of the constructor won’t run.</p>
<p>But there is no else block. So what happens when skip is false? In that case, the if condition is not true, then the code inside the if statement is not executed (including the return keyword) and the constructor simply continues to the next lines of code. That’s where we do the actual bike initialisation and print a success message.</p>
<p>In short:</p>
<ol>
<li><p>If skip is true, the constructor exits early.</p>
</li>
<li><p>If skip is false, the constructor continues and finishes the setup.</p>
</li>
</ol>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeK-1kbbG97wMT_d-zrZ28eCuVsWZEkH6Ve3kuYSyXM1e-pZDsJl8K1S4GVfp54XnxGLOGGH_y_B3lZvmy1GRSvOY5Xp_rqHZd7jdNHHxdVAdVuW5vM__6DU99SdS38b03jXjkj?key=-LGNq3k7xufJJBHkVFXMZw" alt="output of the example explaining return keyword" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This is a simple way to control how much of the constructor runs, based on a condition.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this blog, we have understood many different topics, what a constructor is, its different types, like default constructor, no argument constructor, parameterised constructor and copy constructor, not only with theory but with code examples as well.</p>
<p>Understanding them will not only enhance our understanding but also help us write modular and well-maintained code in Java. While this concept is also important in OOP, as it is centred around the concept of objects and constructors are the ones that are used to initialise them.</p>
<h2 id="heading-frequently-asked-questions"><strong>Frequently Asked Questions</strong></h2>
<p><strong>Q1. Why do we use constructors?</strong></p>
<p><strong>A:</strong> We use constructors because:</p>
<ol>
<li><p>They are created automatically by the compiler and initialise the object with default values.</p>
</li>
<li><p>We can initialise all the attributes of the objects in one go.</p>
</li>
<li><p>They prevent incomplete or incorrect object initialisation by ensuring that important data is provided during object creation.</p>
</li>
<li><p>Code maintainability and modularity increase.</p>
</li>
<li><p>We can use objects as soon as they are created.</p>
</li>
</ol>
<p><strong>Q2. What is the basic difference between Method Overloading and Constructor Overloading?</strong></p>
<p><strong>A:</strong> </p>
<table><tbody><tr><td><p><strong>Feature</strong></p></td><td><p><strong>Method Overloading</strong></p></td><td><p><strong>Constructor Overloading</strong></p></td></tr><tr><td><p><strong>Purpose</strong></p></td><td><p>To perform different operations with the same method name</p></td><td><p>To create objects with different initialisations</p></td></tr><tr><td><p><strong>Return Type</strong></p></td><td><p>Can have a return type</p></td><td><p>Has no return type</p></td></tr><tr><td><p><strong>Name</strong></p></td><td><p>Can be any valid method name</p></td><td><p>Always has the same name as the class</p></td></tr><tr><td><p><strong>Usage Context</strong></p></td><td><p>Called on existing objects</p></td><td><p>Called when creating objects</p></td></tr></tbody></table>

<p>You can check out some of my other beginner-friendly articles on my blog:</p>
<ol>
<li><p><a target="_blank" href="https://tekolio.com/what-is-abstraction-in-java-and-how-to-achieve-it/">Understanding abstraction in Java</a></p>
</li>
<li><p><a target="_blank" href="https://tekolio.com/how-to-build-a-movie-app-in-react-using-tmdb-api/">How to build a Movie App in React using TMDB API?</a></p>
</li>
<li><p><a target="_blank" href="https://tekolio.com/how-to-merge-two-sorted-arrays/">How to merge two sorted arrays</a></p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the Java Collections Framework – A Guide for Developers ]]>
                </title>
                <description>
                    <![CDATA[ In your Java applications, you’ll typically work with various types of objects. And you might want to perform operations like sorting, searching, and iterating on these objects. Prior to the introduction of the Collections framework in JDK 1.2, you w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/java-collections-framework-reference-guide/</link>
                <guid isPermaLink="false">6798fd38ac05f27ed5691abd</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Collection Framework ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anjan Baradwaj ]]>
                </dc:creator>
                <pubDate>Tue, 28 Jan 2025 15:52:24 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738077724002/cfbf6a90-f9c2-4853-b1c3-c33774f078c1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In your Java applications, you’ll typically work with various types of objects. And you might want to perform operations like sorting, searching, and iterating on these objects.</p>
<p>Prior to the introduction of the Collections framework in JDK 1.2, you would’ve used Arrays and Vectors to store and manage a group of objects. But they had their own share of drawbacks.</p>
<p>The Java Collections Framework aims to overcome these issues by providing high-performance implementations of common data structures. These allow you to focus on writing the application logic instead of focusing on low-level operations.</p>
<p>Then, the introduction of Generics in JDK 1.5 significantly improved the Java Collections Framework. Generics let you enforce type safety for objects stored in a collection, which enhances the robustness of your applications. You can read more about Java Generics <a target="_blank" href="https://www.freecodecamp.org/news/generics-in-java/">here</a>.</p>
<p>In this article, I will guide you through how to use the Java Collections Framework. We’ll discuss the different types of collections, such as Lists, Sets, Queues, and Maps. I’ll also provide a brief explanation of their key characteristics such as:</p>
<ul>
<li><p>Internal mechanisms</p>
</li>
<li><p>Handling of duplicates</p>
</li>
<li><p>Support for null values</p>
</li>
<li><p>Ordering</p>
</li>
<li><p>Synchronization</p>
</li>
<li><p>Performance</p>
</li>
<li><p>Key methods</p>
</li>
<li><p>Common implementations</p>
</li>
</ul>
<p>We’ll also walk through some code examples for better understanding, and I’ll touch on the Collections utility class and its usage.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-understanding-the-java-collections-framework">Understanding the Java Collections Framework</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-collection-interfaces">Collection Interfaces</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-decoding-the-java-collections-framework-hierarchy">Decoding the Java Collections Framework Hierarchy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-a-closer-look-at-collection-interfaces">A Closer Look at Collection Interfaces</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-java-collection-interfaces">Java Collection Interfaces</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-lists">Lists</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-sets">Sets</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-queues">Queues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-maps">Maps</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-collections-utility-class">Collections Utility Class</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-understanding-the-java-collections-framework"><strong>Understanding the Java Collections Framework</strong></h2>
<p>According to the Java <a target="_blank" href="https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html">documentation</a>, “<em>A collection is an object that represents a group of objects. A collections framework is a unified architecture for representing and manipulating collections</em>.”</p>
<p>In simple terms, the Java Collections Framework helps you manage a group of objects and perform operations on them efficiently and in an organized way. It makes it easier to develop applications by offering various methods to handle groups of objects. You can add, remove, search, and sort objects effectively using the Java Collections Framework.</p>
<h3 id="heading-collection-interfaces">Collection Interfaces</h3>
<p>In Java, an interface specifies a contract that must be fulfilled by any class that implements it. This means the implementing class must provide concrete implementations for all the methods declared in the interface.</p>
<p>In the Java Collections Framework, various collection interfaces like <code>Set</code>, <code>List</code>, and <code>Queue</code> extend the <code>Collection</code> interface, and they must adhere to the contract defined by the <code>Collection</code> interface.</p>
<h3 id="heading-decoding-the-java-collections-framework-hierarchy">Decoding the Java Collections Framework Hierarchy</h3>
<p>Check out this neat diagram from this <a target="_blank" href="https://medium.com/@mbanaee61/mastering-the-java-collections-framework-hierarchy-with-java-code-and-junit-testing-ab2eb87746ed">article</a> that illustrates the Java Collection Hierarchy:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736532451482/6ef571c1-afe0-4314-9038-b472b06f4065.webp" alt="Diagram showing the Java Collection Framework hierarchy. It includes interfaces like Iterable, Collection, List, Queue, Set, Map, and SortedMap, with classes such as ArrayList, LinkedList, Vector, Stack, PriorityQueue, Deque, HashSet, LinkedHashSet, SortedSet, TreeSet, Hashtable, LinkedHashMap, HashMap, and TreeMap. Arrows indicate implementation and extension relationships." class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>We’ll start from the top and work down so you can understand what this diagram is showing:</p>
<ol>
<li><p>At the root of the Java Collections Framework is the <code>Iterable</code> interface, which lets you iterate over the elements of a collection.</p>
</li>
<li><p>The <code>Collection</code> interface extends the <code>Iterable</code> interface. This means it inherits the properties and behavior of the <code>Iterable</code> interface and adds its own behavior for adding, removing, and retrieving elements.</p>
</li>
<li><p>Specific interfaces such as <code>List</code>, <code>Set</code>, and <code>Queue</code> further extend the <code>Collection</code> interface. Each of these interfaces has other classes implementing their methods. For example, <code>ArrayList</code> is a popular implementation of the <code>List</code> interface, <code>HashSet</code> implements the <code>Set</code> interface, and so on.</p>
</li>
<li><p>The <code>Map</code> interface is part of the Java Collections Framework, but it does not extend the <code>Collection</code> interface, unlike the others mentioned above.</p>
</li>
<li><p>All the interfaces and classes in this framework are part of the <code>java.util</code> package.</p>
</li>
</ol>
<p>Note: A common source of confusion in the Java Collections Framework revolves around the difference between <code>Collection</code> and <code>Collections</code>. <code>Collection</code> is an interface in the framework, while <code>Collections</code> is a utility class. The <code>Collections</code> class provides static methods that perform operations on the elements of a collection.</p>
<h2 id="heading-java-collection-interfaces">Java Collection Interfaces</h2>
<p>By now, you’re familiar with the different types of collections that form the foundation of the collections framework. Now we’ll take a closer look at the <code>List</code>, <code>Set</code>, <code>Queue</code>, and <code>Map</code> interfaces.</p>
<p>In this section, we'll discuss each of these interfaces while exploring their internal mechanisms. We'll examine how they handle duplicate elements and whether they support the insertion of null values. We'll also understand the ordering of elements during insertion and their support for synchronization, which deals with the concept of thread safety. Then we’ll walk through a few key methods of these interfaces and conclude by reviewing common implementations and their performance for various operations.</p>
<p>Before we begin, let's talk briefly about Synchronization and Performance.</p>
<ul>
<li><p>Synchronization controls access to shared objects by multiple threads, ensuring their integrity and preventing conflicts. This is crucial for maintaining thread safety.</p>
</li>
<li><p>When choosing a collection type, one important factor is its performance during common operations like insertion, deletion, and retrieval. Performance is usually expressed using Big-O notation. You can learn more about it <a target="_blank" href="https://www.freecodecamp.org/news/big-o-notation-why-it-matters-and-why-it-doesnt-1674cfa8a23c/">here</a>.</p>
</li>
</ul>
<h3 id="heading-lists">Lists</h3>
<p>A <code>List</code> is an ordered or sequential collection of elements. It follows zero-based indexing, allowing the elements to be inserted, removed, or accessed using their index position.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: A <code>List</code> is internally supported by either an array or a linked list, depending on the type of implementation. For example, an <code>ArrayList</code> uses an array, while a <code>LinkedList</code> uses a linked list internally. You can read more about <code>LinkedList</code> <a target="_blank" href="https://www.freecodecamp.org/news/how-linked-lists-work/">here</a>. A <code>List</code> dynamically resizes itself upon the addition or removal of elements. The indexing-based retrieval makes it a very efficient type of collection.</p>
</li>
<li><p><strong>Duplicates</strong>: Duplicate elements are allowed in a <code>List</code>, which means there can be more than one element in a <code>List</code> with the same value. Any value can be retrieved based on the index at which it is stored.</p>
</li>
<li><p><strong>Null</strong>: Null values are also allowed in a <code>List</code>. Since duplicates are permitted, you can also have multiple null elements.</p>
</li>
<li><p><strong>Ordering</strong>: A <code>List</code> maintains insertion order, meaning the elements are stored in the same order they are added. This is helpful when you want to retrieve elements in the exact order they were inserted.</p>
</li>
<li><p><strong>Synchronization</strong>: A <code>List</code> is not synchronized by default, which means it doesn't have a built-in way to handle access by multiple threads at the same time.</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>List</code> interface: <code>add(E element)</code>, <code>get(int index)</code>, <code>set(int index, E element)</code>, <code>remove(int index)</code>, and <code>size()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.ArrayList;
 <span class="hljs-keyword">import</span> java.util.List;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ListExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a list</span>
         List&lt;String&gt; list = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

         <span class="hljs-comment">// add(E element)</span>
         list.add(<span class="hljs-string">"Apple"</span>);
         list.add(<span class="hljs-string">"Banana"</span>);
         list.add(<span class="hljs-string">"Cherry"</span>);

         <span class="hljs-comment">// get(int index)</span>
         String secondElement = list.get(<span class="hljs-number">1</span>); <span class="hljs-comment">// "Banana"</span>

         <span class="hljs-comment">// set(int index, E element)</span>
         list.set(<span class="hljs-number">1</span>, <span class="hljs-string">"Blueberry"</span>);

         <span class="hljs-comment">// remove(int index)</span>
         list.remove(<span class="hljs-number">0</span>); <span class="hljs-comment">// Removes "Apple"</span>

         <span class="hljs-comment">// size()</span>
         <span class="hljs-keyword">int</span> size = list.size(); <span class="hljs-comment">// 2</span>

         <span class="hljs-comment">// Print the list</span>
         System.out.println(list); <span class="hljs-comment">// Output: [Blueberry, Cherry]</span>

         <span class="hljs-comment">// Print the size of the list</span>
         System.out.println(size); <span class="hljs-comment">// Output: 2</span>
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>ArrayList</code>, <code>LinkedList</code>, <code>Vector</code>, <code>Stack</code></p>
</li>
<li><p><strong>Performance</strong>: Typically, insert and delete operations are fast in both <code>ArrayList</code> and <code>LinkedList</code>. But fetching elements can be slow because you have to traverse through the nodes.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>ArrayList</strong></td><td><strong>LinkedList</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast at the end - O(1) amortized, slow at the beginning or middle- O(n)</td><td>Fast at the beginning or middle - O(1), slow at the end - O(n)</td></tr>
<tr>
<td>Deletion</td><td>Fast at the end - O(1) amortized, slow at the beginning or middle- O(n)</td><td>Fast - O(1) if position is known</td></tr>
<tr>
<td>Retrieval</td><td>Fast - O(1) for random access</td><td>Slow - O(n) for random access, as it involves traversing</td></tr>
</tbody>
</table>
</div><h3 id="heading-sets">Sets</h3>
<p>A <code>Set</code> is a type of collection that does not allow duplicate elements and represents the concept of a mathematical set.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: A <code>Set</code> is internally backed by a <code>HashMap</code>. Depending on the implementation type, it is supported by either a <code>HashMap</code>, <code>LinkedHashMap</code>, or a <code>TreeMap</code>. I have written a detailed article about how <code>HashMap</code> works internally <a target="_blank" href="https://www.freecodecamp.org/news/how-java-hashmaps-work-internal-mechanics-explained">here</a>. Be sure to check it out.</p>
</li>
<li><p><strong>Duplicates</strong>: Since a <code>Set</code> represents the concept of a mathematical set, duplicate elements are not allowed. This ensures that all elements are unique, maintaining the integrity of the collection.</p>
</li>
<li><p><strong>Null</strong>: A maximum of one null value is allowed in a <code>Set</code> because duplicates are not permitted. But this does not apply to the <code>TreeSet</code> implementation, where null values are not allowed at all.</p>
</li>
<li><p><strong>Ordering</strong>: Ordering of elements in a <code>Set</code> depends on the type of implementation.</p>
<ul>
<li><p><code>HashSet</code>: Order is not guaranteed, and elements can be placed in any position.</p>
</li>
<li><p><code>LinkedHashSet</code>: This implementation maintains the insertion order, so you can retrieve the elements in the same order they were inserted.</p>
</li>
<li><p><code>TreeSet</code>: Elements are inserted based on their natural order. Alternatively, you can control the insertion order by specifying a custom comparator.</p>
</li>
</ul>
</li>
<li><p><strong>Synchronization</strong>: A <code>Set</code> is not synchronized, meaning you might encounter concurrency issues, like race conditions, which can affect data integrity if two or more threads try to access a <code>Set</code> object simultaneously</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>Set</code> interface: <code>add(E element)</code>, <code>remove(Object o)</code>, <code>contains(Object o)</code>, and <code>size()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.HashSet;
 <span class="hljs-keyword">import</span> java.util.Set;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SetExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a set</span>
         Set&lt;String&gt; set = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();

         <span class="hljs-comment">// Add elements to the set</span>
         set.add(<span class="hljs-string">"Apple"</span>);
         set.add(<span class="hljs-string">"Banana"</span>);
         set.add(<span class="hljs-string">"Cherry"</span>);

         <span class="hljs-comment">// Remove an element from the set</span>
         set.remove(<span class="hljs-string">"Banana"</span>);

         <span class="hljs-comment">// Check if the set contains an element</span>
         <span class="hljs-keyword">boolean</span> containsApple = set.contains(<span class="hljs-string">"Apple"</span>);
         System.out.println(<span class="hljs-string">"Contains Apple: "</span> + containsApple);

         <span class="hljs-comment">// Get the size of the set</span>
         <span class="hljs-keyword">int</span> size = set.size();
         System.out.println(<span class="hljs-string">"Size of the set: "</span> + size);
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>HashSet</code>, <code>LinkedHashSet</code>, <code>TreeSet</code></p>
</li>
<li><p><strong>Performance</strong>: <code>Set</code> implementations offer fast performance for basic operations, except for a <code>TreeSet</code>, where the performance can be relatively slower because the internal data structure involves sorting the elements during these operations.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>HashSet</strong></td><td><strong>LinkedHashSet</strong></td><td><strong>TreeSet</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Deletion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Retrieval</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
</tbody>
</table>
</div><h3 id="heading-queues">Queues</h3>
<p>A <code>Queue</code> is a linear collection of elements used to hold multiple items before processing, usually following the FIFO (first-in-first-out) order. This means elements are added at one end and removed from the other, so the first element added to the queue is the first one removed.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: The internal workings of a <code>Queue</code> can differ based on its specific implementation.</p>
<ul>
<li><p><code>LinkedList</code> – uses a doubly-linked list to store elements, which means you can traverse both forward and backward, allowing for flexible operations.</p>
</li>
<li><p><code>PriorityQueue</code> – is internally backed by a binary heap, which is very efficient for retrieval operations.</p>
</li>
<li><p><code>ArrayDeque</code> – is implemented using an array that expands or shrinks as elements are added or removed. Here, elements can be added or removed from both ends of the queue.</p>
</li>
</ul>
</li>
<li><p><strong>Duplicates</strong>: In a <code>Queue</code>, duplicate elements are permitted, allowing multiple instances of the same value to be inserted</p>
</li>
<li><p><strong>Null</strong>: You cannot insert a null value into a <code>Queue</code> because, by design, some methods of a <code>Queue</code> return null to indicate that it is empty. To avoid confusion, null values are not allowed.</p>
</li>
<li><p><strong>Ordering</strong>: Elements are inserted based on their natural order. Alternatively, you can control the insertion order by specifying a custom comparator.</p>
</li>
<li><p><strong>Synchronization</strong>: A <code>Queue</code> is not synchronized by default. But, you can use a <code>ConcurrentLinkedQueue</code> or a <code>BlockingQueue</code> implementation for achieving thread safety.</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>Queue</code> interface: <code>add(E element)</code>, <code>offer(E element)</code>, <code>poll()</code>, and <code>peek()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.LinkedList;
 <span class="hljs-keyword">import</span> java.util.Queue;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QueueExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a queue using LinkedList</span>
         Queue&lt;String&gt; queue = <span class="hljs-keyword">new</span> LinkedList&lt;&gt;();

         <span class="hljs-comment">// Use add method to insert elements, throws exception if insertion fails</span>
         queue.add(<span class="hljs-string">"Element1"</span>);
         queue.add(<span class="hljs-string">"Element2"</span>);
         queue.add(<span class="hljs-string">"Element3"</span>);

         <span class="hljs-comment">// Use offer method to insert elements, returns false if insertion fails</span>
         queue.offer(<span class="hljs-string">"Element4"</span>);

         <span class="hljs-comment">// Display queue</span>
         System.out.println(<span class="hljs-string">"Queue: "</span> + queue);

         <span class="hljs-comment">// Peek at the first element (does not remove it)</span>
         String firstElement = queue.peek();
         System.out.println(<span class="hljs-string">"Peek: "</span> + firstElement); <span class="hljs-comment">// outputs "Element1"</span>

         <span class="hljs-comment">// Poll the first element (retrieves and removes it)</span>
         String polledElement = queue.poll();
         System.out.println(<span class="hljs-string">"Poll: "</span> + polledElement); <span class="hljs-comment">// outputs "Element1"</span>

         <span class="hljs-comment">// Display queue after poll</span>
         System.out.println(<span class="hljs-string">"Queue after poll: "</span> + queue);
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>LinkedList</code>, <code>PriorityQueue</code>, <code>ArrayDeque</code></p>
</li>
<li><p><strong>Performance</strong>: Implementations like <code>LinkedList</code> and <code>ArrayDeque</code> are usually quick for adding and removing items. The <code>PriorityQueue</code> is a bit slower because it inserts items based on the set priority order.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>LinkedList</strong></td><td><strong>PriorityQueue</strong></td><td><strong>ArrayDeque</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast at the beginning or middle - O(1), slow at the end - O(n)</td><td>Slower - O(log n)</td><td>Fast - O(1), Slow - O(n), if it involves resizing of the internal array</td></tr>
<tr>
<td>Deletion</td><td>Fast - O(1) if position is known</td><td>Slower - O(log n)</td><td>Fast - O(1), Slow - O(n), if it involves resizing of the internal array</td></tr>
<tr>
<td>Retrieval</td><td>Slow - O(n) for random access, as it involves traversing</td><td>Fast - O(1)</td><td>Fast - O(1)</td></tr>
</tbody>
</table>
</div><h3 id="heading-maps">Maps</h3>
<p>A <code>Map</code> represents a collection of key-value pairs, with each key mapping to a single value. Although <code>Map</code> is part of the Java Collection framework, it does not extend the <code>java.util.Collection</code> interface.</p>
<ol>
<li><p><strong>Internal mechanism</strong>: A <code>Map</code> works internally using a <code>HashTable</code> based on the concept of hashing. I have written a detailed <a target="_blank" href="https://www.freecodecamp.org/news/how-java-hashmaps-work-internal-mechanics-explained">article</a> on this topic, so give it a read for a deeper understanding.</p>
</li>
<li><p><strong>Duplicates</strong>: A <code>Map</code> stores data as key-value pairs. Here, each key is unique, so duplicate keys are not allowed. But duplicate values are permitted.</p>
</li>
<li><p><strong>Null</strong>: Since duplicate keys are not allowed, a <code>Map</code> can have only one null key. As duplicate values are permitted, it can have multiple null values. In the <code>TreeMap</code> implementation, keys cannot be null because it sorts the elements based on the keys. However, null values are allowed.</p>
</li>
<li><p><strong>Ordering</strong>: Insertion order of a <code>Map</code> varies on the implementation:</p>
<ul>
<li><p><code>HashMap</code> – the insertion order is not guaranteed as they are determined based on the concept of hashing.</p>
</li>
<li><p><code>LinkedHashMap</code> – the insertion order is preserved and you can retrieve the elements back in the same order that they were added into the collection.</p>
</li>
<li><p><code>TreeMap</code> – Elements are inserted based on their natural order. Alternatively, you can control the insertion order by specifying a custom comparator.</p>
</li>
</ul>
</li>
<li><p><strong>Synchronization</strong>: A <code>Map</code> is not synchronized by default. But you can use <code>Collections.synchronizedMap()</code> or <code>ConcurrentHashMap</code> implementations for achieving thread safety.</p>
</li>
<li><p><strong>Key methods</strong>: Here are some key methods of a <code>Map</code> interface: <code>put(K key, V value)</code>, <code>get(Object key)</code>, <code>remove(Object key)</code>, <code>containsKey(Object key)</code>, and <code>keySet()</code>. Let's look at how to use these methods with an example program.</p>
<pre><code class="lang-java"> <span class="hljs-keyword">import</span> java.util.HashMap;
 <span class="hljs-keyword">import</span> java.util.Map;
 <span class="hljs-keyword">import</span> java.util.Set;

 <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MapMethodsExample</span> </span>{
     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
         <span class="hljs-comment">// Create a new HashMap</span>
         Map&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();

         <span class="hljs-comment">// put(K key, V value) - Inserts key-value pairs into the map</span>
         map.put(<span class="hljs-string">"Apple"</span>, <span class="hljs-number">1</span>);
         map.put(<span class="hljs-string">"Banana"</span>, <span class="hljs-number">2</span>);
         map.put(<span class="hljs-string">"Orange"</span>, <span class="hljs-number">3</span>);

         <span class="hljs-comment">// get(Object key) - Returns the value associated with the key</span>
         Integer value = map.get(<span class="hljs-string">"Banana"</span>);
         System.out.println(<span class="hljs-string">"Value for 'Banana': "</span> + value);

         <span class="hljs-comment">// remove(Object key) - Removes the key-value pair for the specified key</span>
         map.remove(<span class="hljs-string">"Orange"</span>);

         <span class="hljs-comment">// containsKey(Object key) - Checks if the map contains the specified key</span>
         <span class="hljs-keyword">boolean</span> hasApple = map.containsKey(<span class="hljs-string">"Apple"</span>);
         System.out.println(<span class="hljs-string">"Contains 'Apple': "</span> + hasApple);

         <span class="hljs-comment">// keySet() - Returns a set view of the keys contained in the map</span>
         Set&lt;String&gt; keys = map.keySet();
         System.out.println(<span class="hljs-string">"Keys in map: "</span> + keys);
     }
 }
</code></pre>
</li>
<li><p><strong>Common implementations</strong>: <code>HashMap</code>, <code>LinkedHashMap</code>, <code>TreeMap</code>, <code>Hashtable</code>, <code>ConcurrentHashMap</code></p>
</li>
<li><p><strong>Performance</strong>: <code>HashMap</code> implementation is widely used mainly due to its efficient performance characteristics depicted in the below table.</p>
</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Operation</strong></td><td><strong>HashMap</strong></td><td><strong>LinkedHashMap</strong></td><td><strong>TreeMap</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Insertion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Deletion</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
<tr>
<td>Retrieval</td><td>Fast - O(1)</td><td>Fast - O(1)</td><td>Slower - O(log n)</td></tr>
</tbody>
</table>
</div><h2 id="heading-collections-utility-class">Collections Utility Class</h2>
<p>As highlighted at the beginning of this article, the <code>Collections</code> utility class has several useful static methods that let you perform commonly used operations on the elements of a collection. These methods help you reduce the boilerplate code in your application and lets you focus on the business logic.</p>
<p>Here are some key features and methods, along with what they do, listed briefly:</p>
<ol>
<li><p><strong>Sorting:</strong> <code>Collections.sort(List&lt;T&gt;)</code> – this method is used to sort the elements of a list in ascending order.</p>
</li>
<li><p><strong>Searching:</strong> <code>Collections.binarySearch(List&lt;T&gt;, key)</code> – this method is used to search for a specific element in a sorted list and return its index.</p>
</li>
<li><p><strong>Reverse order:</strong> <code>Collections.reverse(List&lt;T&gt;)</code> – this method is used to reverse the order of elements in a list.</p>
</li>
<li><p><strong>Min/Max Operations:</strong> <code>Collections.min(Collection&lt;T&gt;)</code> and <code>Collections.max(Collection&lt;T&gt;)</code> – these methods are used to find the minimum and maximum elements in a collection, respectively.</p>
</li>
<li><p><strong>Synchronization:</strong> <code>Collections.synchronizedList(List&lt;T&gt;)</code> – this method is used to make a list thread-safe by synchronizing it.</p>
</li>
<li><p><strong>Unmodifiable Collections:</strong> <code>Collections.unmodifiableList(List&lt;T&gt;)</code> – this method is used to create a read-only view of a list, preventing modifications.</p>
</li>
</ol>
<p>Here's a sample Java program that demonstrates various functionalities of the <code>Collections</code> utility class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CollectionsExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Integer&gt; numbers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        numbers.add(<span class="hljs-number">5</span>);
        numbers.add(<span class="hljs-number">3</span>);
        numbers.add(<span class="hljs-number">8</span>);
        numbers.add(<span class="hljs-number">1</span>);

        <span class="hljs-comment">// Sorting</span>
        Collections.sort(numbers);
        System.out.println(<span class="hljs-string">"Sorted List: "</span> + numbers);

        <span class="hljs-comment">// Searching</span>
        <span class="hljs-keyword">int</span> index = Collections.binarySearch(numbers, <span class="hljs-number">3</span>);
        System.out.println(<span class="hljs-string">"Index of 3: "</span> + index);

        <span class="hljs-comment">// Reverse Order</span>
        Collections.reverse(numbers);
        System.out.println(<span class="hljs-string">"Reversed List: "</span> + numbers);

        <span class="hljs-comment">// Min/Max Operations</span>
        <span class="hljs-keyword">int</span> min = Collections.min(numbers);
        <span class="hljs-keyword">int</span> max = Collections.max(numbers);
        System.out.println(<span class="hljs-string">"Min: "</span> + min + <span class="hljs-string">", Max: "</span> + max);

        <span class="hljs-comment">// Synchronization</span>
        List&lt;Integer&gt; synchronizedList = Collections.synchronizedList(numbers);
        System.out.println(<span class="hljs-string">"Synchronized List: "</span> + synchronizedList);

        <span class="hljs-comment">// Unmodifiable Collections</span>
        List&lt;Integer&gt; unmodifiableList = Collections.unmodifiableList(numbers);
        System.out.println(<span class="hljs-string">"Unmodifiable List: "</span> + unmodifiableList);
    }
}
</code></pre>
<p>This program demonstrates sorting, searching, reversing, finding minimum and maximum values, synchronizing, and creating an unmodifiable list using the <code>Collections</code> utility class.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you’ve learned about the Java Collections Framework and how it helps manage groups of objects in Java applications. We explored various collection types like Lists, Sets, Queues, and Maps and gained insight into some of the key characteristics and how each of these types supports them.</p>
<p>You learned about performance, synchronization, and key methods, gaining valuable insights into choosing the right data structures for your needs.</p>
<p>By understanding these concepts, you can fully utilize the Java Collections Framework, allowing you to write more efficient code and build robust applications.</p>
<p>If you found this article interesting, feel free to check out my other articles on <a target="_blank" href="https://www.freecodecamp.org/news/author/anjanbaradwaj/">freeCodeCamp</a> and connect with me on <a target="_blank" href="https://www.linkedin.com/in/abaradwaj/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Design Patterns in Java with Spring Boot – Explained with Code Examples ]]>
                </title>
                <description>
                    <![CDATA[ As software projects grow, it becomes increasingly important to keep your code organized, maintainable, and scalable. This is where design patterns come into play. Design patterns provide proven, reusable solutions to common software design challenge... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-design-patterns-in-java-with-spring-boot/</link>
                <guid isPermaLink="false">673616b2ea38d82d84002cda</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Birkaran Sachdev ]]>
                </dc:creator>
                <pubDate>Thu, 14 Nov 2024 15:26:42 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1td5Iq5IvNc/upload/adaeb0229ea4ed1cd3c985d8eb92d23e.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As software projects grow, it becomes increasingly important to keep your code organized, maintainable, and scalable. This is where design patterns come into play. Design patterns provide proven, reusable solutions to common software design challenges, making your code more efficient and easier to manage.</p>
<p>In this guide, we'll dive deep into some of the most popular design patterns and show you how to implement them in Spring Boot. By the end, you'll not only understand these patterns conceptually but also be able to apply them in your own projects with confidence.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-introduction-to-design-patterns">Introduction to Design Patterns</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-your-spring-boot-project">How to Set Up Your Spring Boot Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-singleton-pattern">What is the Singleton Pattern?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-factory-pattern">What is the Factory Pattern?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-strategy-pattern">What is the Strategy Pattern?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-the-observer-pattern">What is the Observer Pattern?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-spring-boots-dependency-injection">How to Use Spring Boot’s Dependency Injection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-and-optimization-tips">Best Practices and Optimization Tips</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion-and-key-takeaways">Conclusion and Key Takeaways</a></p>
</li>
</ul>
<h2 id="heading-introduction-to-design-patterns">Introduction to Design Patterns</h2>
<p>Design patterns are reusable solutions to common software design problems. Think of them as best practices distilled into templates that can be applied to solve specific challenges in your code. They are not specific to any language, but they can be particularly powerful in Java due to its object-oriented nature.</p>
<p>In this guide, we'll cover:</p>
<ul>
<li><p><strong>Singleton Pattern</strong>: Ensuring a class has only one instance.</p>
</li>
<li><p><strong>Factory Pattern</strong>: Creating objects without specifying the exact class.</p>
</li>
<li><p><strong>Strategy Pattern</strong>: Allowing algorithms to be selected at runtime.</p>
</li>
<li><p><strong>Observer Pattern</strong>: Setting up a publish-subscribe relationship.</p>
</li>
</ul>
<p>We'll not only cover how these patterns work but also explore how they can be applied in Spring Boot for real-world applications.</p>
<h2 id="heading-how-to-set-up-your-spring-boot-project">How to Set Up Your Spring Boot Project</h2>
<p>Before we dive into the patterns, let’s set up a Spring Boot project:</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Make sure you have:</p>
<ul>
<li><p>Java 11+</p>
</li>
<li><p>Maven</p>
</li>
<li><p>Spring Boot CLI (optional)</p>
</li>
<li><p>Postman or curl (for testing)</p>
</li>
</ul>
<h3 id="heading-project-initialization">Project Initialization</h3>
<p>You can quickly create a Spring Boot project using Spring Initializr:</p>
<pre><code class="lang-bash">curl https://start.spring.io/starter.zip \
-d dependencies=web \
-d name=DesignPatternsDemo \
-d javaVersion=11 -o design-patterns-demo.zip
unzip design-patterns-demo.zip
<span class="hljs-built_in">cd</span> design-patterns-demo
</code></pre>
<h2 id="heading-what-is-the-singleton-pattern">What is the Singleton Pattern?</h2>
<p>The Singleton pattern ensures that a class has only one instance and provides a global access point to it. This pattern is commonly used for services like logging, configuration management, or database connections.</p>
<h3 id="heading-how-to-implement-the-singleton-pattern-in-spring-boot">How to Implement the Singleton Pattern in Spring Boot</h3>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Spring_Framework#:~:text=Creating%20and%20managing%20beans">Spring Boot beans</a> are singletons by default, meaning that Spring automatically manages the lifecycle of these beans to ensure only one instance exists. However, it's important to understand how the Singleton pattern works under the hood, especially when you're not using Spring-managed beans or need more control over instance management.</p>
<p>Let’s walk through a manual implementation of the Singleton pattern to demonstrate how you can control the creation of a single instance within your application.</p>
<h3 id="heading-step-1-create-a-loggerservice-class">Step 1: Create a <code>LoggerService</code> Class</h3>
<p>In this example, we’ll create a simple logging service using the Singleton pattern. The goal is to ensure that all parts of the application use the same logging instance.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoggerService</span> </span>{
    <span class="hljs-comment">// The static variable to hold the single instance</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> LoggerService instance;

    <span class="hljs-comment">// Private constructor to prevent instantiation from outside</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">LoggerService</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// This constructor is intentionally empty to prevent other classes from creating instances</span>
    }

    <span class="hljs-comment">// Public method to provide access to the single instance</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">synchronized</span> LoggerService <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
            instance = <span class="hljs-keyword">new</span> LoggerService();
        }
        <span class="hljs-keyword">return</span> instance;
    }

    <span class="hljs-comment">// Example logging method</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">log</span><span class="hljs-params">(String message)</span> </span>{
        System.out.println(<span class="hljs-string">"[LOG] "</span> + message);
    }
}
</code></pre>
<ul>
<li><p><strong>Static Variable</strong> (<code>instance</code>): This holds the single instance of <code>LoggerService</code>.</p>
</li>
<li><p><strong>Private Constructor</strong>: The constructor is marked private to prevent other classes from creating new instances directly.</p>
</li>
<li><p><strong>Synchronized</strong> <code>getInstance()</code> Method: The method is synchronized to make it thread-safe, ensuring that only one instance is created even if multiple threads try to access it simultaneously.</p>
</li>
<li><p><strong>Lazy Initialization</strong>: The instance is created only when it's first requested (<code>lazy initialization</code>), which is efficient in terms of memory usage.</p>
</li>
</ul>
<p><strong>Real-World Usage</strong>: This pattern is commonly used for shared resources, such as logging, configuration settings, or managing database connections, where you want to control access and ensure that only one instance is used throughout your application.</p>
<h3 id="heading-step-2-use-the-singleton-in-a-spring-boot-controller">Step 2: Use the Singleton in a Spring Boot Controller</h3>
<p>Now, let's see how we can use our <code>LoggerService</code> Singleton within a Spring Boot controller. This controller will expose an endpoint that logs a message whenever it's accessed.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.http.ResponseEntity;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.GetMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RestController;

<span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LogController</span> </span>{

    <span class="hljs-meta">@GetMapping("/log")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ResponseEntity&lt;String&gt; <span class="hljs-title">logMessage</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Accessing the Singleton instance of LoggerService</span>
        LoggerService logger = LoggerService.getInstance();
        logger.log(<span class="hljs-string">"This is a log message!"</span>);
        <span class="hljs-keyword">return</span> ResponseEntity.ok(<span class="hljs-string">"Message logged successfully"</span>);
    }
}
</code></pre>
<ul>
<li><p><strong>GET Endpoint</strong>: We’ve created a <code>/log</code> endpoint that, when accessed, logs a message using the <code>LoggerService</code>.</p>
</li>
<li><p><strong>Singleton Usage</strong>: Instead of creating a new instance of <code>LoggerService</code>, we call <code>getInstance()</code> to ensure we’re using the same instance every time.</p>
</li>
<li><p><strong>Response</strong>: After logging, the endpoint returns a response indicating success.</p>
</li>
</ul>
<h3 id="heading-step-3-testing-the-singleton-pattern">Step 3: Testing the Singleton Pattern</h3>
<p>Now, let's test this endpoint using Postman or your browser:</p>
<pre><code class="lang-bash">GET http://localhost:8080/<span class="hljs-built_in">log</span>
</code></pre>
<p><strong>Expected Output</strong>:</p>
<ul>
<li><p>Console log: <code>[LOG] This is a log message!</code></p>
</li>
<li><p>HTTP Response: <code>Message logged successfully</code></p>
</li>
</ul>
<p>You can call the endpoint multiple times, and you'll see that the same instance of <code>LoggerService</code> is used, as indicated by the consistent log output.</p>
<h3 id="heading-real-world-use-cases-for-the-singleton-pattern">Real-World Use Cases for the Singleton Pattern</h3>
<p>Here’s when you might want to use the Singleton pattern in real-world applications:</p>
<ol>
<li><p><strong>Configuration Management</strong>: Ensure that your application uses a consistent set of configuration settings, especially when those settings are loaded from files or databases.</p>
</li>
<li><p><strong>Database Connection Pools</strong>: Control access to a limited number of database connections, ensuring that the same pool is shared across the application.</p>
</li>
<li><p><strong>Caching</strong>: Maintain a single cache instance to avoid inconsistent data.</p>
</li>
<li><p><strong>Logging Services</strong>: As shown in this example, use a single logging service to centralize log outputs across different modules of your application.</p>
</li>
</ol>
<h3 id="heading-key-takeaways">Key Takeaways</h3>
<ul>
<li><p>The Singleton pattern is an easy way to ensure that only one instance of a class is created.</p>
</li>
<li><p>Thread safety is crucial if multiple threads are accessing the Singleton, which is why we used <code>synchronized</code> in our example.</p>
</li>
<li><p>Spring Boot beans are already singletons by default, but understanding how to implement it manually helps you gain more control when needed.</p>
</li>
</ul>
<p>This covers the implementation and usage of the Singleton pattern. Next, we’ll explore the Factory pattern to see how it can help streamline object creation.</p>
<h2 id="heading-what-is-the-factory-pattern">What is the Factory Pattern?</h2>
<p>The Factory pattern allows you to create objects without specifying the exact class. This pattern is useful when you have different types of objects that need to be instantiated based on some input.</p>
<h3 id="heading-how-to-implementing-a-factory-in-spring-boot">How to Implementing a Factory in Spring Boot</h3>
<p>The Factory pattern is incredibly useful when you need to create objects based on certain criteria but want to decouple the object creation process from your main application logic.</p>
<p>In this section, we’ll walk through building a <code>NotificationFactory</code> to send notifications via Email or SMS. This is especially useful if you anticipate adding more notification types in the future, such as push notifications or in-app alerts, without changing your existing code.</p>
<h3 id="heading-step-1-create-the-notification-interface">Step 1: Create the <code>Notification</code> Interface</h3>
<p>The first step is to define a common interface that all notification types will implement. This ensures that each type of notification (Email, SMS, and so on) will have a consistent <code>send()</code> method.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Notification</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">send</span><span class="hljs-params">(String message)</span></span>;
}
</code></pre>
<ul>
<li><p><strong>Purpose</strong>: The <code>Notification</code> interface defines the contract for sending notifications. Any class that implements this interface must provide an implementation for the <code>send()</code> method.</p>
</li>
<li><p><strong>Scalability</strong>: By using an interface, you can easily extend your application in the future to include other types of notifications without modifying existing code.</p>
</li>
</ul>
<h3 id="heading-step-2-implement-emailnotification-and-smsnotification">Step 2: Implement <code>EmailNotification</code> and <code>SMSNotification</code></h3>
<p>Now, let's implement two concrete classes, one for sending emails and another for sending SMS messages.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailNotification</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Notification</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">send</span><span class="hljs-params">(String message)</span> </span>{
        System.out.println(<span class="hljs-string">"Sending Email: "</span> + message);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SMSNotification</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Notification</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">send</span><span class="hljs-params">(String message)</span> </span>{
        System.out.println(<span class="hljs-string">"Sending SMS: "</span> + message);
    }
}
</code></pre>
<h3 id="heading-step-3-create-a-notificationfactory">Step 3: Create a <code>NotificationFactory</code></h3>
<p>The <code>NotificationFactory</code> class is responsible for creating instances of <code>Notification</code> based on the specified type. This design ensures that the <code>NotificationController</code> doesn’t need to know about the details of object creation.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotificationFactory</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Notification <span class="hljs-title">createNotification</span><span class="hljs-params">(String type)</span> </span>{
        <span class="hljs-keyword">switch</span> (type.toUpperCase()) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">"EMAIL"</span>:
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> EmailNotification();
            <span class="hljs-keyword">case</span> <span class="hljs-string">"SMS"</span>:
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SMSNotification();
            <span class="hljs-keyword">default</span>:
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IllegalArgumentException(<span class="hljs-string">"Unknown notification type: "</span> + type);
        }
    }
}
</code></pre>
<p><strong>Factory Method</strong> (<code>createNotification()</code>):</p>
<ul>
<li><p>The factory method takes a string (<code>type</code>) as input and returns an instance of the corresponding notification class.</p>
</li>
<li><p><strong>Switch Statement</strong>: The switch statement selects the appropriate notification type based on the input.</p>
</li>
<li><p><strong>Error Handling</strong>: If the provided type is not recognized, it throws an <code>IllegalArgumentException</code>. This ensures that invalid types are caught early.</p>
</li>
</ul>
<p><strong>Why Use a Factory?</strong></p>
<ul>
<li><p><strong>Decoupling</strong>: The factory pattern decouples object creation from the business logic. This makes your code more modular and easier to maintain.</p>
</li>
<li><p><strong>Extensibility</strong>: If you want to add a new notification type, you only need to update the factory without changing the controller logic.</p>
</li>
</ul>
<h3 id="heading-step-4-use-the-factory-in-a-spring-boot-controller">Step 4: Use the Factory in a Spring Boot Controller</h3>
<p>Now, let’s put everything together by creating a Spring Boot controller that uses the <code>NotificationFactory</code> to send notifications based on the user’s request.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.http.ResponseEntity;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.GetMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RequestParam;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RestController;

<span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NotificationController</span> </span>{

    <span class="hljs-meta">@GetMapping("/notify")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ResponseEntity&lt;String&gt; <span class="hljs-title">notify</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam</span> String type, <span class="hljs-meta">@RequestParam</span> String message)</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Create the appropriate Notification object using the factory</span>
            Notification notification = NotificationFactory.createNotification(type);
            notification.send(message);
            <span class="hljs-keyword">return</span> ResponseEntity.ok(<span class="hljs-string">"Notification sent successfully!"</span>);
        } <span class="hljs-keyword">catch</span> (IllegalArgumentException e) {
            <span class="hljs-keyword">return</span> ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}
</code></pre>
<p><strong>GET Endpoint</strong> (<code>/notify</code>):</p>
<ul>
<li><p>The controller exposes a <code>/notify</code> endpoint that accepts two query parameters: <code>type</code> (either "EMAIL" or "SMS") and <code>message</code>.</p>
</li>
<li><p>It uses the <code>NotificationFactory</code> to create the appropriate notification type and sends the message.</p>
</li>
<li><p><strong>Error Handling</strong>: If an invalid notification type is provided, the controller catches the <code>IllegalArgumentException</code> and returns a <code>400 Bad Request</code> response.</p>
</li>
</ul>
<h3 id="heading-step-5-testing-the-factory-pattern">Step 5: Testing the Factory Pattern</h3>
<p>Let’s test the endpoint using Postman or a browser:</p>
<ol>
<li><p><strong>Send an Email Notification</strong>:</p>
<pre><code class="lang-bash"> GET http://localhost:8080/notify?<span class="hljs-built_in">type</span>=email&amp;message=Hello%20Email
</code></pre>
<p> <strong>Output</strong>:</p>
<pre><code class="lang-bash"> Sending Email: Hello Email
</code></pre>
</li>
<li><p><strong>Send an SMS Notification</strong>:</p>
<pre><code class="lang-bash"> GET http://localhost:8080/notify?<span class="hljs-built_in">type</span>=sms&amp;message=Hello%20SMS
</code></pre>
<p> <strong>Output</strong>:</p>
<pre><code class="lang-bash"> Sending SMS: Hello SMS
</code></pre>
</li>
<li><p><strong>Test with an Invalid Type</strong>:</p>
<pre><code class="lang-bash"> GET http://localhost:8080/notify?<span class="hljs-built_in">type</span>=unknown&amp;message=Test
</code></pre>
<p> <strong>Output</strong>:</p>
<pre><code class="lang-bash"> Bad Request: Unknown notification <span class="hljs-built_in">type</span>: unknown
</code></pre>
</li>
</ol>
<h3 id="heading-real-world-use-cases-for-the-factory-pattern">Real-World Use Cases for the Factory Pattern</h3>
<p>The Factory pattern is particularly useful in scenarios where:</p>
<ol>
<li><p><strong>Dynamic Object Creation</strong>: When you need to create objects based on user input, like sending different types of notifications, generating reports in various formats, or handling different payment methods.</p>
</li>
<li><p><strong>Decoupling Object Creation</strong>: By using a factory, you can keep your main business logic separate from object creation, making your code more maintainable.</p>
</li>
<li><p><strong>Scalability</strong>: Easily extend your application to support new types of notifications without modifying existing code. Simply add a new class that implements the <code>Notification</code> interface and update the factory.</p>
</li>
</ol>
<h2 id="heading-what-is-the-strategy-pattern">What is the Strategy Pattern?</h2>
<p>The Strategy pattern is perfect when you need to switch between multiple algorithms or behaviors dynamically. It allows you to define a family of algorithms, encapsulate each one within separate classes, and make them easily interchangeable at runtime. This is especially useful for selecting an algorithm based on specific conditions, keeping your code clean, modular, and flexible.</p>
<p><strong>Real-World Use Case</strong>: Imagine an e-commerce system that needs to support multiple payment options, like credit cards, PayPal, or bank transfers. By using the Strategy pattern, you can easily add or modify payment methods without altering existing code. This approach ensures that your application remains scalable and maintainable as you introduce new features or update existing ones.</p>
<p>We’ll demonstrate this pattern with a Spring Boot example that handles payments using either a credit card or PayPal strategy.</p>
<h3 id="heading-step-1-define-a-paymentstrategy-interface">Step 1: Define a <code>PaymentStrategy</code> Interface</h3>
<p>We start by creating a common interface that all payment strategies will implement:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span></span>;
}
</code></pre>
<p>The interface defines a contract for all payment methods, ensuring consistency across implementations.</p>
<h3 id="heading-step-2-implement-payment-strategies">Step 2: Implement Payment Strategies</h3>
<p>Create concrete classes for credit card and PayPal payments.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreditCardPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid $"</span> + amount + <span class="hljs-string">" with Credit Card"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PayPalPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid $"</span> + amount + <span class="hljs-string">" via PayPal"</span>);
    }
}
</code></pre>
<p>Each class implements the <code>pay()</code> method with its specific behavior.</p>
<h3 id="heading-step-3-use-the-strategy-in-a-controller">Step 3: Use the Strategy in a Controller</h3>
<p>Create a controller to dynamically select a payment strategy based on user input:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.http.ResponseEntity;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.GetMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RequestParam;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RestController;

<span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentController</span> </span>{

    <span class="hljs-meta">@GetMapping("/pay")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ResponseEntity&lt;String&gt; <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam</span> String method, <span class="hljs-meta">@RequestParam</span> <span class="hljs-keyword">double</span> amount)</span> </span>{
        PaymentStrategy strategy = selectPaymentStrategy(method);
        <span class="hljs-keyword">if</span> (strategy == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">return</span> ResponseEntity.badRequest().body(<span class="hljs-string">"Invalid payment method"</span>);
        }
        strategy.pay(amount);
        <span class="hljs-keyword">return</span> ResponseEntity.ok(<span class="hljs-string">"Payment processed successfully!"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> PaymentStrategy <span class="hljs-title">selectPaymentStrategy</span><span class="hljs-params">(String method)</span> </span>{
        <span class="hljs-keyword">switch</span> (method.toUpperCase()) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">"CREDIT"</span>: <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> CreditCardPayment();
            <span class="hljs-keyword">case</span> <span class="hljs-string">"PAYPAL"</span>: <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> PayPalPayment();
            <span class="hljs-keyword">default</span>: <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
    }
}
</code></pre>
<p>The endpoint accepts <code>method</code> and <code>amount</code> as query parameters and processes the payment using the appropriate strategy.</p>
<h3 id="heading-step-4-testing-the-endpoint">Step 4: Testing the Endpoint</h3>
<ol>
<li><p><strong>Credit Card Payment</strong>:</p>
<pre><code class="lang-bash"> GET http://localhost:8080/pay?method=credit&amp;amount=100
</code></pre>
<p> Output: <code>Paid $100.0 with Credit Card</code></p>
</li>
<li><p><strong>PayPal Payment</strong>:</p>
<pre><code class="lang-bash"> GET http://localhost:8080/pay?method=paypal&amp;amount=50
</code></pre>
<p> Output: <code>Paid $50.0 via PayPal</code></p>
</li>
<li><p><strong>Invalid Method</strong>:</p>
<pre><code class="lang-bash"> GET http://localhost:8080/pay?method=bitcoin&amp;amount=25
</code></pre>
<p> Output: <code>Invalid payment method</code></p>
</li>
</ol>
<h3 id="heading-use-cases-for-the-strategy-pattern">Use Cases for the Strategy Pattern</h3>
<ul>
<li><p><strong>Payment Processing</strong>: Dynamically switch between different payment gateways.</p>
</li>
<li><p><strong>Sorting Algorithms</strong>: Choose the best sorting method based on data size.</p>
</li>
<li><p><strong>File Exporting</strong>: Export reports in various formats (PDF, Excel, CSV).</p>
</li>
</ul>
<h3 id="heading-key-takeaways-1">Key Takeaways</h3>
<ul>
<li><p>The Strategy pattern keeps your code modular and follows the Open/Closed principle.</p>
</li>
<li><p>Adding new strategies is easy—just create a new class implementing the <code>PaymentStrategy</code> interface.</p>
</li>
<li><p>It’s ideal for scenarios where you need flexible algorithm selection at runtime.</p>
</li>
</ul>
<p>Next, we’ll explore the Observer pattern, perfect for handling event-driven architectures.</p>
<h2 id="heading-what-is-the-observer-pattern">What is the Observer Pattern?</h2>
<p>The Observer pattern is ideal when you have one object (the subject) that needs to notify multiple other objects (observers) about changes in its state. It’s perfect for event-driven systems where updates need to be pushed to various components without creating tight coupling between them. This pattern allows you to maintain a clean architecture, especially when different parts of your system need to react to changes independently.</p>
<p><strong>Real-World Use Case</strong>: This pattern is commonly used in systems that send notifications or alerts, such as chat applications or stock price trackers, where updates need to be pushed to users in real-time. By using the Observer pattern, you can add or remove notification types easily without altering the core logic.</p>
<p>We’ll demonstrate how to implement this pattern in Spring Boot by building a simple notification system where both Email and SMS notifications are sent whenever a user registers.</p>
<h3 id="heading-step-1-create-an-observer-interface">Step 1: Create an <code>Observer</code> Interface</h3>
<p>We begin by defining a common interface that all observers will implement:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Observer</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(String event)</span></span>;
}
</code></pre>
<p>The interface establishes a contract where all observers must implement the <code>update()</code> method, which will be triggered whenever the subject changes.</p>
<h3 id="heading-step-2-implement-emailobserver-and-smsobserver">Step 2: Implement <code>EmailObserver</code> and <code>SMSObserver</code></h3>
<p>Next, we create two concrete implementations of the <code>Observer</code> interface to handle email and SMS notifications.</p>
<h4 id="heading-emailobserver-class"><code>EmailObserver</code> Class</h4>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EmailObserver</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Observer</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(String event)</span> </span>{
        System.out.println(<span class="hljs-string">"Email sent for event: "</span> + event);
    }
}
</code></pre>
<p>The <code>EmailObserver</code> handles sending email notifications whenever it's notified of an event.</p>
<h4 id="heading-smsobserver-class"><code>SMSObserver</code> Class</h4>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SMSObserver</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Observer</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">update</span><span class="hljs-params">(String event)</span> </span>{
        System.out.println(<span class="hljs-string">"SMS sent for event: "</span> + event);
    }
}
</code></pre>
<p>The <code>SMSObserver</code> handles sending SMS notifications whenever it's notified.</p>
<h3 id="heading-step-3-create-a-userservice-class-the-subject">Step 3: Create a <code>UserService</code> Class (The Subject)</h3>
<p>We’ll now create a <code>UserService</code> class that acts as the subject, notifying its registered observers whenever a user registers.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.stereotype.Service;
<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
    <span class="hljs-keyword">private</span> List&lt;Observer&gt; observers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

    <span class="hljs-comment">// Method to register observers</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">registerObserver</span><span class="hljs-params">(Observer observer)</span> </span>{
        observers.add(observer);
    }

    <span class="hljs-comment">// Method to notify all registered observers of an event</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">notifyObservers</span><span class="hljs-params">(String event)</span> </span>{
        <span class="hljs-keyword">for</span> (Observer observer : observers) {
            observer.update(event);
        }
    }

    <span class="hljs-comment">// Method to register a new user and notify observers</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">registerUser</span><span class="hljs-params">(String username)</span> </span>{
        System.out.println(<span class="hljs-string">"User registered: "</span> + username);
        notifyObservers(<span class="hljs-string">"User Registration"</span>);
    }
}
</code></pre>
<ul>
<li><p><strong>Observers List</strong>: Keeps track of all registered observers.</p>
</li>
<li><p><code>registerObserver()</code> Method: Adds new observers to the list.</p>
</li>
<li><p><code>notifyObservers()</code> Method: Notifies all registered observers when an event occurs.</p>
</li>
<li><p><code>registerUser()</code> Method: Registers a new user and triggers notifications to all observers.</p>
</li>
</ul>
<h3 id="heading-step-4-use-the-observer-pattern-in-a-controller">Step 4: Use the Observer Pattern in a Controller</h3>
<p>Finally, we’ll create a Spring Boot controller to expose an endpoint for user registration. This controller will register both <code>EmailObserver</code> and <code>SMSObserver</code> with the <code>UserService</code>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.http.ResponseEntity;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.*;

<span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping("/api")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserService userService;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserController</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">this</span>.userService = <span class="hljs-keyword">new</span> UserService();
        <span class="hljs-comment">// Register observers</span>
        userService.registerObserver(<span class="hljs-keyword">new</span> EmailObserver());
        userService.registerObserver(<span class="hljs-keyword">new</span> SMSObserver());
    }

    <span class="hljs-meta">@PostMapping("/register")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ResponseEntity&lt;String&gt; <span class="hljs-title">registerUser</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam</span> String username)</span> </span>{
        userService.registerUser(username);
        <span class="hljs-keyword">return</span> ResponseEntity.ok(<span class="hljs-string">"User registered and notifications sent!"</span>);
    }
}
</code></pre>
<ul>
<li><p><strong>Endpoint</strong> (<code>/register</code>): Accepts a <code>username</code> parameter and registers the user, triggering notifications to all observers.</p>
</li>
<li><p><strong>Observers</strong>: Both <code>EmailObserver</code> and <code>SMSObserver</code> are registered with <code>UserService</code>, so they are notified whenever a user registers.</p>
</li>
</ul>
<h3 id="heading-testing-the-observer-pattern">Testing the Observer Pattern</h3>
<p>Now, let’s test our implementation using Postman or a browser:</p>
<pre><code class="lang-bash">POST http://localhost:8080/api/register?username=JohnDoe
</code></pre>
<p><strong>Expected Output in Console</strong>:</p>
<pre><code class="lang-java">User registered: JohnDoe
Email sent <span class="hljs-keyword">for</span> event: User Registration
SMS sent <span class="hljs-keyword">for</span> event: User Registration
</code></pre>
<p>The system registers the user and notifies both the Email and SMS observers, showcasing the flexibility of the Observer pattern.</p>
<h3 id="heading-real-world-applications-of-the-observer-pattern">Real-World Applications of the Observer Pattern</h3>
<ol>
<li><p><strong>Notification Systems</strong>: Sending updates to users via different channels (email, SMS, push notifications) when certain events occur.</p>
</li>
<li><p><strong>Event-Driven Architectures</strong>: Notifying multiple subsystems when specific actions take place, such as user activities or system alerts.</p>
</li>
<li><p><strong>Data Streaming</strong>: Broadcasting data changes to various consumers in real-time (for example, live stock prices or social media feeds).</p>
</li>
</ol>
<h2 id="heading-how-to-use-spring-boots-dependency-injection">How to Use Spring Boot’s Dependency Injection</h2>
<p>So far, we’ve been manually creating objects to demonstrate design patterns. However, in real-world Spring Boot applications, Dependency Injection (DI) is the preferred way to manage object creation. DI allows Spring to automatically handle the instantiation and wiring of your classes, making your code more modular, testable, and maintainable.</p>
<p>Let’s refactor our Strategy pattern example to take advantage of Spring Boot's powerful DI capabilities. This will allow us to switch between payment strategies dynamically, using Spring’s annotations to manage dependencies.</p>
<h3 id="heading-updated-strategy-pattern-using-spring-boots-di">Updated Strategy Pattern Using Spring Boot's DI</h3>
<p>In our refactored example, we’ll leverage Spring’s annotations like <code>@Component</code>, <code>@Service</code>, and <code>@Autowired</code> to streamline the process of injecting dependencies.</p>
<h4 id="heading-step-1-annotate-payment-strategies-with-component">Step 1: Annotate Payment Strategies with <code>@Component</code></h4>
<p>First, we’ll mark our strategy implementations with the <code>@Component</code> annotation so that Spring can detect and manage them automatically.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Component("creditCardPayment")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreditCardPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid $"</span> + amount + <span class="hljs-string">" with Credit Card"</span>);
    }
}

<span class="hljs-meta">@Component("payPalPayment")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PayPalPayment</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid $"</span> + amount + <span class="hljs-string">" using PayPal"</span>);
    }
}
</code></pre>
<ul>
<li><p><code>@Component</code> Annotation: By adding <code>@Component</code>, we tell Spring to treat these classes as Spring-managed beans. The string value (<code>"creditCardPayment"</code> and <code>"payPalPayment"</code>) acts as the bean identifier.</p>
</li>
<li><p><strong>Flexibility</strong>: This setup allows us to switch between strategies by using the appropriate bean identifier.</p>
</li>
</ul>
<h4 id="heading-step-2-refactor-the-paymentservice-to-use-dependency-injection">Step 2: Refactor the <code>PaymentService</code> to Use Dependency Injection</h4>
<p>Next, let’s modify the <code>PaymentService</code> to inject a specific payment strategy using <code>@Autowired</code> and <code>@Qualifier</code>.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentService</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> PaymentStrategy paymentStrategy;

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PaymentService</span><span class="hljs-params">(<span class="hljs-meta">@Qualifier("payPalPayment")</span> PaymentStrategy paymentStrategy)</span> </span>{
        <span class="hljs-keyword">this</span>.paymentStrategy = paymentStrategy;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processPayment</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        paymentStrategy.pay(amount);
    }
}
</code></pre>
<ul>
<li><p><code>@Service</code> Annotation: Marks <code>PaymentService</code> as a Spring-managed service bean.</p>
</li>
<li><p><code>@Autowired</code>: Spring injects the required dependency automatically.</p>
</li>
<li><p><code>@Qualifier</code>: Specifies which implementation of <code>PaymentStrategy</code> to inject. In this example, we’re using <code>"payPalPayment"</code>.</p>
</li>
<li><p><strong>Ease of Configuration</strong>: By simply changing the <code>@Qualifier</code> value, you can switch the payment strategy without altering any business logic.</p>
</li>
</ul>
<h3 id="heading-step-3-using-the-refactored-service-in-a-controller">Step 3: Using the Refactored Service in a Controller</h3>
<p>To see the benefits of this refactoring, let’s update the controller to use our <code>PaymentService</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.*;

<span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping("/api")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentController</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> PaymentService paymentService;

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PaymentController</span><span class="hljs-params">(PaymentService paymentService)</span> </span>{
        <span class="hljs-keyword">this</span>.paymentService = paymentService;
    }

    <span class="hljs-meta">@GetMapping("/pay")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">makePayment</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam</span> <span class="hljs-keyword">double</span> amount)</span> </span>{
        paymentService.processPayment(amount);
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Payment processed using the current strategy!"</span>;
    }
}
</code></pre>
<ul>
<li><p><code>@Autowired</code>: The controller automatically receives the <code>PaymentService</code> with the injected payment strategy.</p>
</li>
<li><p><strong>GET Endpoint (</strong><code>/pay</code>): When accessed, it processes a payment using the currently configured strategy (PayPal in this example).</p>
</li>
</ul>
<h3 id="heading-testing-the-refactored-strategy-pattern-with-di">Testing the Refactored Strategy Pattern with DI</h3>
<p>Now, let’s test the new implementation using Postman or a browser:</p>
<pre><code class="lang-bash">GET http://localhost:8080/api/pay?amount=100
</code></pre>
<p><strong>Expected Output</strong>:</p>
<pre><code class="lang-bash">Paid <span class="hljs-variable">$100</span>.0 using PayPal
</code></pre>
<p>If you change the qualifier in <code>PaymentService</code> to <code>"creditCardPayment"</code>, the output will change accordingly:</p>
<pre><code class="lang-bash">Paid <span class="hljs-variable">$100</span>.0 with Credit Card
</code></pre>
<h3 id="heading-benefits-of-using-dependency-injection">Benefits of Using Dependency Injection</h3>
<ul>
<li><p><strong>Loose Coupling</strong>: The service and controller don’t need to know the details of how a payment is processed. They simply rely on Spring to inject the correct implementation.</p>
</li>
<li><p><strong>Modularity</strong>: You can easily add new payment methods (for example, <code>BankTransferPayment</code>, <code>CryptoPayment</code>) by creating new classes annotated with <code>@Component</code> and adjusting the <code>@Qualifier</code>.</p>
</li>
<li><p><strong>Configurability</strong>: By leveraging Spring Profiles, you can switch strategies based on the environment (for example, development vs. production).</p>
</li>
</ul>
<p><strong>Example</strong>: You can use <code>@Profile</code> to automatically inject different strategies based on the active profile:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Component</span>
<span class="hljs-meta">@Profile("dev")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DevPaymentStrategy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{ <span class="hljs-comment">/* ... */</span> }

<span class="hljs-meta">@Component</span>
<span class="hljs-meta">@Profile("prod")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProdPaymentStrategy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">PaymentStrategy</span> </span>{ <span class="hljs-comment">/* ... */</span> }
</code></pre>
<h3 id="heading-key-takeaways-2">Key Takeaways</h3>
<ul>
<li><p>By using Spring Boot’s DI, you can simplify object creation and improve the flexibility of your code.</p>
</li>
<li><p>The Strategy Pattern combined with DI allows you to easily switch between different strategies without changing your core business logic.</p>
</li>
<li><p>Using <code>@Qualifier</code> and Spring Profiles gives you the flexibility to configure your application based on different environments or requirements.</p>
</li>
</ul>
<p>This approach not only makes your code cleaner but also prepares it for more advanced configurations and scaling in the future. In the next section, we’ll explore Best Practices and Optimization Tips to take your Spring Boot applications to the next level.</p>
<h2 id="heading-best-practices-and-optimization-tips">Best Practices and Optimization Tips</h2>
<h3 id="heading-general-best-practices">General Best Practices</h3>
<ul>
<li><p><strong>Don’t overuse patterns</strong>: Use them only when necessary. Overengineering can make your code harder to maintain.</p>
</li>
<li><p><strong>Favor composition over inheritance</strong>: Patterns like Strategy and Observer are great examples of this principle.</p>
</li>
<li><p><strong>Keep your patterns flexible</strong>: Leverage interfaces to keep your code decoupled.</p>
</li>
</ul>
<h3 id="heading-performance-considerations">Performance Considerations</h3>
<ul>
<li><p><strong>Singleton Pattern</strong>: Ensure thread safety by using <code>synchronized</code> or the <code>Bill Pugh Singleton Design</code>.</p>
</li>
<li><p><strong>Factory Pattern</strong>: Cache objects if they are expensive to create.</p>
</li>
<li><p><strong>Observer Pattern</strong>: Use asynchronous processing if you have many observers to prevent blocking.</p>
</li>
</ul>
<h3 id="heading-advanced-topics">Advanced Topics</h3>
<ul>
<li><p>Using <strong>Reflection</strong> with the Factory pattern for dynamic class loading.</p>
</li>
<li><p>Leveraging <strong>Spring Profiles</strong> to switch strategies based on the environment.</p>
</li>
<li><p>Adding <strong>Swagger Documentation</strong> for your API endpoints.</p>
</li>
</ul>
<h2 id="heading-conclusion-and-key-takeaways">Conclusion and Key Takeaways</h2>
<p>In this tutorial, we explored some of the most powerful design patterns—Singleton, Factory, Strategy, and Observer—and demonstrated how to implement them in Spring Boot. Let’s briefly summarize each pattern and highlight what it’s best suited for:</p>
<p><strong>Singleton Pattern</strong>:</p>
<ul>
<li><p><strong>Summary</strong>: Ensures that a class has only one instance and provides a global access point to it.</p>
</li>
<li><p><strong>Best For</strong>: Managing shared resources like configuration settings, database connections, or logging services. It’s ideal when you want to control access to a shared instance across your entire application.</p>
</li>
</ul>
<p><strong>Factory Pattern</strong>:</p>
<ul>
<li><p><strong>Summary</strong>: Provides a way to create objects without specifying the exact class to be instantiated. This pattern decouples object creation from the business logic.</p>
</li>
<li><p><strong>Best For</strong>: Scenarios where you need to create different types of objects based on input conditions, such as sending notifications via email, SMS, or push notifications. It’s great for making your code more modular and extensible.</p>
</li>
</ul>
<p><strong>Strategy Pattern</strong>:</p>
<ul>
<li><p><strong>Summary</strong>: Allows you to define a family of algorithms, encapsulate each one, and make them interchangeable. This pattern helps you choose an algorithm at runtime.</p>
</li>
<li><p><strong>Best For</strong>: When you need to switch between different behaviors or algorithms dynamically, such as processing various payment methods in an e-commerce application. It keeps your code flexible and adheres to the Open/Closed Principle.</p>
</li>
</ul>
<p><strong>Observer Pattern</strong>:</p>
<ul>
<li><p><strong>Summary</strong>: Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified automatically.</p>
</li>
<li><p><strong>Best For</strong>: Event-driven systems like notification services, real-time updates in chat apps, or systems that need to react to changes in data. It’s ideal for decoupling components and making your system more scalable.</p>
</li>
</ul>
<h3 id="heading-whats-next">What’s Next?</h3>
<p>Now that you’ve learned these essential design patterns, try integrating them into your existing projects to see how they can improve your code structure and scalability. Here are a few suggestions for further exploration:</p>
<ul>
<li><p><strong>Experiment</strong>: Try implementing other design patterns like <strong>Decorator</strong>, <strong>Proxy</strong>, and <strong>Builder</strong> to expand your toolkit.</p>
</li>
<li><p><strong>Practice</strong>: Use these patterns to refactor existing projects and enhance their maintainability.</p>
</li>
<li><p><strong>Share</strong>: If you have any questions or want to share your experience, feel free to reach out!</p>
</li>
</ul>
<p>I hope this guide has helped you understand how to effectively use design patterns in Java. Keep experimenting, and happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Multi-Module Projects in Spring Boot for Scalable Microservices ]]>
                </title>
                <description>
                    <![CDATA[ As software applications grow in complexity, managing scalability, modularity, and clarity becomes essential. Spring Boot’s multi-module structure allows you to manage different parts of the application independently, which lets your team develop, te... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-multi-module-projects-in-spring-boot-for-scalable-microservices/</link>
                <guid isPermaLink="false">6733855c0e235bf7a79c5c4f</guid>
                
                    <category>
                        <![CDATA[ Spring Boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ maven ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Backend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Birkaran Sachdev ]]>
                </dc:creator>
                <pubDate>Tue, 12 Nov 2024 16:42:04 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/uyfohHiTxho/upload/716c6610c336976df67b833912170336.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As software applications grow in complexity, managing scalability, modularity, and clarity becomes essential.</p>
<p>Spring Boot’s multi-module structure allows you to manage different parts of the application independently, which lets your team develop, test, and deploy components separately. This structure keeps code organized and modular, making it useful for both microservices and large monolithic systems.</p>
<p>In this tutorial, you’ll build a multi-module Spring Boot project, with each module dedicated to a specific responsibility. You’ll learn how to set up modules, configure inter-module communication, handle errors, implement JWT-based security, and deploy using Docker.</p>
<p><strong>Prerequisites</strong>:</p>
<ul>
<li><p>Basic knowledge of Spring Boot and Maven.</p>
</li>
<li><p>Familiarity with Docker and CI/CD concepts (optional but helpful).</p>
</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-1-why-multi-module-projects">Why Multi-Module Projects?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-project-structure-and-architecture">Project Structure and Architecture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-how-to-set-up-the-parent-project">How to Set Up the Parent Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-how-to-create-the-modules">How to Create the Modules</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-inter-module-communication">Inter-Module Communication</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-common-pitfalls-and-solutions">Common Pitfalls and Solutions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-7-testing-strategy">Testing Strategy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-8-error-handling-and-logging">Error Handling and Logging</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-9-security-and-jwt-integration">Security and JWT Integration</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-10-deployment-with-docker-and-cicd">Deployment with Docker and CI/CD</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-11-best-practices-and-advanced-use-cases">Best Practices and Advanced Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-12-conclusion-and-key-takeaways">Conclusion and Key Takeaways</a></p>
</li>
</ol>
<h2 id="heading-1-why-multi-module-projects">1. Why Multi-Module Projects?</h2>
<p>In single-module projects, components are often tightly coupled, making it difficult to scale and manage complex codebases. A multi-module structure offers several advantages:</p>
<ul>
<li><p><strong>Modularity</strong>: Each module is dedicated to a specific task, such as User Management or Inventory, simplifying management and troubleshooting.</p>
</li>
<li><p><strong>Team Scalability</strong>: Teams can work independently on different modules, minimizing conflicts and enhancing productivity.</p>
</li>
<li><p><strong>Flexible Deployment</strong>: Modules can be deployed or updated independently, which is particularly beneficial for microservices or large applications with numerous features.</p>
</li>
</ul>
<h3 id="heading-real-world-example"><strong>Real-World Example</strong></h3>
<p>Consider a large e-commerce application. Its architecture can be divided into distinct modules:</p>
<ul>
<li><p><strong>Customer Management</strong>: Responsible for handling customer profiles, preferences, and authentication.</p>
</li>
<li><p><strong>Product Management</strong>: Focuses on managing product details, stock, and pricing.</p>
</li>
<li><p><strong>Order Processing</strong>: Manages orders, payments, and order tracking.</p>
</li>
<li><p><strong>Inventory Management</strong>: Oversees stock levels and supplier orders.</p>
</li>
</ul>
<h3 id="heading-case-study-netflix"><strong>Case Study: Netflix</strong></h3>
<p>To illustrate these benefits, let's examine how Netflix employs a multi-module architecture.</p>
<p>Netflix is a leading example of a company that effectively uses this approach through its microservices architecture. Each microservice at Netflix is dedicated to a specific function, such as user authentication, content recommendations, or streaming services.</p>
<p>This modular structure enables Netflix to scale its operations efficiently, deploy updates independently, and maintain high availability and performance. By decoupling services, Netflix can manage millions of users and deliver content seamlessly worldwide, ensuring a robust and flexible system that supports its vast and dynamic platform.</p>
<p>This architecture not only enhances scalability but also improves fault isolation, allowing Netflix to innovate rapidly and respond effectively to user demands.</p>
<h2 id="heading-2-project-structure-and-architecture">2. Project Structure and Architecture</h2>
<p>Now let’s get back to our example project. Your multi-module Spring Boot project will use five key modules. Here’s the layout:</p>
<pre><code class="lang-plaintext">codespring-boot-multi-module/
 ├── common/               # Shared utilities and constants
 ├── domain/               # Domain entities
 ├── repository/           # Data access layer (DAL)
 ├── service/              # Business logic
 └── web/                  # Main Spring Boot application and controllers
</code></pre>
<p>Each module has a specific role:</p>
<ul>
<li><p><code>common</code>: Stores shared utilities, constants, and configuration files used across other modules.</p>
</li>
<li><p><code>domain</code>: Contains data models for your application.</p>
</li>
<li><p><code>repository</code>: Manages database operations.</p>
</li>
<li><p><code>service</code>: Encapsulates business logic.</p>
</li>
<li><p><code>web</code>: Defines REST API endpoints and serves as the application’s entry point.</p>
</li>
</ul>
<p>This structure aligns with <strong>separation of concerns</strong> principles, where each layer is independent and handles its own logic.</p>
<p>The diagram below illustrates the various modules:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730873719792/adfc3689-26ae-477a-9850-75070a777e5e.png" alt="Diagram showing a software architecture with five modules: Web, Service, Repository, Domain, and Common, connected by arrows indicating relationships." class="image--center mx-auto" width="1306" height="767" loading="lazy"></p>
<h2 id="heading-3-how-to-set-up-the-parent-project">3. How to Set Up the Parent Project</h2>
<h3 id="heading-step-1-create-the-root-project">Step 1: Create the Root Project</h3>
<p>Let’s run these commands to create the Maven parent project:</p>
<pre><code class="lang-bash">mvn archetype:generate -DgroupId=com.example -DartifactId=spring-boot-multi-module -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=<span class="hljs-literal">false</span>
<span class="hljs-built_in">cd</span> spring-boot-multi-module
</code></pre>
<h3 id="heading-step-2-configure-the-parent-pomxml">Step 2: Configure the Parent <code>pom.xml</code></h3>
<p>In the <code>pom.xml</code>, let’s define our dependencies and modules:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0"</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0 http://www.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.example<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-multi-module<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>1.0-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">packaging</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">packaging</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">modules</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>common<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>domain<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>repository<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>service<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">module</span>&gt;</span>web<span class="hljs-tag">&lt;/<span class="hljs-name">module</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">modules</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">java.version</span>&gt;</span>11<span class="hljs-tag">&lt;/<span class="hljs-name">java.version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">spring.boot.version</span>&gt;</span>2.5.4<span class="hljs-tag">&lt;/<span class="hljs-name">spring.boot.version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">dependencyManagement</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-dependencies<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>${spring.boot.version}<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">type</span>&gt;</span>pom<span class="hljs-tag">&lt;/<span class="hljs-name">type</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>import<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependencies</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">dependencyManagement</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">build</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">plugins</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span>
</code></pre>
<p>This <code>pom.xml</code> file centralizes dependencies and configurations, making it easier to manage shared settings across modules.</p>
<h2 id="heading-4-how-to-create-the-modules">4. How to Create the Modules</h2>
<h3 id="heading-common-module">Common Module</h3>
<p>Let’s create a <strong>common</strong> module to define shared utilities like date formatters. Create this module and add a sample utility class:</p>
<pre><code class="lang-bash">mvn archetype:generate -DgroupId=com.example.common -DartifactId=common -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=<span class="hljs-literal">false</span>
</code></pre>
<p><strong>Date Formatter Utility:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.common;

<span class="hljs-keyword">import</span> java.time.LocalDate;
<span class="hljs-keyword">import</span> java.time.format.DateTimeFormatter;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DateUtils</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">formatDate</span><span class="hljs-params">(LocalDate date)</span> </span>{
        <span class="hljs-keyword">return</span> date.format(DateTimeFormatter.ofPattern(<span class="hljs-string">"yyyy-MM-dd"</span>));
    }
}
</code></pre>
<h3 id="heading-domain-module">Domain Module</h3>
<p>In the <strong>domain</strong> module, you will define your data models.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.domain;

<span class="hljs-keyword">import</span> javax.persistence.Entity;
<span class="hljs-keyword">import</span> javax.persistence.Id;

<span class="hljs-meta">@Entity</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-meta">@Id</span>
    <span class="hljs-keyword">private</span> Long id;
    <span class="hljs-keyword">private</span> String name;

    <span class="hljs-comment">// Getters and Setters</span>
}
</code></pre>
<h3 id="heading-repository-module">Repository Module</h3>
<p>Let’s create the <strong>repository</strong> module to manage data access. Here’s a basic repository interface:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.repository;

<span class="hljs-keyword">import</span> com.example.domain.User;
<span class="hljs-keyword">import</span> org.springframework.data.jpa.repository.JpaRepository;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">User</span>, <span class="hljs-title">Long</span>&gt; </span>{}
</code></pre>
<h3 id="heading-service-module">Service Module</h3>
<p>Let’s create the <strong>service</strong> module to hold your business logic. Here’s an example service class:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.example.service;

<span class="hljs-keyword">import</span> com.example.domain.User;
<span class="hljs-keyword">import</span> com.example.repository.UserRepository;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

<span class="hljs-meta">@Service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserRepository userRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getUserById</span><span class="hljs-params">(Long id)</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.findById(id).orElse(<span class="hljs-keyword">null</span>);
    }
}
</code></pre>
<h3 id="heading-web-module">Web Module</h3>
<p>The <strong>web</strong> module serves as the REST API layer.</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserService userService;

    <span class="hljs-meta">@GetMapping("/users/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getUserById</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable</span> Long id)</span> </span>{
        <span class="hljs-keyword">return</span> userService.getUserById(id);
    }
}
</code></pre>
<h2 id="heading-5-inter-module-communication">5. Inter-Module Communication</h2>
<p>To avoid direct dependencies, you can use <strong>REST APIs</strong> or <strong>message brokers</strong> (like Kafka) for inter-module communication. This ensures loose coupling and allows each module to communicate independently.</p>
<p>The diagram below demonstrates how modules communicate with each other:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730874358819/89d7f058-d074-4b1d-bbb7-81a7bdcb868e.png" alt="Flowchart showing the interaction between modules in the software architecture: Web Module handles API endpoints and returns responses, Service Module executes business logic, Repository Module accesses data and returns processed data, and connects to a Database." class="image--center mx-auto" width="932" height="1263" loading="lazy"></p>
<p>The diagram illustrates how different system components communicate to handle requests efficiently.</p>
<p>The <strong>Web Module</strong> processes incoming API requests and forwards them to the <strong>Service Module</strong>, which contains the business logic. The <strong>Service Module</strong> then interacts with the <strong>Repository Module</strong> to fetch or update data in the <strong>Database</strong>. This layered approach ensures that each module operates independently, promoting flexibility and easier maintenance.</p>
<p><strong>Example Using Feign Client</strong>:</p>
<p>In the context of inter-module communication, using tools like <strong>Feign Clients</strong> is a powerful way to achieve loose coupling between services.</p>
<p>The Feign client allows one module to seamlessly communicate with another through REST API calls, without requiring direct dependencies. This approach fits perfectly within the layered architecture described earlier, where the <strong>Service Module</strong> can fetch data from other services or microservices using Feign clients, rather than directly accessing databases or hard-coding HTTP requests.</p>
<p>This not only simplifies the code but also improves scalability and maintainability by isolating service dependencies.</p>
<pre><code class="lang-java"><span class="hljs-meta">@FeignClient(name = "userServiceClient", url = "http://localhost:8081")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserServiceClient</span> </span>{
    <span class="hljs-meta">@GetMapping("/users/{id}")</span>
    <span class="hljs-function">User <span class="hljs-title">getUserById</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable("id")</span> Long id)</span></span>;
}
</code></pre>
<h2 id="heading-6-common-pitfalls-and-solutions">6. Common Pitfalls and Solutions</h2>
<p>When implementing a multi-module architecture, you may encounter several challenges. Here are some common pitfalls and their solutions:</p>
<ul>
<li><p><strong>Circular Dependencies</strong>: Modules may inadvertently depend on each other, creating a circular dependency that complicates builds and deployments.</p>
<ul>
<li><strong>Solution</strong>: Carefully design module interfaces and use dependency management tools to detect and resolve circular dependencies early in the development process.</li>
</ul>
</li>
<li><p><strong>Over-Engineering</strong>: There's a risk of creating too many modules, leading to unnecessary complexity.</p>
<ul>
<li><strong>Solution</strong>: Start with a minimal set of modules and only split further when there's a clear need, ensuring each module has a distinct responsibility.</li>
</ul>
</li>
<li><p><strong>Inconsistent Configurations</strong>: Managing configurations across multiple modules can lead to inconsistencies.</p>
<ul>
<li><strong>Solution</strong>: Use centralized configuration management tools, such as Spring Cloud Config, to maintain consistency across modules.</li>
</ul>
</li>
<li><p><strong>Communication Overhead</strong>: Inter-module communication can introduce latency and complexity.</p>
<ul>
<li><strong>Solution</strong>: Optimize communication by using efficient protocols and consider asynchronous messaging where appropriate to reduce latency.</li>
</ul>
</li>
<li><p><strong>Testing Complexity</strong>: Testing a multi-module project can be more complex due to the interactions between modules.</p>
<ul>
<li><strong>Solution</strong>: Implement a robust testing strategy that includes unit tests for individual modules and integration tests for inter-module interactions.</li>
</ul>
</li>
</ul>
<p>By being aware of these pitfalls and applying these solutions, you can effectively manage the complexities of a multi-module architecture and ensure a smooth development process.</p>
<h2 id="heading-7-testing-strategy-and-configuration">7. Testing Strategy and Configuration</h2>
<p>Testing each module independently and as a unit is critical in multi-module setups.</p>
<h3 id="heading-unit-tests">Unit Tests</h3>
<p>Here, we’ll use JUnit and Mockito for performing unit tests:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RunWith(MockitoJUnitRunner.class)</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserServiceTest</span> </span>{

    <span class="hljs-meta">@Mock</span>
    <span class="hljs-keyword">private</span> UserRepository userRepository;

    <span class="hljs-meta">@InjectMocks</span>
    <span class="hljs-keyword">private</span> UserService userService;

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testGetUserById</span><span class="hljs-params">()</span> </span>{
        User user = <span class="hljs-keyword">new</span> User();
        user.setId(<span class="hljs-number">1L</span>);
        user.setName(<span class="hljs-string">"John"</span>);

        Mockito.when(userRepository.findById(<span class="hljs-number">1L</span>)).thenReturn(Optional.of(user));

        User result = userService.getUserById(<span class="hljs-number">1L</span>);
        assertEquals(<span class="hljs-string">"John"</span>, result.getName());
    }
}
</code></pre>
<h3 id="heading-integration-tests">Integration Tests</h3>
<p>And we’ll use Testcontainers with an in-memory database for integration tests:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Testcontainers</span>
<span class="hljs-meta">@ExtendWith(SpringExtension.class)</span>
<span class="hljs-meta">@SpringBootTest</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserServiceIntegrationTest</span> </span>{

    <span class="hljs-meta">@Container</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> PostgreSQLContainer&lt;?&gt; postgresqlContainer = <span class="hljs-keyword">new</span> PostgreSQLContainer&lt;&gt;(<span class="hljs-string">"postgres:latest"</span>);

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> UserService userService;

    <span class="hljs-meta">@Test</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testFindById</span><span class="hljs-params">()</span> </span>{
        User user = userService.getUserById(<span class="hljs-number">1L</span>);
        assertNotNull(user);
    }
}
</code></pre>
<h2 id="heading-8-error-handling-and-logging">8. Error Handling and Logging</h2>
<p>Error handling and logging ensure a robust and debuggable application.</p>
<h3 id="heading-error-handling">Error Handling</h3>
<p>In this section, we'll explore how to handle errors gracefully in your Spring Boot application using a <strong>global exception handler</strong>. By using <code>@ControllerAdvice</code>, we'll set up a centralized way to catch and respond to errors, keeping our code clean and our responses consistent.</p>
<pre><code class="lang-java"><span class="hljs-meta">@ControllerAdvice</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GlobalExceptionHandler</span> </span>{

    <span class="hljs-meta">@ExceptionHandler(UserNotFoundException.class)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ResponseEntity&lt;String&gt; <span class="hljs-title">handleUserNotFoundException</span><span class="hljs-params">(UserNotFoundException ex)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ResponseEntity&lt;&gt;(<span class="hljs-string">"User not found"</span>, HttpStatus.NOT_FOUND);
    }
}
</code></pre>
<p>In the code example above, we define a <code>GlobalExceptionHandler</code> that catches any <code>UserNotFoundException</code> and returns a friendly message like "User not found" with a status of <code>404</code>. This way, you don’t have to handle this exception in every controller—you’ve got it covered in one place!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730874789550/feed75e6-f92c-4102-b3c3-a01f189f3cd7.png" alt="Flowchart depicting a sequence of interactions between a Client, Web Module, Global Error Handler, and Logger. The process involves handling requests, processing them, and managing exceptions. If an exception occurs, it is handled and logged, followed by an error response. If no exception occurs, a successful response is returned." class="image--center mx-auto" width="1617" height="1350" loading="lazy"></p>
<p>Now, let’s take a look at the diagram. Here’s how it all flows: when a client sends a request to our <strong>Web Module</strong>, if everything goes smoothly, you'll get a successful response. But if something goes wrong, like a user not being found, the error will be caught by our <strong>Global Error Handler</strong>. This handler logs the issue and returns a clean, structured response to the client.</p>
<p>This approach ensures that users get clear error messages while keeping your app’s internals hidden and secure.</p>
<h3 id="heading-logging">Logging</h3>
<p>Structured logging in each module improves traceability and debugging. You can use a centralized logging system like Logback and include correlation IDs to trace requests.</p>
<h2 id="heading-9-security-and-jwt-integration">9. Security and JWT Integration</h2>
<p>In this section, we’re going to set up <strong>JSON Web Tokens (JWT)</strong> to secure our endpoints and control access based on user roles. We'll configure this in the <code>SecurityConfig</code> class, which will help us enforce who can access what parts of our application.</p>
<pre><code class="lang-java"><span class="hljs-meta">@EnableWebSecurity</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecurityConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">WebSecurityConfigurerAdapter</span> </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        http.authorizeRequests()
            .antMatchers(<span class="hljs-string">"/admin/**"</span>).hasRole(<span class="hljs-string">"ADMIN"</span>)
            .antMatchers(<span class="hljs-string">"/user/**"</span>).hasAnyRole(<span class="hljs-string">"USER"</span>, <span class="hljs-string">"ADMIN"</span>)
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer().jwt();
    }
}
</code></pre>
<p>In the code example above, you can see how we’ve defined access rules:</p>
<ul>
<li><p>The <code>/admin/**</code> endpoints are restricted to users with the <code>ADMIN</code> role.</p>
</li>
<li><p>The <code>/user/**</code> endpoints can be accessed by users with either the <code>USER</code> or <code>ADMIN</code> roles.</p>
</li>
<li><p>Any other requests will require the user to be authenticated.</p>
</li>
</ul>
<p>Next, we set up our application to validate incoming tokens using <code>.oauth2ResourceServer().jwt();</code>. This ensures that only requests with a valid token can access our secured endpoints.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1730875088355/b0502e8e-88e4-4aab-bf52-81360892ffbb.png" alt="Diagram depicting a sequence of interactions among five components: Client, Web Module, Security Filter, Service, and Repository. Arrows represent steps for token authentication and accessing a service, including requests, validations, data fetching, and responses, with outcomes for both valid and invalid tokens." class="image--center mx-auto" width="2012" height="1531" loading="lazy"></p>
<p>Now, let’s walk through the diagram. When a client sends a request to access a resource, the <strong>Security Filter</strong> first checks if the provided JWT token is valid. If the token is valid, the request proceeds to the <strong>Service Module</strong> to fetch or process the data. If not, access is denied right away, and the client receives an error response.</p>
<p>This flow ensures that only authenticated users can access sensitive resources, keeping our application secure.</p>
<h2 id="heading-10-deployment-with-docker-and-cicd">10. Deployment with Docker and CI/CD</h2>
<p>In this section, we'll containerize each module using <strong>Docker</strong> to make our application easier to deploy and run consistently across different environments. We’ll also set up a <strong>CI/CD pipeline</strong> using GitHub Actions (but you can use Jenkins too if you prefer). Automating this process ensures that any changes you push are automatically built, tested, and deployed.</p>
<h3 id="heading-step-1-containerizing-with-docker">Step 1: Containerizing with Docker</h3>
<p>We start by creating a <strong>Dockerfile</strong> for the <strong>Web Module:</strong></p>
<pre><code class="lang-java">FROM openjdk:<span class="hljs-number">11</span>-jre-slim
COPY target/web-<span class="hljs-number">1.0</span>-SNAPSHOT.jar app.jar
ENTRYPOINT [<span class="hljs-string">"java"</span>, <span class="hljs-string">"-jar"</span>, <span class="hljs-string">"/app.jar"</span>]
</code></pre>
<p>Here, we’re using a lightweight version of Java 11 to keep our image size small. We copy the compiled <code>.jar</code> file into the container and set it up to run when the container starts.</p>
<h3 id="heading-step-2-using-docker-compose-for-multi-module-deployment">Step 2: Using Docker Compose for Multi-Module Deployment</h3>
<p>Now, we'll use a <strong>Docker Compose</strong> file to orchestrate multiple modules together:</p>
<pre><code class="lang-java">version: <span class="hljs-string">'3'</span>
services:
  web:
    build: ./web
    ports:
      - <span class="hljs-string">"8080:8080"</span>
  service:
    build: ./service
    ports:
      - <span class="hljs-string">"8081:8081"</span>
</code></pre>
<p>With this setup, we can run both the <strong>Web Module</strong> and the <strong>Service Module</strong> at the same time, making it easy to spin up the entire application with a single command. Each service is built separately from its own directory, and we expose the necessary ports to access them.</p>
<h3 id="heading-cicd-example-with-github-actions">CI/CD Example with GitHub Actions</h3>
<pre><code class="lang-java">name: CI Pipeline

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout<span class="hljs-meta">@v2</span>
    - name: Set up JDK <span class="hljs-number">11</span>
      uses: actions/setup-java<span class="hljs-meta">@v2</span>
      with:
        java-version: <span class="hljs-string">'11'</span>
    - name: Build with Maven
      run: mvn clean install
</code></pre>
<p>This pipeline automatically kicks in whenever you push new code or create a pull request. It checks out your code, sets up Java, and runs a Maven build to ensure everything is working correctly.</p>
<h2 id="heading-11-best-practices-and-advanced-use-cases">11. Best Practices and Advanced Use Cases</h2>
<p>The following best practices ensure maintainability and scalability.</p>
<h3 id="heading-best-practices">Best Practices</h3>
<ul>
<li><p><strong>Avoid Circular Dependencies</strong>: Ensure modules don’t have circular references to avoid build issues.</p>
</li>
<li><p><strong>Separate Concerns Clearly</strong>: Each module should focus on one responsibility.</p>
</li>
<li><p><strong>Centralized Configurations</strong>: Manage configurations centrally for consistent setups.</p>
</li>
</ul>
<h3 id="heading-advanced-use-cases">Advanced Use Cases</h3>
<ol>
<li><p><strong>Asynchronous Messaging with Kafka</strong>: Use Kafka for decoupled communication between services. Modules can publish and subscribe to events asynchronously.</p>
</li>
<li><p><strong>REST Client with Feign</strong>: Use Feign to call services within modules. Define a Feign client interface for communication.</p>
</li>
<li><p><strong>Caching for Performance</strong>: Use Spring Cache in the service module for optimizing data retrieval.</p>
</li>
</ol>
<h2 id="heading-conclusion-and-key-takeaways">Conclusion and Key Takeaways</h2>
<p>A multi-module Spring Boot project provides modularity, scalability, and ease of maintenance.</p>
<p>In this tutorial, you learned to set up modules, manage inter-module communication, handle errors, add security, and deploy with Docker.</p>
<p>Following best practices and using advanced techniques like messaging and caching will further optimize your multi-module architecture for production use.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement Fine-Grained Authorization in Java and SpringBoot ]]>
                </title>
                <description>
                    <![CDATA[ Securing your application goes beyond simply granting or denying access at the surface level. As a developer, you need to implement fine-grained authorization (FGA) to manage permissions at a more detailed, granular level. FGA allows you to set up de... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/fine-grained-authorization-in-java-and-springboot/</link>
                <guid isPermaLink="false">671a85db0db570158155ec00</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Developer Tools ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ankur Tyagi ]]>
                </dc:creator>
                <pubDate>Thu, 24 Oct 2024 17:37:31 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1729783227124/9725e8cf-553d-42c3-a823-5215e8d4d0e9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Securing your application goes beyond simply granting or denying access at the surface level. As a developer, you need to implement <code>fine-grained authorization</code> (FGA) to manage permissions at a more detailed, granular level.</p>
<p>FGA allows you to set up detailed access controls that specify who can do what and under which conditions.</p>
<p>In this tutorial, you will learn how to implement <code>fine-grained authorization</code> in Java and Spring Boot using <a target="_blank" href="https://permit.io/">Permit.io</a>.</p>
<p>Here is the <a target="_blank" href="https://github.com/tyaga001/java-spring-fine-grained-auth">source code</a> (remember to give it a star ⭐).</p>
<p>I hope you enjoyed my previous <a target="_blank" href="https://www.freecodecamp.org/news/how-i-built-a-custom-video-conferencing-app-with-stream-and-nextjs/">blog</a> about building a custom video conferencing app with Stream and Next.js. These blogs reflect my journey in creating DevTools Academy, a platform designed to help developers discover amazing developer tools.</p>
<p>This tutorial is another effort to introduce you to a super helpful developer tool that I recently explored.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents:</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-permit">What is Permit</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-fine-grained-authorization">What is Fine-Grained Authorization</a>?</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-role-based-access-control-rbac">Role-Based Access Control (RBAC)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-attribute-based-access-control-abac">Attribute-Based Access Control (ABAC)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-relationship-based-access-control-rebac">Relationship-Based Access Control (ReBAC)</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-fine-grained-authorization">How to Implement Fine-Grained Authorization</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-implementing-role-based-access-control">Implementing Role-Based Access Control</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-implementing-attribute-based-access-control">Implementing Attribute-Based Access Control</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-implementing-relationship-based-access-control">Implementing Relationship-Based Access Control</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-fga-in-java-and-springboot">How to Implement FGA in Java and SpringBoot</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-setting-up-the-e-commerce-application">Step 1: Setting Up the E-commerce Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-get-your-environment-api-key">Step 2: Get your Environment API Key</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-deploy-policy-decision-point-pdp">Step 3: Deploy Policy Decision Point (PDP)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-running-the-app">Step 4: Running the App</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-next-steps">Next Steps</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-before-we-end">Before We End...</a></li>
</ul>
</li>
</ul>
<h2 id="heading-what-is-permit"><strong>What is</strong> Permit?</h2>
<blockquote>
<p><a target="_blank" href="https://www.permit.io">Permit.io</a> is a full stack, plug-and-play application-level authorization solution that allows you to implement a <code>secure</code>, <code>flexible</code>, <code>authorization</code> layer within minutes, so you can focus on what matters most.</p>
</blockquote>
<p><a target="_blank" href="https://www.permit.io"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729499767197/6e2b4312-8986-493e-9453-3b67e6aad155.png" alt="what is permit - screenshot of homepage" class="image--center mx-auto" width="600" height="400" loading="lazy"></a></p>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To fully understand the tutorial, you need to have a basic understanding of <code>Java</code> and <code>Spring Boot</code>. You’ll also need the following:</p>
<ul>
<li><p><a target="_blank" href="http://Permit.io"><strong>Permit.io</strong></a>: A developer tool that simplifies the implementation of FGA.</p>
</li>
<li><p><strong>Spring Boot Starter Web</strong>: Provides essential components for building web applications, including RESTful APIs.</p>
</li>
<li><p><strong>Gradle</strong>: A build tool for managing dependencies.</p>
</li>
<li><p><strong>JDK 11 or later</strong>: The Java Development Kit version required to compile and run your Spring Boot app.</p>
</li>
<li><p><strong>Postman or cURL</strong>: Tools for testing your <code>API</code> endpoints.</p>
</li>
</ul>
<h2 id="heading-what-is-fine-grained-authorization"><strong>What is Fine-Grained Authorization?</strong></h2>
<p><a target="_blank" href="https://www.permit.io/blog/what-is-fine-grained-authorization-fga">Fine-grained authorization</a> offers access control to resources by determining who can access them, to what extent, and under specified conditions.</p>
<p>Contrary to coarse-grained authorization (that handles access based on categories like <code>user roles</code> such as "<code>admin</code>" or "<code>user</code>"), fine-grained authorization gives you the flexibility to define access at a granular level, for specific resources or actions and even attributes. </p>
<p>In <code>Fine Grained Authorization</code> there exist 3 types of policy models for managing authorization; <strong>Role Based Access Control (RBAC)</strong>, <strong>Attribute Based Access Control (ABAC)</strong>, and <strong>Relationship-Based Access Control (ReBAC)</strong>.</p>
<p>Let's take a look, at each of these approaches and see how you can implement them in your application.</p>
<h3 id="heading-role-based-access-control-rbac"><strong>Role-Based Access Control (RBAC)</strong></h3>
<p><a target="_blank" href="https://www.permit.io/blog/what-is-rebac">RBAC</a> is a security approach that controls resource access based on the roles of users within an organization. This model streamlines permissions by organizing users into roles and managing access control according to these defined roles.</p>
<p><strong>Key Concepts in RBAC:</strong></p>
<p><strong>Users:</strong> People who use the system such as employees or customers.</p>
<p><strong>Roles:</strong> A set of permissions or access privileges assigned to a group of users based on their responsibilities or tasks such as admin, manager, or customer.</p>
<p><strong>Permissions:</strong> The rights granted to users for interacting with resources, such as read, write, or delete.</p>
<h3 id="heading-attribute-based-access-control-abac"><strong>Attribute-Based Access Control (ABAC)</strong></h3>
<p><a target="_blank" href="https://www.permit.io/blog/what-is-abac">ABAC</a> is a versatile and adaptive access control model that decides who can or cannot access resources based on attributes, like user details. The ABAC model allows you to define fine-grained authorization based on user attributes.</p>
<p><strong>Key Concepts in ABAC:</strong></p>
<p><strong>Attributes:</strong> Characteristics or properties used to make access control decisions. Attributes are typically categorized into:</p>
<ul>
<li><p><strong>User Attributes:</strong> Information about the user (for example, role, department, job title, age, and so on).</p>
</li>
<li><p><strong>Resource Attributes:</strong> Characteristics of the resource (for example, file type, data classification level, creation date, owner).</p>
</li>
<li><p><strong>Action Attributes:</strong> The action the user is trying to perform (for example, read, write, delete, approve).</p>
</li>
<li><p><strong>Environmental Attributes:</strong> Contextual information about the access request (for example, time of day, location, device type, IP address).</p>
</li>
</ul>
<h3 id="heading-relationship-based-access-control-rebac"><strong>Relationship-Based Access Control (ReBAC)</strong></h3>
<p>ReBAC is an access control system that grants permissions to access resources based on the relationship between entities within a system. The approach emphasizes defining and managing access control by mapping out how users relate to resources and other entities such as organizations or groups.</p>
<p><strong>Key Concepts of ReBAC:</strong></p>
<p><strong>Entities:</strong> Users, resources (such as files and documents), and other entities, such as groups or organizational units.</p>
<p><strong>Relationships:</strong> The connections that specify the relationship between two entities. A user might be the "owner" of a document or a "member" of a team, for instance.</p>
<p><strong>Policies:</strong> Rules that use relationships to determine access rights. A user can access a resource or execute an action on it if they have a particular relationship with it.</p>
<h2 id="heading-how-to-implement-fine-grained-authorization"><strong>How to Implement Fine-Grained Authorization</strong></h2>
<p>Now that you have a basic understanding of <code>RBAC</code>, <code>ABAC</code>, and <code>ReBAC</code>, let’s see how we can implement these models in an e-commerce app.</p>
<h3 id="heading-implementing-role-based-access-control"><strong>Implementing Role-Based Access Control</strong></h3>
<p><strong>Step 1:</strong> Navigate to <a target="_blank" href="http://Permit.io">Permit.io</a>, and then create an account and your workspace.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729494514537/a49035e8-1eb2-495f-acee-6ac212d0076e.png" alt="Permit.io - create your workspace page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>By default, you should see a project that includes two environments: <code>Development</code> and <code>Production</code>. </p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong><em>Note:</em></strong><em> You need to define and test your policies in the development environment before deploying them to production.</em></div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729494835226/8d0e6841-09e7-44e2-89fb-1ec3bacb316d.png" alt="Permit.io - project dashboard" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2:</strong> Create a resource named <strong>Products</strong>. To create the resource, open the <strong>Policy</strong> tab on the left sidebar and then open the <strong>Resources</strong> tab at the top. After that, click the <strong>Create a Resource</strong> button and then create a resource called <strong>Products</strong> with actions <code>read</code>, <code>create</code>, <code>update</code>, and <code>delete</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495042599/91660d3d-eafe-4874-aeb2-50bf88c5a291.png" alt="Permit.io - how to add a new resource" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3:</strong> Create another resource called <strong>Reviews</strong> with actions <code>read</code>, <code>create</code>, <code>update</code>, and <code>delete</code>.</p>
<p><strong>Step 4:</strong> Open the <strong>Policy Editor</strong> tab. You’ll see that 3 roles named <code>admin</code>, <code>editor</code>, and <code>viewer</code> were created.</p>
<ul>
<li><p>Role admin has permission to <code>create</code>, <code>delete</code>, <code>read</code>, or <code>update</code> a product or a review.</p>
</li>
<li><p>Role <code>editor</code> has permission to <code>create</code>, <code>read</code>, or <code>update</code> a <code>product</code> or a <code>review</code> but not <code>delete</code> any.</p>
</li>
<li><p>Role <code>viewer</code> has permission to <code>create</code> and <code>read</code> a product or a <code>review</code> but not <code>delete</code> or <code>update</code> any.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495227714/38553c90-5cc0-4fa0-a116-2f5051b5ebb8.png" alt="Permit.io - Policy editor" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-implementing-attribute-based-access-control"><strong>Implementing Attribute-Based Access Control</strong></h3>
<p><strong>Step 1:</strong> Open the <strong>Resources</strong> tab, then click the <strong>Add Attributes</strong> button.</p>
<ul>
<li><p>Add an attribute called <strong>vendor</strong></p>
</li>
<li><p>Add an attribute called the <strong>customer</strong></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495417262/94a09532-83b3-496c-8fef-6ee7c836a211.png" alt="Permit.io - edit resource" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 2:</strong> Open the ABAC Rules tab, then create a new ABAC Resource Set called <strong>Own Products</strong> that depends on the Products resource. After that, add a condition that gives permissions only to the user who created a product based on the vendor attribute.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729495597939/d528f47f-710a-4bd6-b13a-1cf3a3c49031.png" alt="Permit.io - create your resource set page" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3:</strong> Create another ABAC Resource Set called <strong>Own Reviews</strong> that depends on the Reviews resource.</p>
<h3 id="heading-implementing-relationship-based-access-control"><strong>Implementing Relationship-Based Access Control</strong></h3>
<p><strong>Step 1:</strong> Open the Resources tab and edit the Products resource. Add role <code>vendor</code> in the <code>ReBAC</code> options section. Then set products as parent of reviews in the relations section.</p>
<p><strong>Step 2:</strong> Edit the Reviews resource by adding role customer in the <code>ReBAC</code> options section, as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729497355241/4f1a6235-7181-468a-82ce-c727df517604.png" alt="Permit.io - ABAC edit resource" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><strong>Step 3:</strong> Go to <code>Policy</code> <code>Editor</code> tab and add:</p>
<ul>
<li><p>role <code>vendor</code> permission to update and delete own products.</p>
</li>
<li><p>role <code>customer</code> permission to update and delete their own reviews on products.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729497438508/935f79b7-3789-4047-b7b5-73e82654b617.png" alt="Permit.io - Policy editor" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-implement-fga-in-java-and-springboot"><strong>How to Implement FGA in Java and SpringBoot</strong></h2>
<p>Now that we have defined <code>RBAC</code>, <code>ABAC</code>, and <code>ReBAC</code> policies in the Permit.io web interface, let’s learn how to enforce them in an E-Commerce Management System application using the Permit.io API.</p>
<p>There’s a lot of code coming up, so make sure you read through the extensive comments I’ve left throughout each code block. These will help you understand more fully what’s going on in this code.</p>
<h3 id="heading-step-1-setting-up-the-e-commerce-application"><strong>Step 1: Setting Up the E-commerce Application</strong></h3>
<p>To set up the e-commerce application and git clone the source code.</p>
<pre><code class="lang-powershell">git clone https://github.com/tyaga001/java<span class="hljs-literal">-spring</span><span class="hljs-literal">-fine</span><span class="hljs-literal">-grained</span><span class="hljs-literal">-auth</span>.git
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Then open the code in your Java IDE.&nbsp;I used <a target="_blank" href="https://www.jetbrains.com/idea/">JetBrains</a> for all my work.</div>
</div>

<h4 id="heading-installing-permit-package-sdk"><strong>Installing Permit package SDK</strong></h4>
<p>To install the Permit package SDK, you add the SDK under the dependencies block in the <code>build.graddle</code> file.</p>
<pre><code class="lang-java">## Dependencies

To set up the necessary dependencies <span class="hljs-keyword">for</span> your Spring Boot project, include the following in your `build.gradle` file:

```groovy
dependencies {
    implementation <span class="hljs-string">'org.springframework.boot:spring-boot-starter-web'</span>
    implementation <span class="hljs-string">'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'</span>
    developmentOnly <span class="hljs-string">'org.springframework.boot:spring-boot-devtools'</span>
    testImplementation <span class="hljs-string">'org.springframework.boot:spring-boot-starter-test'</span>
    testRuntimeOnly <span class="hljs-string">'org.junit.platform:junit-platform-launcher'</span>

    <span class="hljs-comment">// Add this line to install the Permit.io Java SDK in your project</span>
    implementation <span class="hljs-string">'io.permit:permit-sdk-java:2.0.0'</span>
}
</code></pre>
<h4 id="heading-initializing-the-permit-sdk"><strong>Initializing the Permit SDK</strong></h4>
<p>You can initialize the Permit <code>SDK</code> Client using the code below:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.config;

<span class="hljs-keyword">import</span> io.permit.sdk.Permit;
<span class="hljs-keyword">import</span> io.permit.sdk.PermitConfig;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Value;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;

<span class="hljs-meta">@Configuration</span>  <span class="hljs-comment">// Marks this class as a configuration class for Spring IoC</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PermitClientConfig</span> </span>{

    <span class="hljs-meta">@Value("${permit.api-key}")</span>  <span class="hljs-comment">// Inject Permit API key from application properties</span>
    <span class="hljs-keyword">private</span> String apiKey;

    <span class="hljs-meta">@Value("${permit.pdp-url}")</span>  <span class="hljs-comment">// Inject Permit PDP (Policy Decision Point) URL from application properties</span>
    <span class="hljs-keyword">private</span> String pdpUrl;

    <span class="hljs-comment">/**
     * Creates a Permit client bean with custom configuration
     * <span class="hljs-doctag">@return</span> Permit client instance
     */</span>
    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Permit <span class="hljs-title">permit</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Permit(
                <span class="hljs-keyword">new</span> PermitConfig.Builder(apiKey)  <span class="hljs-comment">// Initialize PermitConfig with API key</span>
                        .withPdpAddress(pdpUrl)   <span class="hljs-comment">// Set the PDP address</span>
                        .withDebugMode(<span class="hljs-keyword">true</span>)      <span class="hljs-comment">// Enable debug mode for detailed logging</span>
                        .build()                  <span class="hljs-comment">// Build the PermitConfig object</span>
        );
    }
}
</code></pre>
<h4 id="heading-syncing-users-with-sdk"><strong>Syncing Users with SDK</strong></h4>
<p>To start enforcing permissions, you should first sync a user to Permit, and then assign them a role.</p>
<p>In the code below, the <strong>UserService</strong> class provides methods for user login, signup, role assignment, and authorization, with exception handling for possible errors when interacting with the Permit API.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.service;

<span class="hljs-keyword">import</span> com.boostmytool.store.exception.ForbiddenAccessException;
<span class="hljs-keyword">import</span> com.boostmytool.store.exception.UnauthorizedException;
<span class="hljs-keyword">import</span> io.permit.sdk.Permit;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitApiError;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitContextError;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.Resource;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-meta">@Service</span>  <span class="hljs-comment">// Marks this class as a Spring service, making it a candidate for component scanning</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Permit permit;

    <span class="hljs-comment">// Constructor injection for the Permit SDK</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserService</span><span class="hljs-params">(Permit permit)</span> </span>{
        <span class="hljs-keyword">this</span>.permit = permit;
    }

    <span class="hljs-comment">/**
     * Simulates user login by creating and returning a Permit User object.
     * 
     * <span class="hljs-doctag">@param</span> key User's unique key
     * <span class="hljs-doctag">@return</span> User object
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">login</span><span class="hljs-params">(String key)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> User.Builder(key).build();
    }

    <span class="hljs-comment">/**
     * Handles user signup by creating and syncing a new Permit User.
     * 
     * <span class="hljs-doctag">@param</span> key User's unique key
     * <span class="hljs-doctag">@return</span> Created and synced User object
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">signup</span><span class="hljs-params">(String key)</span> </span>{
        <span class="hljs-keyword">var</span> user = <span class="hljs-keyword">new</span> User.Builder(key).build();
        <span class="hljs-keyword">try</span> {
            permit.api.users.sync(user);  <span class="hljs-comment">// Syncs the new user with the Permit service</span>
        } <span class="hljs-keyword">catch</span> (PermitContextError | PermitApiError | IOException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to create user"</span>, e);  <span class="hljs-comment">// Handles exceptions during user creation</span>
        }
        <span class="hljs-keyword">return</span> user;
    }

    <span class="hljs-comment">/**
     * Assigns a role to the user within the "default" environment.
     * 
     * <span class="hljs-doctag">@param</span> user User object to assign the role to
     * <span class="hljs-doctag">@param</span> role Role to be assigned
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">assignRole</span><span class="hljs-params">(User user, String role)</span> </span>{
        <span class="hljs-keyword">try</span> {
            permit.api.users.assignRole(user.getKey(), role, <span class="hljs-string">"default"</span>);  <span class="hljs-comment">// Assigns role in the "default" environment</span>
        } <span class="hljs-keyword">catch</span> (PermitApiError | PermitContextError | IOException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to assign role to user"</span>, e);  <span class="hljs-comment">// Handles exceptions during role assignment</span>
        }
    }

    <span class="hljs-comment">/**
     * Checks if the user is authorized to perform a specific action on a resource.
     * 
     * <span class="hljs-doctag">@param</span> user User object requesting authorization
     * <span class="hljs-doctag">@param</span> action Action to be authorized
     * <span class="hljs-doctag">@param</span> resource Resource on which the action will be performed
     * <span class="hljs-doctag">@throws</span> UnauthorizedException if user is not logged in
     * <span class="hljs-doctag">@throws</span> ForbiddenAccessException if user is denied access
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Resource resource)</span> </span>{
        <span class="hljs-keyword">if</span> (user == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">"Not logged in"</span>);  <span class="hljs-comment">// Throws exception if user is not logged in</span>
        }
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">var</span> permitted = permit.check(user, action, resource);  <span class="hljs-comment">// Performs authorization check</span>
            <span class="hljs-keyword">if</span> (!permitted) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ForbiddenAccessException(<span class="hljs-string">"Access denied"</span>);  <span class="hljs-comment">// Throws exception if access is denied</span>
            }
        } <span class="hljs-keyword">catch</span> (PermitApiError | IOException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to authorize user"</span>, e);  <span class="hljs-comment">// Handles exceptions during authorization</span>
        }
    }
}
</code></pre>
<p>Then in the code below, the <strong>UserController</strong> class exposes REST API endpoints for user signup and role assignment. It interacts with the UserService class to handle user-related business logic and provides appropriate HTTP responses.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.controllers;

<span class="hljs-keyword">import</span> com.boostmytool.store.exception.UnauthorizedException;
<span class="hljs-keyword">import</span> com.boostmytool.store.service.UserService;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> jakarta.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.PostMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RequestBody;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.RestController;

<span class="hljs-meta">@RestController</span>  <span class="hljs-comment">// Indicates that this class handles HTTP requests and returns JSON responses</span>
<span class="hljs-meta">@RequestMapping("/api/users")</span>  <span class="hljs-comment">// Base URL path for all user-related operations</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserController</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserService userService;

    <span class="hljs-comment">// Constructor injection of UserService, containing business logic for user operations</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserController</span><span class="hljs-params">(UserService userService)</span> </span>{
        <span class="hljs-keyword">this</span>.userService = userService;
    }

    <span class="hljs-comment">/**
     * Handles user signup requests.
     * Endpoint: POST /api/users/signup
     * 
     * <span class="hljs-doctag">@param</span> key Unique key for the new user
     * <span class="hljs-doctag">@return</span> Created User object
     */</span>
    <span class="hljs-meta">@PostMapping("/signup")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">signup</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> String key)</span> </span>{
        <span class="hljs-keyword">return</span> userService.signup(key);  <span class="hljs-comment">// Calls the signup method in UserService to create a new user</span>
    }

    <span class="hljs-comment">/**
     * Handles assigning a role to the logged-in user.
     * Endpoint: POST /api/users/assign-role
     * 
     * <span class="hljs-doctag">@param</span> request HTTP request, used to retrieve the current user
     * <span class="hljs-doctag">@param</span> role Role to be assigned to the current user
     */</span>
    <span class="hljs-meta">@PostMapping("/assign-role")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">assignRole</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@RequestBody</span> String role)</span> </span>{
        <span class="hljs-comment">// Retrieves the current user from the request attributes</span>
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);

        <span class="hljs-comment">// Throws an exception if the user is not logged in</span>
        <span class="hljs-keyword">if</span> (currentUser == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">"Not logged in"</span>);
        }

        <span class="hljs-comment">// Assigns the specified role to the current user</span>
        userService.assignRole(currentUser, role);
    }
}
</code></pre>
<h4 id="heading-creating-rbac-abac-and-rebac-policy-enforcement-point"><strong>Creating RBAC, ABAC, and ReBAC Policy Enforcement Point</strong></h4>
<p>In the code below, the <strong>ProductService</strong> class manages CRUD operations for products and reviews, handling permissions and roles via the Permit API.</p>
<p>Each operation includes user <code>authorization</code> checks, with appropriate exception handling for Permit API errors and resource not found scenarios.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.service;

<span class="hljs-keyword">import</span> com.boostmytool.store.exception.ResourceNotFoundException;
<span class="hljs-keyword">import</span> com.boostmytool.store.model.Product;
<span class="hljs-keyword">import</span> com.boostmytool.store.model.Review;
<span class="hljs-keyword">import</span> io.permit.sdk.Permit;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitApiError;
<span class="hljs-keyword">import</span> io.permit.sdk.api.PermitContextError;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.Resource;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> io.permit.sdk.openapi.models.RelationshipTupleCreate;
<span class="hljs-keyword">import</span> io.permit.sdk.openapi.models.ResourceInstanceCreate;
<span class="hljs-keyword">import</span> io.permit.sdk.openapi.models.RoleAssignmentCreate;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.concurrent.atomic.AtomicInteger;

<span class="hljs-meta">@Service</span>  <span class="hljs-comment">// Marks this class as a Spring service</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductService</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> List&lt;Product&gt; products = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();  <span class="hljs-comment">// In-memory list to store products</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicInteger productIdCounter = <span class="hljs-keyword">new</span> AtomicInteger();  <span class="hljs-comment">// Counter to generate unique product IDs</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AtomicInteger reviewIdCounter = <span class="hljs-keyword">new</span> AtomicInteger();   <span class="hljs-comment">// Counter to generate unique review IDs</span>

    <span class="hljs-comment">// Builders for Permit resource instances (product and review)</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Resource.Builder productResourceBuilder = <span class="hljs-keyword">new</span> Resource.Builder(<span class="hljs-string">"product"</span>);
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Resource.Builder reviewResourceBuilder = <span class="hljs-keyword">new</span> Resource.Builder(<span class="hljs-string">"review"</span>);

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserService userService;  <span class="hljs-comment">// Service for handling user-related operations</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Permit permit;  <span class="hljs-comment">// Permit SDK instance for handling authorization and resource management</span>

    <span class="hljs-comment">// Constructor for injecting dependencies</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ProductService</span><span class="hljs-params">(UserService userService, Permit permit)</span> </span>{
        <span class="hljs-keyword">this</span>.userService = userService;
        <span class="hljs-keyword">this</span>.permit = permit;
    }

    <span class="hljs-comment">// Method to authorize a user for a given action on a resource</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Resource resource)</span> </span>{
        userService.authorize(user, action, resource);
    }

    <span class="hljs-comment">// Authorizes a user to perform an action on a specific product</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Product product)</span> </span>{
        <span class="hljs-keyword">var</span> attributes = <span class="hljs-keyword">new</span> HashMap&lt;String, Object&gt;();
        attributes.put(<span class="hljs-string">"vendor"</span>, product.getVendor());  <span class="hljs-comment">// Add vendor attribute to the product</span>
        userService.authorize(user, action, productResourceBuilder.withKey(product.getId().toString()).withAttributes(attributes).build());
    }

    <span class="hljs-comment">// Authorizes a user to perform an action on a specific review</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">authorize</span><span class="hljs-params">(User user, String action, Review review)</span> </span>{
        <span class="hljs-keyword">var</span> attributes = <span class="hljs-keyword">new</span> HashMap&lt;String, Object&gt;();
        attributes.put(<span class="hljs-string">"customer"</span>, review.getCustomer());  <span class="hljs-comment">// Add customer attribute to the review</span>
        userService.authorize(user, action, reviewResourceBuilder.withKey(review.getId().toString()).withAttributes(attributes).build());
    }

    <span class="hljs-comment">// Retrieves a product by its ID, throws an exception if not found</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> Product <span class="hljs-title">getProductById</span><span class="hljs-params">(<span class="hljs-keyword">int</span> id)</span> </span>{
        <span class="hljs-keyword">return</span> products.stream().filter(product -&gt; product.getId().equals(id))
                .findFirst().orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Product with id "</span> + id + <span class="hljs-string">" not found"</span>));
    }

    <span class="hljs-comment">// Retrieves all products, checks if the user is authorized to "read" products</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Product&gt; <span class="hljs-title">getAllProducts</span><span class="hljs-params">(User user)</span> </span>{
        authorize(user, <span class="hljs-string">"read"</span>, productResourceBuilder.build());  <span class="hljs-comment">// User must have "read" permission</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(products);  <span class="hljs-comment">// Return a copy of the products list</span>
    }

    <span class="hljs-comment">// Retrieves a product by its ID, checks if the user is authorized to "read" the product</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">getProduct</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> id)</span> </span>{
        authorize(user, <span class="hljs-string">"read"</span>, productResourceBuilder.build());
        <span class="hljs-keyword">return</span> getProductById(id);
    }

    <span class="hljs-comment">// Adds a new product, authorizes the user and creates resource instances and role assignments in Permit</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">addProduct</span><span class="hljs-params">(User user, String content)</span> </span>{
        authorize(user, <span class="hljs-string">"create"</span>, productResourceBuilder.build());  <span class="hljs-comment">// Check if user can create a product</span>
        Product product = <span class="hljs-keyword">new</span> Product(productIdCounter.incrementAndGet(), user.getKey(), content);  <span class="hljs-comment">// Create new product</span>

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Create resource instance in Permit and assign "vendor" role to the user for this product</span>
            permit.api.resourceInstances.create(<span class="hljs-keyword">new</span> ResourceInstanceCreate(product.getId().toString(), <span class="hljs-string">"product"</span>).withTenant(<span class="hljs-string">"default"</span>));
            permit.api.roleAssignments.assign(<span class="hljs-keyword">new</span> RoleAssignmentCreate(<span class="hljs-string">"vendor"</span>, user.getKey()).withResourceInstance(<span class="hljs-string">"product:"</span> + product.getId()).withTenant(<span class="hljs-string">"default"</span>));
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Failed to create resource instance or role assignment: "</span> + e.getMessage());
        }

        products.add(product);  <span class="hljs-comment">// Add product to in-memory list</span>
        <span class="hljs-keyword">return</span> product;
    }

    <span class="hljs-comment">// Updates a product's content, checks if the user is authorized to "update" the product</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">updateProduct</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> id, String content)</span> </span>{
        Product product = getProductById(id);  <span class="hljs-comment">// Get the product by its ID</span>
        authorize(user, <span class="hljs-string">"update"</span>, product);  <span class="hljs-comment">// Check if user can update the product</span>
        product.setContent(content);  <span class="hljs-comment">// Update product content</span>
        <span class="hljs-keyword">return</span> product;
    }

    <span class="hljs-comment">// Deletes a product, checks if the user is authorized to "delete" the product</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteProduct</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> id)</span> </span>{
        <span class="hljs-keyword">boolean</span> isDeleted = products.removeIf(product -&gt; {
            <span class="hljs-keyword">if</span> (product.getId().equals(id)) {
                authorize(user, <span class="hljs-string">"delete"</span>, product);  <span class="hljs-comment">// Check if user can delete the product</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            }
        });

        <span class="hljs-keyword">if</span> (!isDeleted) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Product with id "</span> + id + <span class="hljs-string">" not found"</span>);
        }

        <span class="hljs-keyword">try</span> {
            permit.api.resourceInstances.delete(<span class="hljs-string">"product:"</span> + id);  <span class="hljs-comment">// Remove product resource instance from Permit</span>
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }
    }

    <span class="hljs-comment">// Adds a review to a product, creates a resource instance and relationship in Permit</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">addReview</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> productId, String content)</span> </span>{
        authorize(user, <span class="hljs-string">"create"</span>, reviewResourceBuilder.build());  <span class="hljs-comment">// Check if user can create a review</span>
        Product product = getProductById(productId);  <span class="hljs-comment">// Get the product by its ID</span>
        Review review = <span class="hljs-keyword">new</span> Review(reviewIdCounter.incrementAndGet(), user.getKey(), content);  <span class="hljs-comment">// Create new review</span>

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Create a resource instance for the review and set relationship with the product</span>
            permit.api.resourceInstances.create(<span class="hljs-keyword">new</span> ResourceInstanceCreate(review.getId().toString(), <span class="hljs-string">"review"</span>).withTenant(<span class="hljs-string">"default"</span>));
            permit.api.relationshipTuples.create(<span class="hljs-keyword">new</span> RelationshipTupleCreate(<span class="hljs-string">"product:"</span> + productId, <span class="hljs-string">"parent"</span>, <span class="hljs-string">"review:"</span> + review.getId()));
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }

        product.addReview(review);  <span class="hljs-comment">// Add the review to the product</span>
        <span class="hljs-keyword">return</span> review;
    }

    <span class="hljs-comment">// Updates a review's content, checks if the user is authorized to "update" the review</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">updateReview</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> productId, <span class="hljs-keyword">int</span> reviewId, String content)</span> </span>{
        Product product = getProductById(productId);  <span class="hljs-comment">// Get the product by its ID</span>
        Review review = product.getReviews().stream().filter(c -&gt; c.getId().equals(reviewId))
                .findFirst().orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Review with id "</span> + reviewId + <span class="hljs-string">" not found"</span>));

        authorize(user, <span class="hljs-string">"update"</span>, review);  <span class="hljs-comment">// Check if user can update the review</span>
        review.setContent(content);  <span class="hljs-comment">// Update review content</span>
        <span class="hljs-keyword">return</span> review;
    }

    <span class="hljs-comment">// Deletes a review, checks if the user is authorized to "delete" the review</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteReview</span><span class="hljs-params">(User user, <span class="hljs-keyword">int</span> productId, <span class="hljs-keyword">int</span> reviewId)</span> </span>{
        Product product = getProductById(productId);  <span class="hljs-comment">// Get the product by its ID</span>
        <span class="hljs-keyword">boolean</span> isDeleted = product.getReviews().removeIf(review -&gt; {
            <span class="hljs-keyword">if</span> (review.getId().equals(reviewId)) {
                authorize(user, <span class="hljs-string">"delete"</span>, review);  <span class="hljs-comment">// Check if user can delete the review</span>
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
            }
        });

        <span class="hljs-keyword">if</span> (!isDeleted) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ResourceNotFoundException(<span class="hljs-string">"Review with id "</span> + reviewId + <span class="hljs-string">" not found"</span>);
        }

        <span class="hljs-keyword">try</span> {
            permit.api.resourceInstances.delete(<span class="hljs-string">"review:"</span> + reviewId);  <span class="hljs-comment">// Remove review resource instance from Permit</span>
        } <span class="hljs-keyword">catch</span> (IOException | PermitApiError | PermitContextError e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(e);
        }
    }
}
</code></pre>
<p>Then in the code below, the <strong>ProductController</strong> class handles HTTP requests related to products and their reviews. It exposes endpoints for managing products (like <code>creating</code>, <code>updating</code>, <code>deleting</code>, and <code>retrieving</code>) and for managing product reviews.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.boostmytool.store.controllers;

<span class="hljs-keyword">import</span> com.boostmytool.store.model.Product;
<span class="hljs-keyword">import</span> com.boostmytool.store.model.Review;
<span class="hljs-keyword">import</span> com.boostmytool.store.service.ProductService;
<span class="hljs-keyword">import</span> io.permit.sdk.enforcement.User;
<span class="hljs-keyword">import</span> jakarta.servlet.http.HttpServletRequest;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.http.HttpStatus;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.*;

<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-meta">@RestController</span>  <span class="hljs-comment">// Indicates that this class is a Spring REST controller</span>
<span class="hljs-meta">@RequestMapping("/api/products")</span>  <span class="hljs-comment">// Base URL for all endpoints in this controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductController</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ProductService productService;  <span class="hljs-comment">// ProductService instance to handle product-related operations</span>

    <span class="hljs-meta">@Autowired</span>  <span class="hljs-comment">// Autowires ProductService bean automatically</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ProductController</span><span class="hljs-params">(ProductService productService)</span> </span>{
        <span class="hljs-keyword">this</span>.productService = productService;
    }

    <span class="hljs-comment">// GET request to retrieve all products</span>
    <span class="hljs-meta">@GetMapping</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Product&gt; <span class="hljs-title">getAllProducts</span><span class="hljs-params">(HttpServletRequest request)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.getAllProducts(currentUser);  <span class="hljs-comment">// Calls ProductService to get all products for the user</span>
    }

    <span class="hljs-comment">// GET request to retrieve a product by its ID</span>
    <span class="hljs-meta">@GetMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">getProductById</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.getProduct(currentUser, id);  <span class="hljs-comment">// Calls ProductService to get the product by ID for the user</span>
    }

    <span class="hljs-comment">// POST request to add a new product</span>
    <span class="hljs-meta">@PostMapping</span>
    <span class="hljs-meta">@ResponseStatus(HttpStatus.CREATED)</span>  <span class="hljs-comment">// Sets the response status to 201 (Created)</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">addProduct</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.addProduct(currentUser, content);  <span class="hljs-comment">// Calls ProductService to add a new product</span>
    }

    <span class="hljs-comment">// PUT request to update an existing product by its ID</span>
    <span class="hljs-meta">@PutMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">updateProduct</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.updateProduct(currentUser, id, content);  <span class="hljs-comment">// Calls ProductService to update the product by ID</span>
    }

    <span class="hljs-comment">// DELETE request to delete a product by its ID</span>
    <span class="hljs-meta">@DeleteMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">deleteProduct</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        productService.deleteProduct(currentUser, id);  <span class="hljs-comment">// Calls ProductService to delete the product by ID</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Deleted product with id "</span> + id;  <span class="hljs-comment">// Returns a success message after deletion</span>
    }

    <span class="hljs-comment">// POST request to add a new review to a product by product ID</span>
    <span class="hljs-meta">@PostMapping("/{id}/review")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">addReview</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.addReview(currentUser, id, content);  <span class="hljs-comment">// Calls ProductService to add a review to the product</span>
    }

    <span class="hljs-comment">// PUT request to update an existing review by product and review ID</span>
    <span class="hljs-meta">@PutMapping("/{id}/review/{reviewId}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Review <span class="hljs-title">updateReview</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@PathVariable("reviewId")</span> <span class="hljs-keyword">int</span> reviewId, <span class="hljs-meta">@RequestBody</span> String content)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        <span class="hljs-keyword">return</span> productService.updateReview(currentUser, id, reviewId, content);  <span class="hljs-comment">// Calls ProductService to update the review</span>
    }

    <span class="hljs-comment">// DELETE request to delete a review by product and review ID</span>
    <span class="hljs-meta">@DeleteMapping("/{id}/review/{reviewId}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">deleteReview</span><span class="hljs-params">(HttpServletRequest request, <span class="hljs-meta">@PathVariable("id")</span> <span class="hljs-keyword">int</span> id, <span class="hljs-meta">@PathVariable("reviewId")</span> <span class="hljs-keyword">int</span> reviewId)</span> </span>{
        User currentUser = (User) request.getAttribute(<span class="hljs-string">"user"</span>);  <span class="hljs-comment">// Gets the authenticated user from the request</span>
        productService.deleteReview(currentUser, id, reviewId);  <span class="hljs-comment">// Calls ProductService to delete the review</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Deleted review with id "</span> + reviewId + <span class="hljs-string">" from product "</span> + id;  <span class="hljs-comment">// Returns a success message after deletion</span>
    }
}
</code></pre>
<h3 id="heading-step-2-get-your-environment-api-key"><strong>Step 2: Get your Environment API Key</strong></h3>
<p>In the UI Dashboard, copy the Environment <code>API Key</code> of the active environment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498343969/2bbbd4a0-512f-4b46-a82a-ca41ecb67a4c.png" alt="Permit.io - copy env key" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Then add the env <code>API key</code> and <code>PDP URL</code> in the <code>application.yaml</code> file.</p>
<pre><code class="lang-plaintext">permit:
  pdpUrl: 'http://localhost:7766'
  apiKey: "Your Permit environment API Key"
</code></pre>
<h3 id="heading-step-3-deploy-policy-decision-point-pdp"><strong>Step 3: Deploy Policy Decision Point (PDP)</strong></h3>
<p>The Policy Decision Point (PDP) is deployed in your VPC and is in charge of evaluating your authorization requests. The PDP will ensure zero latency, great performance, high availability, and improved security.</p>
<p>Use the command below to pull the <a target="_blank" href="http://Permit.io">Permit.io</a> PDP container from <code>Docker</code> Hub.</p>
<pre><code class="lang-dockerfile">docker pull permitio/pdp-v2:latest
</code></pre>
<p>Then run the container.</p>
<pre><code class="lang-dockerfile">docker <span class="hljs-keyword">run</span><span class="bash"> -it -p 7766:7000 --env PDP_DEBUG=True --env PDP_API_KEY=&lt;YOUR_API_KEY&gt; permitio/pdp-v2:latest</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729515246656/6bed08e3-6109-4643-a724-f55641d7c974.png" alt="Permit.io - local testing" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-4-running-the-app"><strong>Step 4: Running the App</strong></h3>
<p>You can run the application using the following <code>Gradle</code> command:</p>
<pre><code class="lang-dockerfile">./gradlew bootRun
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729515837209/41556843-b8d5-4433-a2f3-93371562d27d.png" alt="Permit.io - how to run the app in local" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-viewing-and-creating-products"><strong>Viewing and Creating Products</strong></h4>
<p>Let’s now interact with the application endpoints using <a target="_blank" href="https://reqbin.com/curl">REQBIN</a>.</p>
<p>First, create a new user using the <code>/api/users/signup</code> endpoint.</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/signup"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'johndoe'</span>
</code></pre>
<p>You should be able to view the user in your Permit project, under Directory &gt; All Tenants.</p>
<p>Initially, the user has no roles, so it cannot do much. For example, trying to list the products will result in a 403 Forbidden response, as shown below. The 403 error code means the user doesn’t have permissions to access the requested resource, which is products in this case. You can learn more about <a target="_blank" href="https://www.permit.io/blog/401-vs-403-error-whats-the-difference">the difference between 401 and 403 error codes here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498632123/aaf26b76-a89f-4e6b-9324-85d082b8061d.png" alt="Permit.io - endpoints" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>For the user to view a list of products, assign them a viewer role using the command below:</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/assign-role"</span> \
-H <span class="hljs-string">"Authorization: Bearer johndoe"</span> \
-H <span class="hljs-string">"Content-Type: application/json"</span> \
-d <span class="hljs-string">'viewer'</span>
</code></pre>
<p>You should see that user <code>johndoe</code> was assigned role viewer, as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498710784/ebd789fd-ec52-4146-bb94-6f300edb9d7e.png" alt="Permit.io - users" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Since a viewer can create a product, use the command below to create a product with user <code>johndoe</code>.</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/products"</span> -H <span class="hljs-string">"Authorization: Bearer johndoe"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'MacBook'</span>
</code></pre>
<p>You should see that a new product is created with ID 1 and that the user <code>johndoe</code> has been added as the vendor.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729498758160/c14169f0-d720-465e-9bc1-f7096e6da31a.png" alt="Permit.io - API end points " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h4 id="heading-adding-reviews-to-products"><strong>Adding Reviews To Products</strong></h4>
<p>To add reviews to products, create another user called <code>jane</code>.</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/signup"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'jane'</span>
</code></pre>
<p>For the user to add a review to products, assign them a <code>viewer</code> role using the command below:</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/users/assign-role"</span> \
-H <span class="hljs-string">"Authorization: Bearer jane"</span> \
-H <span class="hljs-string">"Content-Type: application/json"</span> \
-d <span class="hljs-string">'viewer'</span>
</code></pre>
<p>Then you can add a review to the product added by <code>johndoe</code> using the command below:</p>
<pre><code class="lang-dockerfile">curl -X POST <span class="hljs-string">"http://localhost:8080/api/products/1/review"</span> -H <span class="hljs-string">"Authorization: Bearer jane"</span> -H <span class="hljs-string">"Content-Type: application/json"</span> -d <span class="hljs-string">'The product was in good quality'</span>
</code></pre>
<p>Congratulations! You’ve completed the project for this tutorial.</p>
<h2 id="heading-next-steps">Next Steps</h2>
<p>Now that you've learned how to implement fine-grained authorization in your Java and Spring Boot applications using <a target="_blank" href="http://Permit.io">Permit.io</a>, you might want to explore further.</p>
<p>Here are some valuable resources:</p>
<ul>
<li><p><a target="_blank" href="https://docs.permit.io/">Permit.io docs</a></p>
</li>
<li><p><a target="_blank" href="https://www.permit.io/blog/rbac-vs-abac">RBAC VS ABAC: Choosing the Right Authorization Policy Model</a></p>
</li>
</ul>
<h3 id="heading-before-we-end">Before We End</h3>
<p>I hope you found this tutorial insightful.</p>
<p>Here are some of my other recent blog posts that you might enjoy:</p>
<ul>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/learn-react-key-concepts/">Learn React – A Guide to the Key Concepts</a></p>
</li>
<li><p><a target="_blank" href="https://www.devtoolsacademy.com/blog/neon-vs-supabase"><strong>Neon Postgres vs Supabase</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/nextjs-clerk-neon-fullstack-development/">Full Stack Development with Next.js, Clerk, and Neon Postgres</a></p>
</li>
</ul>
<p>For more tutorials on amazing developer tools, be sure to check out my blog <a target="_blank" href="https://www.devtoolsacademy.com/">DTA</a>.</p>
<p>Follow me on <a target="_blank" href="https://x.com/TheAnkurTyagi">Twitter</a> to get live updates on my other projects.</p>
<p>Happy coding.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build an AI Chatbot with Spring AI, React, and Docker ]]>
                </title>
                <description>
                    <![CDATA[ Hey Java developers, I’ve got good news: Spring now has official support for building AI applications using the Spring AI module. In this tutorial, we’ll build a chatbot application using Spring Boot, React, Docker, and OpenAI. This app will let user... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/ai-chatbot-with-spring-react-docker/</link>
                <guid isPermaLink="false">66f17acd2085b5a2fdb356e0</guid>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ openai ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Vikas Rajput ]]>
                </dc:creator>
                <pubDate>Mon, 23 Sep 2024 14:27:25 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/6UDansS-rPI/upload/d57a180a4cda63056c786838a71c6679.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hey Java developers, I’ve got good news: Spring now has official support for building AI applications using the <a target="_blank" href="https://spring.io/projects/spring-ai">Spring AI</a> module.</p>
<p>In this tutorial, we’ll build a chatbot application using <a target="_blank" href="https://spring.io/projects/spring-boot"><strong>Spring Boot</strong></a>, <a target="_blank" href="https://react.dev/"><strong>React</strong></a>, <a target="_blank" href="https://www.docker.com/"><strong>Docker</strong></a>, and <a target="_blank" href="https://openai.com/"><strong>OpenAI</strong></a>. This app will let users interact with an AI-powered chatbot, ask questions, and receive responses in real time.</p>
<p>The entire source code mentioned in this article is already available on the <a target="_blank" href="https://github.com/vikasrajputin/springboot-react-docker-chatbot">GitHub repository</a>. Feel free to give it a star and fork it to play around.</p>
<p>To give you an idea of what we’ll be building here, this is how the final application will look:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726657239698/5170bf73-b317-4281-bcd1-583454d4113f.png" alt="Chatbot App UI using Spring AI, React, Docker by Vikas Rajput" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Are you excited? Let’s build it from scratch!</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-get-your-openai-key">Get Your OpenAI key</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-build-the-rest-api-in-spring-boot">Build the REST API in Spring Boot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-build-the-chatui-using-reactjs">Build the ChatUI using Reactjs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-dockerize-the-application">How to Dockerize the Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-run-the-application">Run the Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-congratulations">Congratulations 🎉</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before we dive into building the chatbot, here are a few things you’ll need to be familiar with:</p>
<ol>
<li><p>Basic understanding of <strong>Java</strong> and <strong>Spring Boot</strong>.</p>
</li>
<li><p>Basic understanding of <strong>React</strong> and <strong>CSS</strong>.</p>
</li>
<li><p>Install <a target="_blank" href="https://jdk.java.net/java-se-ri/17-MR1">JDK</a>, <a target="_blank" href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm">Node Package Manager</a> and <a target="_blank" href="https://docs.docker.com/get-started/get-docker/">Docke</a><a target="_blank" href="https://docs.docker.com/desktop/">r</a> onto your machine.</p>
</li>
</ol>
<h2 id="heading-get-your-openai-key"><strong>Get Your OpenAI key</strong></h2>
<p>First, you’ll need to sign up for an <a target="_blank" href="https://platform.openai.com/">OpenAI</a> account if you don’t have one. Once signed in, you’ll be taken to the homepage.</p>
<p>In the top right corner, click the “Dashboard” menu. On the sidebar, click "API Keys," then click the "Create new secret key" button to generate your secret key:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726818120291/5f1681a0-fdbe-401e-ab4b-769fe38d7957.png" alt="How to generate your OpenAI key" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Copy the secret key and save it somewhere safe, as you’ll need it later to connect your app to the OpenAI API.</p>
<p>You can go through the OpenAI <a target="_blank" href="https://platform.openai.com/docs/api-reference/authentication">API reference guide</a> to learn more about how to call the APIs, what requests it accepts, and the responses it gives.</p>
<h2 id="heading-build-the-rest-api-in-spring-boot"><strong>Build the REST API in Spring Boot</strong></h2>
<p>Let’s head over to the <a target="_blank" href="https://start.spring.io/">spring initializer</a> to generate the boilerplate code:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1726662395429/cd4b07fd-2597-43bf-8038-1821003125bb.png" alt="Build Spring AI app using the spring initializer" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You can give the group, artifact, name, description, and package you choose. We’ve used Maven as the built tool, Spring boot version 3.3.3, Jar as a packaging option, and Java version 17.</p>
<p>Hit the generate button and the zip will be downloaded. Unzip the files and import them as a Maven project into your favourite IDE (mine is Intellij).</p>
<h3 id="heading-configure-your-openai-key-in-spring">Configure your OpenAI key in Spring</h3>
<p>You can either use the existing <code>application.properties</code> file or create a <code>application.yaml</code> file. I love working with Yaml, so created a <code>application.yaml</code> file where I can place all my Spring Boot configurations.</p>
<p>Add the OpenAIKey, Model, and Temperature to your <code>application.yaml</code> file:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">spring:</span>
  <span class="hljs-attr">ai:</span>
    <span class="hljs-attr">openai:</span>
      <span class="hljs-attr">chat:</span>
        <span class="hljs-attr">options:</span>
          <span class="hljs-attr">model:</span> <span class="hljs-string">"gpt-3.5-turbo"</span>
          <span class="hljs-attr">temperature:</span> <span class="hljs-string">"0.7"</span>
      <span class="hljs-attr">key:</span> <span class="hljs-string">"PUT YOUR OPEN_API_KEY HERE"</span>
</code></pre>
<p>A similar configuration in <code>application.properties</code> may look like as follows:</p>
<pre><code class="lang-basic">spring.ai.openai.chat.options.model=gpt-<span class="hljs-number">3.5</span>-turbo
spring.ai.openai.chat.options.temperature=<span class="hljs-number">0.7</span>
spring.ai.openai.<span class="hljs-keyword">key</span>=<span class="hljs-string">"PUT YOUR OPEN_API_KEY HERE"</span>
</code></pre>
<h3 id="heading-build-the-chatcontroller">Build the ChatController</h3>
<p>Let’s create a <code>GET</code> API with the URL <code>/ai/chat/string</code> and a method to handle the logic:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ChatController</span> </span>{

    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> OpenAiChatModel chatModel;

    <span class="hljs-meta">@GetMapping("/ai/chat/string")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Flux&lt;String&gt; <span class="hljs-title">generateString</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(value = "message", defaultValue = "Tell me a joke")</span> String message)</span> </span>{
        <span class="hljs-keyword">return</span> chatModel.stream(message);
    }
}
</code></pre>
<ul>
<li><p>First, we’re adding <code>@RestController</code> to mark the <code>ChatController</code> class as our spring controller</p>
</li>
<li><p>Then, we’re injecting the dependency for the <code>OpenAiChatModel</code> class. It comes out of the box as part of the Spring AI dependency we’ve used.</p>
</li>
<li><p>The <code>OpenAiChatModel</code> comes with a method <code>stream(message)</code> which accepts the prompt as <code>String</code> and returns a <code>String</code> response (technically it’s a <code>Flux</code> of <code>String</code> as we’ve used a Reactive version of the same method).</p>
</li>
<li><p>Internally, <code>OpenAiChatModel.stream(message)</code> will call the OpenAI API and fetch the response from there. The OpenAI call will use the configuration steps mentioned in your <code>application.yaml</code> file, so make sure to use a valid OpenAI key.</p>
</li>
<li><p>We’ve created a method to handle the GET API call, which accepts the message and returns <code>Flux&lt;String&gt;</code> as the response.</p>
</li>
</ul>
<h3 id="heading-build-run-and-test-the-rest-api">Build, Run, and Test the REST API</h3>
<p>Use the maven commands to build and run the Spring Boot application:</p>
<pre><code class="lang-bash">./mvnw clean install spring-boot:run
</code></pre>
<p>Ideally, it will run on a <code>8080</code> port unless you’ve customized the port. Make sure to keep that port free to successfully run the application.</p>
<p>You can either use <a target="_blank" href="https://www.postman.com/">Postman</a> or the <a target="_blank" href="https://curl.se/">Curl</a> command to test your REST API:</p>
<pre><code class="lang-bash">curl --location <span class="hljs-string">'http://localhost:8080/ai/chat/string?message=How%20are%20you%3F'</span>
</code></pre>
<h2 id="heading-build-the-chatui-using-reactjs">Build the ChatUI using React.js</h2>
<p>We will be making it super simple and easy for the sake of this tutorial, so pardon me if I don’t follow any React best practices.</p>
<h3 id="heading-create-appjs-to-manage-the-chatui-form">Create <code>App.js</code> to Manage the ChatUI Form</h3>
<p>We’ll be using <code>useState</code> to manage the state:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> [messages, setMessages] = useState([]);
<span class="hljs-keyword">const</span> [input, setInput] = useState(<span class="hljs-string">''</span>);
<span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);
</code></pre>
<ul>
<li><p><code>messages</code>: It will store all the messages in the chat. Each message has a <code>text</code> and a <code>sender</code> (either 'user' or 'ai').</p>
</li>
<li><p><code>input</code>: To hold what the user is typing in the text box.</p>
</li>
<li><p><code>loading</code>: This state is set to <code>true</code> while the chatbot is waiting for a response from the AI, and <code>false</code> when the response is received.</p>
</li>
</ul>
<p>Let’s create a function <code>handleSend</code> and call it when the user sends a message by clicking a button or pressing Enter:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handleSend = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">if</span> (input.trim() === <span class="hljs-string">''</span>) <span class="hljs-keyword">return</span>;

    <span class="hljs-keyword">const</span> newMessage = { <span class="hljs-attr">text</span>: input, <span class="hljs-attr">sender</span>: <span class="hljs-string">'user'</span> };
    setMessages([...messages, newMessage]);
    setInput(<span class="hljs-string">''</span>);
    setLoading(<span class="hljs-literal">true</span>);

    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'http://localhost:8080/ai/chat/string?message='</span> + input);
        <span class="hljs-keyword">const</span> aiMessage = { <span class="hljs-attr">text</span>: response.data, <span class="hljs-attr">sender</span>: <span class="hljs-string">'ai'</span> };
        setMessages([...messages, newMessage, aiMessage]);
    } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error fetching AI response"</span>, error);
    } <span class="hljs-keyword">finally</span> {
        setLoading(<span class="hljs-literal">false</span>);
    }
};
</code></pre>
<p>Here’s what happens step by step:</p>
<ul>
<li><p><strong>Check empty input</strong>: If the input field is empty, the function returns early (nothing is sent).</p>
</li>
<li><p><strong>New message from the user</strong>: A new message is added to the <code>messages</code> array. This message has the <code>text</code> (whatever the user typed) and is marked as being sent by the 'user'.</p>
</li>
<li><p><strong>Reset input</strong>: The input field is cleared after the message is sent.</p>
</li>
<li><p><strong>Start loading</strong>: While waiting for the AI to respond, <code>loading</code> is set to <code>true</code> to show a loading indicator.</p>
</li>
<li><p><strong>Make API request</strong>: The code is used <code>axios</code> to request the AI chatbot API, passing the user's message. When the response comes back, a new message from the AI is added to the chat.</p>
</li>
<li><p><strong>Error handling</strong>: If there is a problem getting the AI’s response, an error is logged to the console.</p>
</li>
<li><p><strong>Stop loading</strong>: Finally, the loading state is turned off.</p>
</li>
</ul>
<p>Let’s write a function to update the <code>input</code> state whenever the user types something in the input field:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handleInputChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    setInput(e.target.value);
};
</code></pre>
<p>Next, let’s create a function to check if the user presses the Enter key. If they do, it calls <code>handleSend()</code> to send the message:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> handleKeyPress = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (e.key === <span class="hljs-string">'Enter'</span>) {
        handleSend();
    }
};
</code></pre>
<p>Now let’s create UI elements to render the chat messages:</p>
<pre><code class="lang-js">{messages.map(<span class="hljs-function">(<span class="hljs-params">message, index</span>) =&gt;</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">message-container</span> ${<span class="hljs-attr">message.sender</span>}`}&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
            <span class="hljs-attr">src</span>=<span class="hljs-string">{message.sender</span> === <span class="hljs-string">'user'</span> ? '<span class="hljs-attr">user-icon.png</span>' <span class="hljs-attr">:</span> '<span class="hljs-attr">ai-assistant.png</span>'}
            <span class="hljs-attr">alt</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">message.sender</span>} <span class="hljs-attr">avatar</span>`}
            <span class="hljs-attr">className</span>=<span class="hljs-string">"avatar"</span>
        /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">message</span> ${<span class="hljs-attr">message.sender</span>}`}&gt;</span>
            {message.text}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
))}
</code></pre>
<p>This block renders all the messages in the chat:</p>
<ul>
<li><p><strong>Mapping through messages</strong>: Each message is displayed as a <code>div</code> using <code>.map()</code>.</p>
</li>
<li><p><strong>Message styling</strong>: The class name of the message changes based on who the sender is (<code>user</code> or <code>ai</code>), making it clear who sent the message.</p>
</li>
<li><p><strong>Avatar images</strong>: Each message shows a small avatar, with a different image for the user and the AI.</p>
</li>
</ul>
<p>Let’s create some logic to show the loader based on a flag:</p>
<pre><code class="lang-js">{loading &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message-container ai"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"ai-assistant.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"AI avatar"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"avatar"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message ai"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
)}
</code></pre>
<p>While the AI is thinking (when <code>loading</code> is <code>true</code>), we show a loading message (<code>...</code>) so the user knows a response is coming soon.</p>
<p>At last, create a button to click the message send button:</p>
<pre><code class="lang-jsx">&lt;button onClick={handleSend}&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FaPaperPlane</span> /&gt;</span></span>
&lt;/button&gt;
</code></pre>
<p>This button triggers the <code>handleSend()</code> function when clicked. The icon used here is a <a target="_blank" href="https://react-icons.github.io/react-icons/icons/fa/">paper plane</a>, which is common for "send" buttons.</p>
<p>The full <code>Chatbot.js</code> looks as below:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
<span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">'axios'</span>;
<span class="hljs-keyword">import</span> { FaPaperPlane } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-icons/fa'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./Chatbot.css'</span>;

<span class="hljs-keyword">const</span> Chatbot = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [messages, setMessages] = useState([]);
    <span class="hljs-keyword">const</span> [input, setInput] = useState(<span class="hljs-string">''</span>);
    <span class="hljs-keyword">const</span> [loading, setLoading] = useState(<span class="hljs-literal">false</span>);

    <span class="hljs-keyword">const</span> handleSend = <span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">if</span> (input.trim() === <span class="hljs-string">''</span>) <span class="hljs-keyword">return</span>;

        <span class="hljs-keyword">const</span> newMessage = { <span class="hljs-attr">text</span>: input, <span class="hljs-attr">sender</span>: <span class="hljs-string">'user'</span> };
        setMessages([...messages, newMessage]);
        setInput(<span class="hljs-string">''</span>);
        setLoading(<span class="hljs-literal">true</span>);

        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> axios.get(<span class="hljs-string">'http://localhost:8080/ai/chat/string?message='</span> + input);
            <span class="hljs-keyword">const</span> aiMessage = { <span class="hljs-attr">text</span>: response.data, <span class="hljs-attr">sender</span>: <span class="hljs-string">'ai'</span> };
            setMessages([...messages, newMessage, aiMessage]);
        } <span class="hljs-keyword">catch</span> (error) {
            <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error fetching AI response"</span>, error);
        } <span class="hljs-keyword">finally</span> {
            setLoading(<span class="hljs-literal">false</span>);
        }
    };

    <span class="hljs-keyword">const</span> handleInputChange = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        setInput(e.target.value);
    };

    <span class="hljs-keyword">const</span> handleKeyPress = <span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (e.key === <span class="hljs-string">'Enter'</span>) {
            handleSend();
        }
    };

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"chatbot-container"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"chat-header"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"ChatBot.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Chatbot Logo"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"chat-logo"</span> /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"breadcrumb"</span>&gt;</span>Home <span class="hljs-symbol">&amp;gt;</span> Chat<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"chatbox"</span>&gt;</span>
                {messages.map((message, index) =&gt; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">message-container</span> ${<span class="hljs-attr">message.sender</span>}`}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
                            <span class="hljs-attr">src</span>=<span class="hljs-string">{message.sender</span> === <span class="hljs-string">'user'</span> ? '<span class="hljs-attr">user-icon.png</span>' <span class="hljs-attr">:</span> '<span class="hljs-attr">ai-assistant.png</span>'}
                            <span class="hljs-attr">alt</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">message.sender</span>} <span class="hljs-attr">avatar</span>`}
                            <span class="hljs-attr">className</span>=<span class="hljs-string">"avatar"</span>
                        /&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">message</span> ${<span class="hljs-attr">message.sender</span>}`}&gt;</span>
                            {message.text}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                ))}
                {loading &amp;&amp; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message-container ai"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"ai-assistant.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"AI avatar"</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"avatar"</span> /&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"message ai"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                )}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"input-container"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                    <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span>
                    <span class="hljs-attr">value</span>=<span class="hljs-string">{input}</span>
                    <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleInputChange}</span>
                    <span class="hljs-attr">onKeyPress</span>=<span class="hljs-string">{handleKeyPress}</span>
                    <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Type your message..."</span>
                /&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleSend}</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">FaPaperPlane</span> /&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
    );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Chatbot;
</code></pre>
<p>Use <code>&lt;Chatbot/&gt;</code> inside the <code>App.js</code> to load the Chatbot UI:</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"App"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Chatbot</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>Along with this, we’re also using CSS to make our chatbot a little more beautiful. You can refer to <a target="_blank" href="https://github.com/vikasrajputin/springboot-react-docker-chatbot/blob/main/chatbot-ui/src/App.css">App.css</a> and <a target="_blank" href="https://github.com/vikasrajputin/springboot-react-docker-chatbot/blob/main/chatbot-ui/src/Chatbot.css">Chatbot.css</a> for that.</p>
<h3 id="heading-run-the-frontend">Run the Frontend</h3>
<p>Use the <code>npm</code> command to run the application:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>This should run the frontend on the URL <code>http://localhost:3000</code>. The application is good to be tested now.</p>
<p>But running the backend and frontend separately is a bit of a hassle. So let’s use Docker to make the entire build process easier.</p>
<h2 id="heading-how-to-dockerize-the-application"><strong>How to Dockerize th</strong>e Applic<strong>ation</strong></h2>
<p>Let’s dockerize the entire application to help bundle and ship it anywhere hassle-free. You can install and configure Docker from the <a target="_blank" href="https://docs.docker.com/get-started/get-docker/">official Docker website</a>.</p>
<h3 id="heading-dockerize-the-backend">Dockerize the Backend</h3>
<p>The backend of our chatbot is built with Spring Boot, so we will create a <code>Dockerfile</code> that builds the Spring Boot app into an executable JAR file and runs it in a container.</p>
<p>Let’s write the <code>Dockerfile</code> for it:</p>
<pre><code class="lang-dockerfile"><span class="hljs-comment"># Start with an official image that has Java installed</span>
<span class="hljs-keyword">FROM</span> openjdk:<span class="hljs-number">17</span>-jdk-alpine

<span class="hljs-comment"># Set the working directory inside the container</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>

<span class="hljs-comment"># Copy the Maven/Gradle build file and source code into the container</span>
<span class="hljs-keyword">COPY</span><span class="bash"> target/chatbot-backend.jar /app/chatbot-backend.jar</span>

<span class="hljs-comment"># Expose the application’s port</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">8080</span>

<span class="hljs-comment"># Command to run the Spring Boot app</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"java"</span>, <span class="hljs-string">"-jar"</span>, <span class="hljs-string">"chatbot-backend.jar"</span>]</span>
</code></pre>
<ul>
<li><p><code>FROM openjdk:17-jdk-alpine</code>: This specifies that the container should be based on a lightweight Alpine Linux image that includes JDK 17, which is needed to run Spring Boot.</p>
</li>
<li><p><code>WORKDIR /app</code>: Sets the working directory inside the container to <code>/app</code>, where our application files will live.</p>
</li>
<li><p><code>COPY target/chatbot-backend.jar /app/chatbot-backend.jar</code>: Copies the built JAR file from your local machine (usually in the <code>target</code> folder after building the project with Maven or Gradle) into the container.</p>
</li>
<li><p><code>EXPOSE 8080</code>: This tells Docker that the application will listen for requests on port 8080.</p>
</li>
<li><p><code>CMD ["java", "-jar", "chatbot-backend.jar"]</code>: This specifies the command that will run when the container starts. It runs the JAR file that launches the Spring Boot app.</p>
</li>
</ul>
<h3 id="heading-dockerize-the-frontend">Dockerize the Frontend</h3>
<p>The front end of our chatbot is built using React, and we can Dockerize it by creating a Dockerfile that installs the necessary dependencies, builds the app, and serves it using a lightweight web server like NGINX.</p>
<p>Let’s write the <code>Dockerfile</code> for the React frontend:</p>
<pre><code class="lang-dockerfile"><span class="hljs-comment"># Use a Node image to build the React app</span>
<span class="hljs-keyword">FROM</span> node:<span class="hljs-number">16</span>-alpine AS build

<span class="hljs-comment"># Set the working directory inside the container</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>

<span class="hljs-comment"># Copy the package.json and install the dependencies</span>
<span class="hljs-keyword">COPY</span><span class="bash"> package.json package-lock.json ./</span>
<span class="hljs-keyword">RUN</span><span class="bash"> npm install</span>

<span class="hljs-comment"># Copy the rest of the application code and build it</span>
<span class="hljs-keyword">COPY</span><span class="bash"> . .</span>
<span class="hljs-keyword">RUN</span><span class="bash"> npm run build</span>

<span class="hljs-comment"># Use a lightweight NGINX server to serve the built app</span>
<span class="hljs-keyword">FROM</span> nginx:alpine
<span class="hljs-keyword">COPY</span><span class="bash"> --from=build /app/build /usr/share/nginx/html</span>

<span class="hljs-comment"># Expose port 80 for the web traffic</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">80</span>

<span class="hljs-comment"># Start NGINX</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"nginx"</span>, <span class="hljs-string">"-g"</span>, <span class="hljs-string">"daemon off;"</span>]</span>
</code></pre>
<ul>
<li><p><code>FROM node:16-alpine AS build</code>: This uses a lightweight Node.js image to build the React app. We install all dependencies and build the app inside this container.</p>
</li>
<li><p><code>WORKDIR /app</code>: Sets the working directory inside the container to <code>/app</code>.</p>
</li>
<li><p><code>COPY package.json package-lock.json ./</code>: Copies <code>package.json</code> and <code>package-lock.json</code> to install dependencies.</p>
</li>
<li><p><code>RUN npm install</code>: Installs the dependencies listed in the package.json.</p>
</li>
<li><p><code>COPY . .</code>: Copies all the frontend source code into the container.</p>
</li>
<li><p><code>RUN npm run build</code>: Builds the React application. The built files will be in a <code>build</code> folder.</p>
</li>
<li><p><code>FROM nginx:alpine</code>: After building the app, this line starts a new container based on the <code>nginx</code> web server.</p>
</li>
<li><p><code>COPY --from=build /app/build /usr/share/nginx/html</code>: Copies the built React app from the first container into the nginx container, placing it in the default folder where NGINX serves files.</p>
</li>
<li><p><code>EXPOSE 80</code>: This exposes port 80, which NGINX uses to serve web traffic.</p>
</li>
<li><p><code>CMD ["nginx", "-g", "daemon off;"]</code>: This starts the NGINX server in the foreground to serve your React app.</p>
</li>
</ul>
<h3 id="heading-docker-compose-to-run-both">Docker Compose to Run Both</h3>
<p>Now that we have separate Dockerfiles for the frontend and backend, we’ll use <code>docker-compose</code> to orchestrate running both containers at once.</p>
<p>Let’s write the <code>docker-compose.yml</code> file inside the root directory of the project:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">version:</span> <span class="hljs-string">'3'</span>
<span class="hljs-attr">services:</span>
  <span class="hljs-attr">backend:</span>
    <span class="hljs-attr">build:</span> <span class="hljs-string">./backend</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"8080:8080"</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">chatbot-network</span>

  <span class="hljs-attr">frontend:</span>
    <span class="hljs-attr">build:</span> <span class="hljs-string">./frontend</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"3000:80"</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">backend</span>
    <span class="hljs-attr">networks:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">chatbot-network</span>

<span class="hljs-attr">networks:</span>
  <span class="hljs-attr">chatbot-network:</span>
    <span class="hljs-attr">driver:</span> <span class="hljs-string">bridge</span>
</code></pre>
<ul>
<li><p><code>version: '3'</code>: This defines the version of Docker Compose being used.</p>
</li>
<li><p><code>services:</code>: This defines the services we want to run.</p>
<ul>
<li><p><code>backend</code>: This service builds the backend using the Dockerfile located in the <code>./backend</code> directory and exposes port 8080.</p>
</li>
<li><p><code>frontend</code>: This service builds the front end using the Dockerfile located in the <code>./frontend</code> directory. It maps port 3000 on the host to port 80 inside the container.</p>
</li>
</ul>
</li>
<li><p><code>depends_on:</code>: This makes sure the front end waits for the backend to be ready before it starts.</p>
</li>
<li><p><code>networks:</code>: This section defines a shared network so that both the backend and frontend can communicate with each other.</p>
</li>
</ul>
<h2 id="heading-run-the-application">Run the Application</h2>
<p>To run the entire application (both frontend and backend), you can use the following command:</p>
<pre><code class="lang-bash">docker-compose up --build
</code></pre>
<p>This command will:</p>
<ul>
<li><p>Build both the frontend and backend images.</p>
</li>
<li><p>Start both containers (backend on port 8080, frontend on port 3000).</p>
</li>
<li><p>Set up networking so that both services can communicate.</p>
</li>
</ul>
<p>Now, you can head over to <code>http://localhost:3000</code> load the Chatbot UI and start asking your questions to the AI.</p>
<h2 id="heading-congratulations">Congratulations 🎉</h2>
<p>You’ve successfully built a full-stack chatbot application using Spring Boot, React, Docker, and OpenAI.</p>
<p>The source code shown in the project is available on <a target="_blank" href="https://github.com/vikasrajputin/springboot-react-docker-chatbot">Github</a>, if you found it helpful give it a star, and feel free to fork it and play around with it.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Java Testing with Selenium ]]>
                </title>
                <description>
                    <![CDATA[ Are you looking to enhance your skills in automated web testing? We just published a comprehensive video course on the freeCodeCamp.org YouTube channel, designed to teach you how to use Selenium with Java using the Page Object Model. Created by Rex J... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-java-testing-with-selenium/</link>
                <guid isPermaLink="false">66ce4334e498db1304d6a333</guid>
                
                    <category>
                        <![CDATA[ selenium ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 27 Aug 2024 21:20:52 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724793636526/bd2fbf2d-1e0f-4a33-a77f-c8314d71330c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you looking to enhance your skills in automated web testing?</p>
<p>We just published a comprehensive video course on the <a target="_blank" href="http://freeCodeCamp.org">freeCodeCamp.org</a> YouTube channel, designed to teach you how to use Selenium with Java using the Page Object Model. Created by Rex Jones II, this course is perfect for developers and testers who want to master the art of automated web testing and ensure the functionality of web applications with precision and efficiency.</p>
<h3 id="heading-course-overview"><strong>Course Overview</strong></h3>
<p>This course is structured to guide you through the essentials of Selenium, a powerful tool for automating web browsers. Selenium allows you to simulate user interactions and verify the functionality of web applications, making it an indispensable tool for modern web testing. The course is divided into several parts, each focusing on different aspects of Selenium and Java, ensuring a thorough understanding of both the basics and advanced techniques.</p>
<p>Here are the core technologies and concepts in this course:</p>
<ol>
<li><p><strong>Selenium</strong>: At the heart of this course is Selenium, an open-source tool that automates web browsers. It supports various browsers and platforms, allowing testers to write test scripts in multiple programming languages, including Java. Selenium is widely used for functional testing, enabling testers to simulate user actions like clicking, typing, and navigating through web pages.</p>
</li>
<li><p><strong>Java</strong>: As one of the most popular programming languages, Java is known for its portability, scalability, and robustness. In this course, you'll learn how to leverage Java to write efficient and maintainable test scripts for web applications.</p>
</li>
<li><p><strong>Page Object Model (POM)</strong>: This design pattern is crucial for creating scalable and maintainable test automation frameworks. POM encourages the separation of test scripts from the page-specific code, making it easier to manage and update tests as web applications evolve.</p>
</li>
<li><p><strong>WebElements and JavaScriptExecutor</strong>: You'll explore how to interact with various web elements such as radio buttons, checkboxes, tables, links, drop-downs, and dates. Additionally, you'll learn how to use JavaScriptExecutor to perform actions like scrolling to elements, enhancing your ability to handle complex web pages.</p>
</li>
<li><p><strong>Selenium Interfaces and Methods</strong>: The course delves into various Selenium interfaces and methods, teaching you how to take screenshots, handle modals, alerts, frames, and windows. You'll also learn about different wait strategies like explicit, fluent, and implicit waits, which are essential for synchronizing your tests with web application behavior.</p>
</li>
<li><p><strong>Simulating User Interactions</strong>: Beyond basic interactions, the course covers how to simulate mouse movements and keyboard events, providing you with the skills to automate complex user scenarios.</p>
</li>
</ol>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>This course is a valuable resource for anyone looking to deepen their understanding of automated web testing using Selenium and Java. Whether you're a beginner or an experienced tester, the structured approach and practical examples will equip you with the skills needed to create robust and efficient test automation frameworks. Watch the full course <a target="_blank" href="https://youtu.be/QQliGCtqD2w">on the freeCodeCamp.org YouTube channel</a> (8-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/QQliGCtqD2w" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Java HashMaps Work – Internal Mechanics Explained ]]>
                </title>
                <description>
                    <![CDATA[ A HashMap is one of the most commonly used data structures in Java, and it's known for its efficiency. Data in a HashMap is stored in the form of key-value pairs. In this article, I will introduce you to HashMaps in Java. We will explore the common o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-java-hashmaps-work-internal-mechanics-explained/</link>
                <guid isPermaLink="false">66b677afa502c749ffbb5c36</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hashmap ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Collection Framework ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anjan Baradwaj ]]>
                </dc:creator>
                <pubDate>Fri, 09 Aug 2024 20:10:23 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Or_Fa550XaQ/upload/f4d40f1c8e94855d53776a3bb6179673.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>A <code>HashMap</code> is one of the most commonly used data structures in Java, and it's known for its efficiency. Data in a <code>HashMap</code> is stored in the form of key-value pairs.</p>
<p>In this article, I will introduce you to <code>HashMap</code>s in Java. We will explore the common operations of <code>HashMap</code> and then delve into how it operates internally. You will gain an understanding of the hash function and how index calculation takes place. Finally, we will look at the time complexities of the operations and touch upon the behavior in a concurrent environment.</p>
<h2 id="heading-what-is-a-hashmap-in-java"><strong>What is a</strong> <code>HashMap</code> in Java?</h2>
<p>A <code>HashMap</code> implements the <code>Map</code> interface, which is part of the Java collection framework. It's based on the concept of Hashing.</p>
<p>Hashing is a technique that transforms an input of arbitrary size into a fixed-size output using a hash function. The generated output is called the hash code and is represented by an integer value in Java. Hash codes are used for efficient lookup and storage operations in a <code>HashMap</code>.</p>
<h2 id="heading-common-operations"><strong>Common Operations</strong></h2>
<p>Like we discussed above, data in a <code>HashMap</code> is stored in the form of key-value pairs. The key is a unique identifier, and each key is associated with a value.</p>
<p>Below are some common operations supported by a <code>HashMap</code>. Let's understand what these methods do with some simple code examples:</p>
<h3 id="heading-insertion"><strong>Insertion</strong></h3>
<ul>
<li><p>This method inserts a new key-value pair to the <code>HashMap</code>.</p>
</li>
<li><p>The insertion order of the key-value pairs is not maintained.</p>
</li>
<li><p>During insertion, if a key is already present, the existing value will be replaced with the new value that is passed.</p>
</li>
<li><p>You can insert only one null key into the <code>HashMap</code>, but you can have multiple null values.</p>
</li>
</ul>
<p>The method signature for this operation is given below, followed by an example:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> V <span class="hljs-title">put</span><span class="hljs-params">(K key, V value)</span></span>
</code></pre>
<pre><code class="lang-java">Map&lt;String, Integer&gt; map = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
map.put(<span class="hljs-string">"apple"</span>, <span class="hljs-number">1</span>);
map.put(<span class="hljs-string">"banana"</span>, <span class="hljs-number">2</span>);
</code></pre>
<p>In the code above, we have a HashMap example where we add a key of type String and value of type Integer.</p>
<h3 id="heading-retrieval"><strong>Retrieval:</strong></h3>
<ul>
<li><p>Fetches the value associated with a given key.</p>
</li>
<li><p>Returns <code>null</code> if the key does not exist in the <code>HashMap</code>.</p>
</li>
</ul>
<p>The method signature for this operation is given below, followed by an example:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> V <span class="hljs-title">get</span><span class="hljs-params">(Object key)</span></span>
</code></pre>
<pre><code class="lang-java">Integer value = map.get(<span class="hljs-string">"apple"</span>); <span class="hljs-comment">// returns 1</span>
</code></pre>
<p>In the code above, we're retrieving the value associated with the key <code>apple</code>.</p>
<p>Other common operations include:</p>
<ul>
<li><p><code>remove</code>: Removes the key-value pair for the specified key. It returns <code>null</code> if the key is not found.</p>
</li>
<li><p><code>containsKey</code>: Checks if a specific key is present in the <code>HashMap</code>.</p>
</li>
<li><p><code>containsValue</code>: Checks if the specified value is present in the <code>HashMap</code>.</p>
</li>
</ul>
<h2 id="heading-internal-structure-of-a-hashmap"><strong>Internal Structure of a</strong> <code>HashMap</code></h2>
<p>Internally, a <code>HashMap</code> uses an array of buckets or bins. Each bucket is a linked list of type <code>Node</code>, which is used to represent the key-value pair of the <code>HashMap</code>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span>&lt;<span class="hljs-title">K</span>, <span class="hljs-title">V</span>&gt; </span>{
    <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> hash;
    <span class="hljs-keyword">final</span> K key;
    V value;
    Node&lt;K, V&gt; next;

    Node(<span class="hljs-keyword">int</span> hash, K key, V value, Node&lt;K, V&gt; next) {
        <span class="hljs-keyword">this</span>.hash = hash;
        <span class="hljs-keyword">this</span>.key = key;
        <span class="hljs-keyword">this</span>.value = value;
        <span class="hljs-keyword">this</span>.next = next;
    }
}
</code></pre>
<p>Above, you can see the structure of the <code>Node</code> class which is used to store the key-value pairs of the <code>HashMap</code>.</p>
<p>The <code>Node</code> class has the following fields:</p>
<ul>
<li><p><code>hash</code>: Refers to the <code>hashCode</code> of the key.</p>
</li>
<li><p><code>key</code>: Refers to the key of the key-value pair.</p>
</li>
<li><p><code>value</code>: Refers to the value associated with the key.</p>
</li>
<li><p><code>next</code>: Acts as a reference to the next node.</p>
</li>
</ul>
<p>The <code>HashMap</code> is fundamentally based on a hash table implementation, and its performance depends on two key parameters: initial capacity and load factor. The <a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/Hashtable.html">original javadocs</a> of the Hash table class define these two parameters as follows:</p>
<ul>
<li><p>The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created.</p>
</li>
<li><p>The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.</p>
</li>
</ul>
<p>Let's now try and understand how the basic operations, <code>put</code> and <code>get</code>, work in a <code>HashMap</code>.</p>
<h3 id="heading-hash-function"><strong>Hash Function</strong></h3>
<p>During the insertion (<code>put</code>) of a key-value pair, the <code>HashMap</code> first calculates the hash code of the key. The hash function then computes an integer for the key. Classes can use the <code>hashCode</code> method of the <code>Object</code> class or override this method and provide their own implementation. (Read about the hash code contract <a target="_blank" href="https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()">here</a>). The hash code is then XORed (eXclusive OR) with its upper 16 bits (h &gt;&gt;&gt; 16) to achieve a more uniform distribution.</p>
<p>XOR is a bitwise operation that compares two bits, resulting in 1 if the bits are different and 0 if they are the same. In this context, performing a bitwise XOR operation between the hash code and its upper 16 bits (obtained using the unsigned right shift <code>&gt;&gt;&gt;</code> operator) helps to mix the bits, leading to a more evenly distributed hash code.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> <span class="hljs-title">hash</span><span class="hljs-params">(Object key)</span> </span>{
    <span class="hljs-keyword">int</span> h;
    <span class="hljs-keyword">return</span> (key == <span class="hljs-keyword">null</span>) ? <span class="hljs-number">0</span> : (h = key.hashCode()) ^ (h &gt;&gt;&gt; <span class="hljs-number">16</span>);
}
</code></pre>
<p>Above, you can see the static hash method of the <code>HashMap</code> class.</p>
<p>The idea is to have a unique hash code for each key, but the hash function could produce the same hash code for different keys. This leads to a situation known as a collision. We will see how to handle collisions in the next section.</p>
<h3 id="heading-index-calculation"><strong>Index Calculation</strong></h3>
<p>Once the hash code for a key is generated, the <code>HashMap</code> calculates an index within the array of buckets to determine where the key-value pair will be stored. This is done using a bitwise AND operation, which is an efficient way to calculate the modulo when the array length is a power of two.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> index = (n - <span class="hljs-number">1</span>) &amp; hash;
</code></pre>
<p>Here, we're calculating the index where n is the length of the bucket array.</p>
<p>Once the index is calculated, the key is then stored at that index in the bucket array. However, if multiple keys end up having the same index, it causes a collision. In such a scenario, the <code>HashMap</code> handles it in one of two ways:</p>
<ul>
<li><p>Chaining/Linking: Each bucket in the array is a linked list of nodes. If a key already exists at a particular index and another key gets hashed to the same index, it gets appended to the list.</p>
</li>
<li><p>Treeify: If the number of nodes exceeds a certain threshold, the linked list is converted into a tree (This was introduced in Java 8).</p>
</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> TREEIFY_THRESHOLD = <span class="hljs-number">8</span>;
</code></pre>
<p>This is the threshold that determines treeification.</p>
<p>Therefore, it is essential to have a good hash function that uniformly distributes the keys across the buckets and minimizes the chances of collisions.</p>
<p>The retrieval (<code>get</code>) and deletion (<code>remove</code>) operations work similarly to the insertion (<code>put</code>) operation. Here's how:</p>
<ul>
<li><p>Retrieval (<code>get</code>): Computes the hash code using the hash function -&gt; calculates the index using the hash code -&gt; traverses the linked list or tree to find the node with the matching key.</p>
</li>
<li><p>Deletion (<code>remove</code>): Computes the hash code using the hash function -&gt; calculates the index using the hash code -&gt; removes the node from the linked list or tree.</p>
</li>
</ul>
<h3 id="heading-time-complexity"><strong>Time Complexity</strong></h3>
<p>The basic operations of a <code>HashMap</code>, such as <code>put</code>, <code>get</code>, and <code>remove</code>, generally offer constant time performance of O(1), assuming that the keys are uniformly distributed. In cases where there is poor key distribution and many collisions occur, these operations might degrade to a linear time complexity of O(n).</p>
<p>Under treeification, where long chains of collisions are converted into balanced trees, lookup operations can improve to a more efficient logarithmic time complexity of O(log n).</p>
<h3 id="heading-synchronization"><strong>Synchronization</strong></h3>
<p>The <code>HashMap</code> implementation is not synchronized. If multiple threads access a HashMap instance concurrently and iterate over the map, and if any one of the threads performs a structural modification (such as adding or removing a key-value mapping) on the map, it leads to a <code>ConcurrentModificationException</code>.</p>
<p>To prevent this, you can create a thread-safe instance using the <code>Collections.synchronizedMap</code> method.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In summary, understanding the internal workings of a <code>HashMap</code> is crucial for developers to make informed decisions. Knowing how a key is mapped, how collisions happen, and how they can be avoided helps you use the <code>HashMap</code> efficiently and effectively.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Comparable vs Comparator Interfaces in Java – Which Should You Use and When? ]]>
                </title>
                <description>
                    <![CDATA[ Sorting is a fundamental operation in programming, essential for organizing data in a specific order. In Java, built-in sorting methods provide efficient ways to sort primitive data types and arrays, making it easy to manage and manipulate collection... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/comparable-vs-comparator-explained-in-java/</link>
                <guid isPermaLink="false">66ba0e6e79b7f411df58dea3</guid>
                
                    <category>
                        <![CDATA[ algorithms ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ashutosh Krishna ]]>
                </dc:creator>
                <pubDate>Tue, 23 Jul 2024 13:13:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/comparable-comparator.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Sorting is a fundamental operation in programming, essential for organizing data in a specific order. In Java, built-in sorting methods provide efficient ways to sort primitive data types and arrays, making it easy to manage and manipulate collections of data. For instance, you can quickly sort an array of integers or a list of strings using methods like <code>Arrays.sort()</code> and <code>Collections.sort()</code>. </p>
<p>However, when it comes to sorting custom objects, such as instances of user-defined classes, the built-in sorting methods fall short. These methods don't know how to order objects based on custom criteria. This is where Java's <code>Comparable</code> and <code>Comparator</code> interfaces come into play, allowing developers to define and implement custom sorting logic tailored to specific requirements.</p>
<p>In this blog post, we'll explore how to use the <code>Comparable</code> and <code>Comparator</code> interfaces to sort custom objects in Java. I'll provide examples to illustrate the differences and use cases for each approach, helping you master custom sorting in your Java applications.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-sorting-methods-for-primitive-types">Sorting Methods for Primitive Types</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-comparable-interface">How to Use the Comparable Interface</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-comparator-interface">How to Use the Comparator Interface</a></li>
<li><a class="post-section-overview" href="#heading-comparable-vs-comparator">Comparable vs Comparator</a></li>
<li><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></li>
</ul>
<h2 id="heading-sorting-methods-for-primitive-types">Sorting Methods for Primitive Types</h2>
<p>Java provides a variety of built-in sorting methods that make it easy to sort primitive data types. These methods are highly optimized and efficient, allowing you to sort arrays and collections with minimal code. For primitive types, such as integers, floating-point numbers, and characters, the <code>Arrays.sort()</code> method is commonly used.</p>
<h3 id="heading-how-to-use-the-arrayssort-method">How to Use the Arrays.sort() Method</h3>
<p>The <code>Arrays.sort()</code> method sorts the specified array into ascending numerical order. This method uses a dual-pivot quicksort algorithm, which is faster and more efficient for most data sets.</p>
<p>Let's look at an example of sorting an array of integers and characters using <code>Arrays.sort()</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.Arrays;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PrimitiveSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">int</span>[] numbers = { <span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-number">8</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span> };
        System.out.println(<span class="hljs-string">"Original array: "</span> + Arrays.toString(numbers));

        Arrays.sort(numbers);
        System.out.println(<span class="hljs-string">"Sorted array: "</span> + Arrays.toString(numbers));

        <span class="hljs-keyword">char</span>[] characters = { <span class="hljs-string">'o'</span>, <span class="hljs-string">'i'</span>, <span class="hljs-string">'e'</span>, <span class="hljs-string">'u'</span>, <span class="hljs-string">'a'</span> };
        System.out.println(<span class="hljs-string">"Original array: "</span> + Arrays.toString(characters));

        Arrays.sort(characters);
        System.out.println(<span class="hljs-string">"Sorted array: "</span> + Arrays.toString(characters));
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original array: [5, 3, 8, 2, 1]
Sorted array: [1, 2, 3, 5, 8]
Original array: [o, i, e, u, a]
Sorted array: [a, e, i, o, u]
</code></pre>
<h3 id="heading-how-to-use-the-collectionssort-method">How to Use the Collections.sort() Method</h3>
<p>The <code>Collections.sort()</code> method is used to sort collections such as <code>ArrayList</code>. This method is also based on the natural ordering of the elements or a custom comparator.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Collections;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CollectionsSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        ArrayList&lt;String&gt; wordsList = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        wordsList.add(<span class="hljs-string">"banana"</span>);
        wordsList.add(<span class="hljs-string">"apple"</span>);
        wordsList.add(<span class="hljs-string">"cherry"</span>);
        wordsList.add(<span class="hljs-string">"date"</span>);
        System.out.println(<span class="hljs-string">"Original list: "</span> + wordsList);

        Collections.sort(wordsList);
        System.out.println(<span class="hljs-string">"Sorted list: "</span> + wordsList);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-plaintext">Original list: [banana, apple, cherry, date]
Sorted list: [apple, banana, cherry, date]
</code></pre>
<h3 id="heading-limitations-with-custom-classes">Limitations with Custom Classes</h3>
<p>While Java's built-in sorting methods, such as <code>Arrays.sort()</code> and <code>Collections.sort()</code>, are powerful and efficient for sorting primitive types and objects with natural ordering (like <code>String</code>), they fall short when it comes to sorting custom objects. These methods do not inherently know how to order user-defined objects because there is no natural way for them to compare these objects.</p>
<p>For example, consider a simple <code>Person</code> class that has <code>name</code>, <code>age</code>, and <code>weight</code> attributes:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Person [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }
}
</code></pre>
<p>If we try to sort a list of <code>Person</code> objects using <code>Arrays.sort()</code> or <code>Collections.sort()</code>, we will encounter a compilation error because these methods do not know how to compare <code>Person</code> objects:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSorting</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Person&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people);
        System.out.println(<span class="hljs-string">"Sorted people list: "</span> + people);
    }
}
</code></pre>
<p>Compilation Error:</p>
<pre><code class="lang-bash">java: no suitable method found <span class="hljs-keyword">for</span> sort(java.util.List&lt;tutorial.Person&gt;)
    method java.util.Collections.&lt;T&gt;sort(java.util.List&lt;T&gt;) is not applicable
      (inference variable T has incompatible bounds
        equality constraints: tutorial.Person
        lower bounds: java.lang.Comparable&lt;? super T&gt;)
    method java.util.Collections.&lt;T&gt;sort(java.util.List&lt;T&gt;,java.util.Comparator&lt;? super T&gt;) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ <span class="hljs-keyword">in</span> length))
</code></pre>
<p>The error occurs because the <code>Person</code> class does not implement the <code>Comparable</code> interface, and there is no way for the sorting method to know how to compare two <code>Person</code> objects.</p>
<p>To sort custom objects like <code>Person</code>, we need to provide a way to compare these objects. Java offers two main approaches to achieve this:</p>
<ol>
<li>Implementing the <code>Comparable</code> Interface: This allows a class to define its natural ordering by implementing the <code>compareTo</code> method.</li>
<li>Using the <code>Comparator</code> Interface: This allows us to create separate classes or lambda expressions to define multiple ways of comparing objects.</li>
</ol>
<p>We will explore both approaches in the upcoming sections, starting with the <code>Comparable</code> interface.</p>
<h2 id="heading-how-to-use-the-comparable-interface">How to Use the Comparable Interface</h2>
<p>Java provides a <code>Comparable</code> interface to define a natural ordering for objects of a user-defined class. By implementing the <code>Comparable</code> interface, a class can provide a single natural ordering that can be used to sort its instances. This is particularly useful when you need a default way to compare and sort objects.</p>
<h3 id="heading-overview">Overview</h3>
<p>The <code>Comparable</code> interface contains a single method, <code>compareTo()</code>, which compares the current object with the specified object for order. The method returns:</p>
<ul>
<li>A negative integer if the current object is less than the specified object.</li>
<li>Zero if the current object is equal to the specified object.</li>
<li>A positive integer if the current object is greater than the specified object.</li>
</ul>
<h3 id="heading-how-comparable-allows-for-a-single-natural-ordering-of-objects">How Comparable Allows for a Single Natural Ordering of Objects</h3>
<p>By implementing the <code>Comparable</code> interface, a class can ensure that its objects have a natural ordering. This allows the objects to be sorted using methods like <code>Arrays.sort()</code> or <code>Collections.sort()</code> without the need for a separate comparator.</p>
<p>Let's implement the <code>Comparable</code> interface in a new <code>PersonV2</code> class, comparing by age.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonV2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparable</span>&lt;<span class="hljs-title">PersonV2</span>&gt; </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PersonV2</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"PersonV2 [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compareTo</span><span class="hljs-params">(PersonV2 other)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.age - other.age;
    }
}
</code></pre>
<p>In this implementation, the <code>compareTo()</code> method compares the <code>age</code> attribute of the current <code>PersonV2</code> object with the <code>age</code> attribute of the specified <code>PersonV2</code> object by subtracting one age from the other. By using the expression <code>this.age - other.age</code>, we’re effectively implementing this logic as follows:</p>
<ul>
<li>If <code>this.age</code> is less than <code>other.age</code>, the result will be negative.</li>
<li>If <code>this.age</code> is equal to <code>other.age</code>, the result will be zero.</li>
<li>If <code>this.age</code> is greater than <code>other.age</code>, the result will be positive.</li>
</ul>
<p><strong>Note</strong>: We can also use <code>Integer.compare(this.age, other.age)</code> instead of performing the arithmetic operation manually.</p>
<p>Now that the <code>PersonV2</code> class implements the <code>Comparable</code> interface, we can sort a list of <code>PersonV2</code> objects using <code>Collections.sort()</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSortingV2</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;PersonV2&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> PersonV2(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people);
        System.out.println(<span class="hljs-string">"Sorted people list: "</span> + people);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original people list: [PersonV2 [name=Alice, age=30, weight=65.5 kgs], PersonV2 [name=Bob, age=25, weight=75.0 kgs], PersonV2 [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list: [PersonV2 [name=Bob, age=25, weight=75.0 kgs], PersonV2 [name=Alice, age=30, weight=65.5 kgs], PersonV2 [name=Charlie, age=35, weight=80.0 kgs]]
</code></pre>
<p>In this example, the <code>PersonV2</code> objects are sorted in ascending order of age using the <code>Collections.sort()</code> method, which relies on the natural ordering defined by the <code>compareTo()</code> method in the <code>PersonV2</code> class.</p>
<h3 id="heading-limitations-of-comparable">Limitations of Comparable</h3>
<p>While the <code>Comparable</code> interface provides a way to define a natural ordering for objects, it has several limitations that can restrict its use in practical applications. Understanding these limitations can help us determine when to use other mechanisms, such as the <code>Comparator</code> interface, to achieve more flexible sorting.</p>
<ul>
<li><strong>Single Natural Ordering</strong>: The primary limitation of <code>Comparable</code> is that it allows only one natural ordering for the objects of a class. When you implement <code>Comparable</code>, you define a single way to compare objects, which is used whenever the objects are sorted or compared. This can be restrictive if you need to sort objects in multiple ways.</li>
<li><strong>Inflexibility</strong>: If you need to sort objects by different attributes or in different orders, you will have to modify the class or create new implementations of <code>Comparable</code>. This inflexibility can lead to a proliferation of comparison methods and can make the code harder to maintain.</li>
<li><strong>Non-Adaptable</strong>: Once a class implements <code>Comparable</code>, the natural ordering is fixed and cannot be easily changed. For instance, if your <code>PersonV2</code> class initially sorts by age but later you need to sort by weight or name, you have to either change the <code>compareTo()</code> method or create a new version of the class.</li>
</ul>
<p>This is where the <code>Comparator</code> interface comes into play. To define multiple ways of comparing objects, we can use the <code>Comparator</code> interface, which we will explore in the next section.</p>
<h2 id="heading-how-to-use-the-comparator-interface">How to Use the Comparator Interface</h2>
<p>The <code>Comparator</code> interface in Java provides a way to define multiple ways of comparing and sorting objects. Unlike the <code>Comparable</code> interface, which allows only a single natural ordering, <code>Comparator</code> is designed to offer flexibility by allowing multiple sorting strategies. This makes it particularly useful for scenarios where objects need to be sorted in different ways.</p>
<h3 id="heading-overview-1">Overview</h3>
<p>The <code>Comparator</code> interface defines a single method, <code>compare()</code>, which compares two objects and returns:</p>
<ul>
<li>A negative integer if the first object is less than the second object.</li>
<li>Zero if the first object is equal to the second object.</li>
<li>A positive integer if the first object is greater than the second object.</li>
</ul>
<p>This method provides a way to define custom ordering for objects without modifying the class itself.</p>
<h3 id="heading-how-comparator-allows-for-multiple-ways-of-ordering-objects">How Comparator Allows for Multiple Ways of Ordering Objects</h3>
<p>The <code>Comparator</code> interface allows you to create multiple <code>Comparator</code> instances, each defining a different ordering for objects. This flexibility means that you can sort objects by various attributes or in different orders without altering the object's class.</p>
<p>Let's implement multiple <code>Comparator</code> instances for the <code>Person</code> class. We'll define comparators for sorting by name, by age, and by weight. First, we need to update the <code>Person</code> class to include getters and ensure that attributes are accessible.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    String name;
    <span class="hljs-keyword">int</span> age;
    <span class="hljs-keyword">double</span> weight;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age, <span class="hljs-keyword">double</span> weight)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        <span class="hljs-keyword">this</span>.weight = weight;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getWeight</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> weight;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Person [name="</span> + name + <span class="hljs-string">", age="</span> + age + <span class="hljs-string">", weight="</span> + weight + <span class="hljs-string">" kgs]"</span>;
    }
}
</code></pre>
<h4 id="heading-comparator-by-name"><strong>Comparator by Name</strong></h4>
<p>This comparator sorts <code>Person</code> objects alphabetically by their <code>name</code>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonNameComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> p1.getName().compareTo(p2.getName());
    }
}
</code></pre>
<h4 id="heading-comparator-by-age">Comparator by Age</h4>
<p>This comparator sorts <code>Person</code> objects by their <code>age</code>, in ascending order.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonAgeComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> p1.getAge() - p2.getAge();
    }
}
</code></pre>
<h4 id="heading-comparator-by-weight">Comparator by Weight</h4>
<p>This comparator sorts <code>Person</code> objects by their <code>weight</code>, in ascending order.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial.comparator;

<span class="hljs-keyword">import</span> tutorial.Person;

<span class="hljs-keyword">import</span> java.util.Comparator;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonWeightComparator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Comparator</span>&lt;<span class="hljs-title">Person</span>&gt; </span>{

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">compare</span><span class="hljs-params">(Person p1, Person p2)</span> </span>{
        <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>) (p1.getWeight() - p2.getWeight());
    }
}
</code></pre>
<p>Now, here’s how you can use these <code>Comparator</code> instances to sort a list of <code>Person</code> objects:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> tutorial;

<span class="hljs-keyword">import</span> tutorial.comparator.PersonAgeComparator;
<span class="hljs-keyword">import</span> tutorial.comparator.PersonNameComparator;
<span class="hljs-keyword">import</span> tutorial.comparator.PersonWeightComparator;

<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomClassSortingV3</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Person&gt; people = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;(Arrays.asList(
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">30</span>, <span class="hljs-number">65.5</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">25</span>, <span class="hljs-number">75.0</span>),
                <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>, <span class="hljs-number">80.0</span>)
        ));
        System.out.println(<span class="hljs-string">"Original people list: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonNameComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by name: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonAgeComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by age: "</span> + people);

        Collections.sort(people, <span class="hljs-keyword">new</span> PersonWeightComparator());
        System.out.println(<span class="hljs-string">"Sorted people list by weight: "</span> + people);
    }
}
</code></pre>
<p>Output:</p>
<pre><code class="lang-bash">Original people list: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by name: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by age: [Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
Sorted people list by weight: [Person [name=Alice, age=30, weight=65.5 kgs], Person [name=Bob, age=25, weight=75.0 kgs], Person [name=Charlie, age=35, weight=80.0 kgs]]
</code></pre>
<p>In this example, the <code>Comparator</code> instances allow sorting the <code>Person</code> objects by different attributes: name, age, and weight. This demonstrates how the <code>Comparator</code> interface enables flexible and versatile sorting strategies for a class.</p>
<h2 id="heading-comparable-vs-comparator">Comparable vs Comparator</h2>
<p>When sorting objects in Java, you have two primary options: the <code>Comparable</code> and <code>Comparator</code> interfaces. Understanding the differences between these two interfaces can help you choose the right approach for your needs. Please note that this is also a very important interview question.</p>
<h3 id="heading-comparison">Comparison</h3>
<p>Here’s a table comparing and contrasting the <code>Comparable</code> and <code>Comparator</code> interfaces in Java:</p>
<table><tbody><tr><th><p>Feature</p></th><th><p>Comparable</p></th><th><p>Comparator</p></th></tr><tr><td><p>Definition</p></td><td><p>Provides a single, natural ordering for objects</p></td><td><p>Provides multiple ways to compare objects</p></td></tr><tr><td><p>Method</p></td><td><p>compareTo(T o)</p></td><td><p>compare(T o1, T o2)</p></td></tr><tr><td><p>Implementation</p></td><td><p>Implemented within the class itself</p></td><td><p>Implemented outside the class</p></td></tr><tr><td><p>Sorting Criteria</p></td><td><p>One default natural ordering</p></td><td><p>Multiple sorting criteria</p></td></tr><tr><td><p>Flexibility</p></td><td><p>Limited to one way of comparing objects</p></td><td><p>Flexible; multiple comparators can be defined</p></td></tr><tr><td><p>Class Modification</p></td><td><p>Requires modifying the class to implement <code>Comparable</code></p></td><td><p>Does not require modifying the class</p></td></tr><tr><td><p>Use Case</p></td><td><p>Use when there is a clear, natural ordering (e.g., sorting employees by ID)</p></td><td><p>Use when different sorting orders are needed or when you cannot modify the class</p></td></tr></tbody></table>

<h3 id="heading-benefits-and-drawbacks-of-each-approach">Benefits and Drawbacks of Each Approach</h3>
<h4 id="heading-comparable-operator">Comparable Operator</h4>
<h5 id="heading-benefits">Benefits:</h5>
<ul>
<li><strong>Simplicity</strong>: Provides a default sorting order that is easy to implement and use.</li>
<li><strong>Built-in</strong>: The natural ordering is part of the class itself, so it is always available and used by default in sorting methods.</li>
</ul>
<h4 id="heading-drawbacks">Drawbacks:</h4>
<ul>
<li><strong>Single Ordering</strong>: Can only define one way to compare objects. If different sorting orders are needed, the class must be modified or additional <code>Comparator</code> instances must be used.</li>
<li><strong>Class Modification</strong>: Requires altering the class to implement <code>Comparable</code>, which might not be feasible if the class is part of a library or if its natural ordering is not clear.</li>
</ul>
<h4 id="heading-comparator">Comparator</h4>
<h5 id="heading-benefits-1">Benefits:</h5>
<ul>
<li><strong>Flexibility</strong>: Allows for multiple sorting orders and criteria, which can be defined externally and used as needed.</li>
<li><strong>Non-invasive</strong>: Does not require modification of the class itself, making it suitable for classes you do not control or when you need different sorting options.</li>
</ul>
<h5 id="heading-drawbacks-1">Drawbacks:</h5>
<ul>
<li><strong>Complexity</strong>: Requires creating and managing multiple <code>Comparator</code> instances, which can add complexity to the code.</li>
<li><strong>Overhead</strong>: Might introduce additional overhead if many comparators are used, especially if they are created on the fly.</li>
</ul>
<p>In summary, <code>Comparable</code> is best used when a class has a natural ordering that makes sense for most use cases. </p>
<p><code>Comparator</code>, on the other hand, provides flexibility for sorting by multiple criteria and is useful when the class does not have a natural ordering or when different sorting orders are needed. </p>
<p>Choosing between <code>Comparable</code> and <code>Comparator</code> depends on your specific sorting needs and whether you need a single default order or multiple flexible sorting options.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Understanding and utilizing both <code>Comparable</code> and <code>Comparator</code> can significantly enhance your ability to manage and manipulate object collections in Java. By applying these concepts, you can create more flexible and powerful sorting mechanisms.</p>
<p>To solidify your understanding, try implementing both <code>Comparable</code> and <code>Comparator</code> in real-world scenarios. Experiment with different classes and sorting criteria to see how each approach works in practice.</p>
<h3 id="heading-links-to-official-java-documentation">Links to Official Java Documentation:</h3>
<ul>
<li><a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html">Java Comparable Interface</a></li>
<li><a target="_blank" href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html">Java Comparator Interface</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
