<?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[ Springboot - 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[ Springboot - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 02 Jun 2026 11:12:43 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/springboot/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <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[ 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="739" height="415" 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="828" height="477" 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[ 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[ Build Smarter Spring Boot Applications with Spring AI ]]>
                </title>
                <description>
                    <![CDATA[ If you're a Java developer working with Spring Boot, you might wonder how to harness the power of AI in your projects. The good news is that Spring AI, an emerging tool within the Spring ecosystem, offers seamless AI integrations that are both access... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-smarter-spring-boot-applications-with-spring-ai/</link>
                <guid isPermaLink="false">67644173f5e203def9a9e2b4</guid>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Thu, 19 Dec 2024 15:53:23 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1734623587345/f6f5386a-7315-4507-8c34-99b2ffde1dbe.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're a Java developer working with Spring Boot, you might wonder how to harness the power of AI in your projects. The good news is that Spring AI, an emerging tool within the Spring ecosystem, offers seamless AI integrations that are both accessible and robust. Whether you want to add natural language processing (NLP) capabilities, generate images on the fly, or transcribe audio, Spring AI provides the tools to make it happen.</p>
<p>We just published a course on the <a target="_blank" href="http://freeCodeCamp.org">freeCodeCamp.org</a> YouTube channel that will teach you all about integrating AI capabilities into your Spring Boot applications using <strong>Spring AI</strong>. Developed by Faisal Memon, this hands-on course goes beyond theory, guiding you through practical projects that showcase the real-world potential of AI in application development. By the end of the course, you'll have built a variety of projects that combine AI creativity and productivity, giving you a solid foundation in leveraging AI technologies with Spring Boot.</p>
<h3 id="heading-what-youll-build"><strong>What You'll Build</strong></h3>
<p>The course is structured around two key projects, designed to give you a comprehensive understanding of how to apply AI in different contexts:</p>
<ol>
<li><p><strong>Project 1: Stock Photo Generator, Q&amp;A Bot, and Recipe Generator</strong></p>
<ul>
<li><p>This project blends creativity and utility by exploring three different AI-driven tools:</p>
<ul>
<li><p><strong>Stock Photo Generator</strong>: Generate high-quality images using AI.</p>
</li>
<li><p><strong>Q&amp;A Bot</strong>: Build a chatbot capable of answering questions based on user input.</p>
</li>
<li><p><strong>Recipe Generator</strong>: Create a tool that suggests recipes based on ingredients, powered by machine learning.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Project 2: Audio Transcriber</strong></p>
<ul>
<li>Develop a transcription tool that converts spoken words into written text. This project demonstrates how to incorporate state-of-the-art speech recognition and processing technologies within a Spring Boot application.</li>
</ul>
</li>
</ol>
<h3 id="heading-course-outline"><strong>Course Outline</strong></h3>
<p>This course is packed with detailed tutorials and step-by-step guidance. Here are the key topics and sections you’ll cover:</p>
<ol>
<li><p><strong>Introduction to Spring AI</strong> and understanding the core concepts.</p>
</li>
<li><p><strong>Setting Up Projects</strong> with proper configurations and dependencies.</p>
</li>
<li><p><strong>Integrating OpenAI APIs</strong> for NLP and image generation.</p>
</li>
<li><p><strong>Building Services and Controllers</strong> for chat and image generation features.</p>
</li>
<li><p><strong>Parameterizing and Customizing Outputs</strong> to enhance functionality.</p>
</li>
<li><p><strong>Creating a React Frontend</strong> to interact with your Spring Boot backend.</p>
</li>
<li><p><strong>Handling CORS Issues</strong> and other common development challenges.</p>
</li>
<li><p><strong>Developing the Audio Transcriber Tool</strong> with end-to-end integration.</p>
</li>
<li><p><strong>Styling Your Applications</strong> with CSS and frontend best practices.</p>
</li>
</ol>
<h3 id="heading-why-learn-spring-ai"><strong>Why Learn Spring AI?</strong></h3>
<p>Spring AI offers a streamlined way to integrate AI into your Java applications without reinventing the wheel. It provides standardized ways to access powerful AI models (like OpenAI’s GPT and image generation APIs) within familiar Spring Boot paradigms. This means you can leverage your existing Spring skills while unlocking new AI-driven possibilities. From chatbots to image generation and transcription tools, the potential applications are vast and relevant to modern software development needs.</p>
<p>If you’re ready to level up your Spring Boot applications with cutting-edge AI features, head over to the <a target="_blank" href="https://youtu.be/9Crrhz0pm8s">freeCodeCamp.org YouTube channel</a> and watch this course (5-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/9Crrhz0pm8s" 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 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 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="3098" height="1810" 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="3124" height="1844" 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="3124" height="1850" 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="3128" height="1852" 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="3108" height="1858" 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="3126" height="1850" 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="3122" height="1854" 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="3124" height="1842" 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="3122" height="1852" 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="3114" height="1834" 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="3150" height="1608" 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="3152" height="1610" 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="1922" height="1144" 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="1884" height="822" 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="1922" height="1202" 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="729" height="883" 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="1903" height="537" 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="1511" height="883" 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[ Build a Shopping Cart Backend with Spring Boot and Spring Security ]]>
                </title>
                <description>
                    <![CDATA[ We just posted a course on the freeCodeCamp.org YouTube channel that is designed to help you master Spring Boot and Spring Security by guiding you through the development of a fully functional shopping cart backend application. Samson Alfred created ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-shopping-cart-backend-with-spring-boot-and-spring-security/</link>
                <guid isPermaLink="false">66cf6c3ca4e795916eba44b0</guid>
                
                    <category>
                        <![CDATA[ Springboot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 28 Aug 2024 18:28:12 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724869670804/390e87e2-487d-410f-84f9-20f636b72439.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We just posted a course on the freeCodeCamp.org YouTube channel that is designed to help you master Spring Boot and Spring Security by guiding you through the development of a fully functional shopping cart backend application. Samson Alfred created this course.</p>
<h3 id="heading-course-overview"><strong>Course Overview</strong></h3>
<p>This course is perfect for developers looking to deepen their understanding of Spring Boot and Spring Security. You'll start from scratch, generating a new project, and progress through creating and mapping entity classes, implementing CRUD operations, and developing services and controllers for products, categories, and carts. By the end of the course, you'll have a robust backend application and a solid grasp of key Spring technologies.</p>
<p>Here are the key technologies featured int his coruse.</p>
<p><strong>Spring Boot</strong>: Spring Boot is a powerful framework that simplifies the process of building production-ready applications. It provides a range of features, including auto-configuration and an embedded server, which help streamline the development process. In this course, you'll learn how to leverage Spring Boot to quickly set up and manage your shopping cart backend.</p>
<p><strong>Spring Security</strong>: Security is a critical aspect of any application, and Spring Security is a comprehensive framework that addresses authentication and authorization concerns. You'll learn how to integrate Spring Security into your project, ensuring that your application is protected against common security threats.</p>
<p><strong>JWT (JSON Web Tokens)</strong>: JWT is a compact, URL-safe means of representing claims to be transferred between two parties. In this course, you'll discover how to use JWT for secure user authentication, allowing your application to verify user identities and manage sessions effectively.</p>
<h3 id="heading-course-content-highlights"><strong>Course Content Highlights</strong></h3>
<ul>
<li><p><strong>Project Generation</strong>: Learn how to set up a new Spring Boot project and configure it for development.</p>
</li>
<li><p><strong>Entity Classes and CRUD Operations</strong>: Understand how to create and map entity classes, and implement CRUD operations for managing products, categories, and carts.</p>
</li>
<li><p><strong>Service and Controller Development</strong>: Develop robust services and controllers to handle business logic and API requests.</p>
</li>
<li><p><strong>Security Integration</strong>: Integrate Spring Security and JWT to secure your application, implementing user authentication and authorization.</p>
</li>
<li><p><strong>Testing and Debugging</strong>: Test your APIs and fix any errors to ensure your application runs smoothly.</p>
</li>
<li><p><strong>Project Wrap-Up</strong>: Clean up your project and conduct final security testing to ensure everything is in place.</p>
</li>
</ul>
<h3 id="heading-conclusion"><strong>Conclusion</strong></h3>
<p>By the end of this course, you'll have a comprehensive understanding of how to build a secure and efficient shopping cart backend using Spring Boot and Spring Security. Whether you're a beginner or an experienced developer, this course offers valuable insights and practical skills that you can apply to your projects.</p>
<p>Watch the full course <a target="_blank" href="https://youtu.be/oGhc5Z-WJSw">on the freeCodeCamp.org YouTube channel</a> (10-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/oGhc5Z-WJSw" 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>
        
    </channel>
</rss>
