<?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[ spring-boot - 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[ spring-boot - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 11 May 2026 10:29:22 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/spring-boot/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ OpenFeign vs WebClient: How to Choose a REST Client for Your Spring Boot Project ]]>
                </title>
                <description>
                    <![CDATA[ When building microservices with Spring Boot, you’ll have to decide how the services will communicate with one another. The basic choices in terms of protocols are Messaging and REST. In this article we’ll discuss tools based on REST, which is a comm... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/best-choice-openfeign-or-webclient/</link>
                <guid isPermaLink="false">6841f2c63a801418642db429</guid>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Casari ]]>
                </dc:creator>
                <pubDate>Thu, 05 Jun 2025 19:40:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749152217156/dc3e8896-b084-4bec-a549-b51a821f7d69.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When building microservices with Spring Boot, you’ll have to decide how the services will communicate with one another. The basic choices in terms of protocols are Messaging and <a target="_blank" href="https://www.freecodecamp.org/news/tag/rest-api/">REST</a>. In this article we’ll discuss tools based on REST, which is a common protocol for microservices. Two well-known tools are <a target="_blank" href="https://codingstrain.com/rest-clients-with-openfeign-how-to-implement-them/"><strong>OpenFeign</strong></a> and <a target="_blank" href="https://docs.spring.io/spring-framework/reference/web/webflux-webclient.html"><strong>WebClient</strong></a>.</p>
<p>You’ll learn how they differ in their approaches, use cases, and design. You’ll then have the necessary information to make a proper choice.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-introduction-to-openfeign">Introduction to OpenFeign</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-introduction-to-webclient">Introduction to WebClient</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-main-differences">Main Differences</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-performance-considerations">Performance Considerations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-use-cases">Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-introduction-to-openfeign">Introduction to OpenFeign</h2>
<p>OpenFeign is an HTTP client tool developed originally by Netflix and now maintained as an open-source community project. In the Spring Cloud ecosystem, OpenFeign allows you to define REST clients using annotated Java interfaces, reducing boilerplate code.</p>
<p>A basic OpenFeign client looks like this:</p>
<pre><code class="lang-java"><span class="hljs-meta">@FeignClient(name = "book-service")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">BookClient</span> </span>{
    <span class="hljs-meta">@GetMapping("/books/{id}")</span>
    <span class="hljs-function">User <span class="hljs-title">getBookById</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable("id")</span> Long id)</span></span>;
}
</code></pre>
<p>You can then inject <code>BookClient</code> like any Spring Bean:</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">BookService</span> </span>{
    <span class="hljs-meta">@Autowired</span>
    <span class="hljs-keyword">private</span> BookClient bookClient;

    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getBook</span><span class="hljs-params">(Long id)</span> </span>{
        <span class="hljs-keyword">return</span> bookClient.getBookById(id);
    }
}
</code></pre>
<p>OpenFeign is well integrated with Spring Cloud Discovery Service (Eureka), Spring Cloud Config, and Spring Cloud LoadBalancer. This makes it perfect for service-to-service calls in a microservice architecture based on Spring Cloud. It has several important features.</p>
<ul>
<li><p>Declarative syntax: It uses interfaces and annotations to define HTTP clients, avoiding manual request implementation.</p>
</li>
<li><p>Spring Cloud integration: It integrates well with the components of Spring Cloud, like Service Discovery (Eureka), Spring Config, and Load Balancer.</p>
</li>
<li><p>Retry and fallback mechanisms: It can be easily integrated with Spring Cloud Circuit Breaker or Resilience4j.</p>
</li>
<li><p>Custom configurations: You can customize many aspects, like headers, interceptors, logging, timeouts, and encoders/decoders.</p>
</li>
</ul>
<h2 id="heading-introduction-to-webclient">Introduction to WebClient</h2>
<p>WebClient is a reactive HTTP client, and it’s part of the <a target="_blank" href="https://medium.com/@bolot.89/an-introduction-to-spring-webflux-reactive-programming-made-easy-f70050f4c6c6"><strong>Spring WebFlux</strong></a> module. It is mainly based on non-blocking asynchronous HTTP communication, but it can also deal with synchronous calls.</p>
<p>While OpenFeign follows a declarative design, WebClient offers an imperative, fluent API.</p>
<p>Here’s a basic example of using WebClient synchronously:</p>
<pre><code class="lang-java">WebClient client = WebClient.create(<span class="hljs-string">"http://book-service"</span>);

User user = client.get()
        .uri(<span class="hljs-string">"/books/{id}"</span>, <span class="hljs-number">1L</span>)
        .retrieve()
        .bodyToMono(Book.class)
        .block(); <span class="hljs-comment">// synchronous</span>
</code></pre>
<p>Or asynchronously:</p>
<pre><code class="lang-java">Mono&lt;User&gt; bookMono = client.get()
        .uri(<span class="hljs-string">"/books/{id}"</span>, <span class="hljs-number">1L</span>)
        .retrieve()
        .bodyToMono(Book.class);
</code></pre>
<p>Being designed to be non-blocking and reactive, WebClient gives its best with high-throughput, I/O intensive operations. This is particularly true if the entire stack is reactive.</p>
<h2 id="heading-main-differences">Main Differences</h2>
<h3 id="heading-programming-model">Programming Model</h3>
<ul>
<li><p><strong>OpenFeign</strong>: Declarative. You just have to define interfaces. The framework will provide implementations of those interfaces.</p>
</li>
<li><p><strong>WebClient</strong>: Programmatic. You use an imperative, fluent API to implement HTTP calls.</p>
</li>
</ul>
<h3 id="heading-synchronousasynchronous-calls">Synchronous/Asynchronous Calls</h3>
<ul>
<li><p><strong>OpenFeign</strong>: Based on synchronous calls. You require customization or third-party extensions to implement asynchronous behavior.</p>
</li>
<li><p><strong>WebClient</strong>: Asynchronous and non-blocking. It fits well with systems based on a reactive stack.</p>
</li>
</ul>
<h3 id="heading-integration-with-spring-cloud">Integration with Spring Cloud</h3>
<ul>
<li><p><strong>OpenFeign</strong>: It integrates well with the Spring Cloud stack, such as service discovery (Eureka), client-side load balancing, and circuit breakers.</p>
</li>
<li><p><strong>WebClient</strong>: It integrates with Spring Cloud, but additional configuration is required for some features, like load balancing.</p>
</li>
</ul>
<h3 id="heading-boilerplate-code">Boilerplate Code</h3>
<ul>
<li><p><strong>OpenFeign</strong>: You have to define only the endpoint with Interfaces, and the rest is implemented automatically by the framework.</p>
</li>
<li><p><strong>WebClient</strong>: You have a little more code to write and more explicit configuration.</p>
</li>
</ul>
<h3 id="heading-error-handling">Error Handling</h3>
<ul>
<li><p><strong>OpenFeign</strong>: You require custom error handling or fallbacks by <a target="_blank" href="https://stackoverflow.com/questions/39349591/what-is-hystrix-in-spring">Hystrix</a> or <a target="_blank" href="https://codingstrain.com/how-to-implement-circuit-breaker-pattern-with-spring-cloud/">Resilience4j</a>.</p>
</li>
<li><p><strong>WebClient</strong>: Error handling is more flexible with operators like onStatus() and exception mapping.</p>
</li>
</ul>
<h2 id="heading-performance-considerations">Performance Considerations</h2>
<p>When high throughput is not the main concern, OpenFeign is a better choice, since it is well-suited for traditional, blocking applications where simplicity and developer productivity are more important than maximum throughput.</p>
<p>When you have a large number of concurrent requests, such as hundreds or thousands per second, with OpenFeign, you can encounter thread exhaustion problems unless you significantly increase the thread pool sizes. This results in higher memory consumption and increased CPU overhead. For a monolithic application with blocking operations, OpenFeign is better, because mixing blocking and non-blocking models is discouraged.</p>
<p>WebClient is more suitable if your application is I/O bound and has to handle heavy loads. Its non-blocking, reactive nature is excellent for those scenarios, because it can handle more concurrent requests with fewer threads. WebClient does not block a thread while waiting for a response, it releases it immediately to be reused for other work. It also provides a reactive feature called backpressure, used to control the data flow rate. This is useful when dealing with large data streams or when the speed at which clients consume data is too low. It's suited for applications that need to manage thousands of concurrent requests. It is more complex, though, and has a steeper learning curve.</p>
<h2 id="heading-use-cases">Use Cases</h2>
<p><strong>Use OpenFeign When:</strong></p>
<ul>
<li><p>You need to call other services in a Spring Cloud microservice architecture, with tight integration with Service Discovery and Spring Cloud LoadBalancer.</p>
</li>
<li><p>You prefer productivity and simplicity.</p>
</li>
<li><p>You’re bound to a synchronous, blocking model.</p>
</li>
</ul>
<p><strong>Use WebClient When:</strong></p>
<ul>
<li><p>You're using Spring WebFlux to develop the application.</p>
</li>
<li><p>You need full control over request/response handling.</p>
</li>
<li><p>You require high-performance, non-blocking communication.</p>
</li>
<li><p>You want more control over error handling and retry logic.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The architecture and performance requirements of your system guide the choice between OpenFeign and WebClient.</p>
<p>OpenFeign is ideal for synchronous REST calls in a Spring Cloud stack and helps in reducing boilerplate code. WebClient, on the other hand, gives its best for reactive and high-performance applications and is more flexible.</p>
<p>If you're building a traditional microservices system using Spring Boot and Spring Cloud, OpenFeign is most likely to be the obvious choice. If you're in the context of reactive programming or you have to handle thousands of concurrent connections, then WebClient would be a better choice.</p>
<p>Understanding both tools, their pros and cons, is important to make the proper choice.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Develop a CRUD App with Spring Boot, Neon Postgres, and Azure App Service ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we'll explore how to develop a CRUD (Create, Read, Update, Delete) application using Spring Boot and Neon Postgres. We'll also deploy the application on Azure App Service and make it production-ready by setting up features like autos... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-crud-app-spring-boot-neon-postgres/</link>
                <guid isPermaLink="false">66c3762340438b5931fe0a0b</guid>
                
                    <category>
                        <![CDATA[ Azure ]]>
                    </category>
                
                    <category>
                        <![CDATA[ crud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ postgres ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Abhinav Pandey ]]>
                </dc:creator>
                <pubDate>Fri, 26 Jul 2024 19:14:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/07/neon-banner.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we'll explore how to develop a CRUD (Create, Read, Update, Delete) application using Spring Boot and <a target="_blank" href="https://neon.tech/">Neon Postgres</a>.</p>
<p>We'll also deploy the application on <a target="_blank" href="https://azure.microsoft.com/en-us/products/app-service">Azure App Service</a> and make it production-ready by setting up features like autoscaling and multiple environments.</p>
<p>You'll learn how Neon Postgres can make your development and deployment processes easier along the way.</p>
<h2 id="heading-heres-what-well-cover">Here's what we'll cover:</h2>
<ul>
<li>Setting up a Neon Postgres database and exploring its features</li>
<li>Building a CRUD application using Spring Boot and deploying the application on Azure App Service</li>
<li>Why Neon is a good fit for infrastructure that auto-scales</li>
<li>Database branching in Neon Postgres and how it can ease the development workflow</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Working knowledge of Java, Maven, and Spring Boot</li>
<li>Basics of SQL databases</li>
<li>Understanding of serverless and cloud services</li>
<li>Familiarity with testing and deployment processes</li>
</ul>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-neon-postgres">What is Neon Postgres?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-the-database">How to Set Up the Database</a><ul>
<li><a class="post-section-overview" href="#heading-create-the-database">Create the Database</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-build-the-spring-boot-crud-app">How to Build the Spring Boot CRUD App</a><ul>
<li><a class="post-section-overview" href="#heading-create-an-entity-class">Create an Entity Class</a></li>
<li><a class="post-section-overview" href="#heading-create-a-repository">Create a Repository</a></li>
<li><a class="post-section-overview" href="#heading-create-a-rest-controller">Create a REST Controller</a></li>
<li><a class="post-section-overview" href="#heading-configure-the-database">Configure the Database</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-deploy-on-azure-app-service">How to Deploy on Azure App Service</a><ul>
<li><a class="post-section-overview" href="#heading-create-a-new-web-app">Create a New Web App</a></li>
<li><a class="post-section-overview" href="#heading-deploy-the-application">Deploy the Application</a></li>
<li><a class="post-section-overview" href="#heading-access-the-application">Access the Application</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-autoscaling">How to Set Up Autoscaling</a><ul>
<li><a class="post-section-overview" href="#heading-autoscaling-in-azure">Autoscaling in Azure</a></li>
<li><a class="post-section-overview" href="#heading-autoscaling-in-neon">Autoscaling in Neon</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-configure-database-branches-in-neon">How to Configure Database Branches in Neon</a></li>
<li><a class="post-section-overview" href="#heading-summary">Summary</a></li>
</ul>
<h2 id="heading-what-is-neon-postgres">What is Neon Postgres?</h2>
<p>Neon is a fully managed serverless Postgres database platform. It offers features such as high availability, automatic backups, and scaling options to handle varying traffic levels.</p>
<p>Neon is designed to be cost-efficient and developer-friendly, and it focuses on providing a seamless experience for developers.</p>
<p>In addition to the standard Postgres features, it provides capabilities like database branching, allowing you to create Git-like branches of the database for different purposes.</p>
<h2 id="heading-how-to-set-up-the-database">How to Set Up the Database</h2>
<p>To begin with, let's explore how you can set up a Neon database for your application.</p>
<p>Firstly, you'll need to <a target="_blank" href="https://console.neon.tech/signup">create an account</a> on the Neon website. It doesn't require a credit card to sign up, and you're automatically set up with the free tier to get started.</p>
<p>Here's a <a target="_blank" href="https://neon.tech/pricing">pricing and features comparison</a> of Neon plans:</p>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Finxumg46sf92ffre6l2q.png" alt="A screenshot of pricing plans in Neon listing down free and paid features" width="600" height="400" loading="lazy">
<em>Neon pricing plans</em></p>
<p>In the free tier, we get 0.5 GB of storage with basic computing which is enough for playing around with the database and building small applications.</p>
<h3 id="heading-create-the-database">Create the Database</h3>
<p>Once you've signed up, you can access the dashboard and create a new project.</p>
<p>Star by filling in the project name, region, and Postgres version options. In addition to this, we can choose two additional options:</p>
<ul>
<li><strong>compute size</strong> – You can choose a min and max compute size for the database. This is useful for autoscaling the database based on the load.</li>
<li><strong>suspend time</strong> – You can set a time after which the database will be suspended if not being used. This is useful for saving costs when the database is not being used.</li>
</ul>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggwuvqtb8ydl3mxd1dak.png" alt="Form with specifications required when creating a database" width="600" height="400" loading="lazy">
<em>Creating a database project in Neon</em></p>
<p>Once you submit the form, Neon will create the database and provide the connection details.</p>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe2x5d81euphg2owgxhd.png" alt="Neon Dashboard showing the project is ready. Also shows connection details." width="600" height="400" loading="lazy">
<em>Neon Dashboard</em></p>
<p>As you can see, the database was set up in 3.3 seconds (compared to hours of installing and setting up your own infrastructure). You can choose multiple ways to connect to the database. For this tutorial, select Java as your programming language and get the JDBC connection string.</p>
<h2 id="heading-how-to-build-the-spring-boot-crud-app">How to Build the Spring Boot CRUD App</h2>
<p>Next, let's set up our CRUD application. We'll use Spring Boot, as it provides easy bootstrapping and configuration for building web applications.</p>
<p>We can use the <a target="_blank" href="https://start.spring.io/">Spring Initializr</a> to generate a new Spring Boot project with the necessary dependencies:</p>
<ul>
<li>Spring Web – for building web applications</li>
<li>Spring Data JPA – for working with databases using JPA</li>
<li>PostGres Driver – for connecting to the Postgres database</li>
</ul>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffifv17tc5d3swothe3zf.png" alt="Spring Initializer website form to select spring boot project specifications and dependencies" width="600" height="400" loading="lazy">
<em>Creating a Spring Boot project using Spring Initializer</em></p>
<p>You can generate, download, and import the project into your favorite IDE.</p>
<h3 id="heading-create-an-entity-class">Create an Entity Class</h3>
<p>Let's create an entity class to represent the data in the application. First, create a <code>User</code> class:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Entity(name = "users")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-meta">@Id</span>
    <span class="hljs-meta">@GeneratedValue(strategy = GenerationType.IDENTITY)</span>
    <span class="hljs-keyword">private</span> Long id;
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> String email;

    <span class="hljs-comment">// Constructors, Getters and Setters</span>
}
</code></pre>
<p>The entity name <code>users</code> is the name of the table you want to use in your database.</p>
<h3 id="heading-create-a-repository">Create a Repository</h3>
<p>Next, create a repository interface to interact with the database. You'll extend the <code>JpaRepository</code> interface provided by Spring Data JPA:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Repository</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">User</span>, <span class="hljs-title">Long</span>&gt; </span>{
}
</code></pre>
<p>You need to annotate the interface with <code>@Repository</code> to mark it as a Spring bean. The <code>JpaRepository</code> interface provides methods for CRUD operations like <code>save</code>, <code>findAll</code>, <code>findById</code>, <code>delete</code>, and so on, so you don't need to write the queries manually.</p>
<p>You'll provide your entity class <code>User</code> and the type of the primary key <code>Long</code> as type arguments to the <code>JpaRepository</code> interface.</p>
<h3 id="heading-create-a-rest-controller">Create a REST Controller</h3>
<p>Finally, create a REST controller to handle the CRUD operations. You'll inject the <code>UserRepository</code> into the controller and implement the necessary endpoints:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping("/users")</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> UserRepository userRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserController</span><span class="hljs-params">(UserRepository userRepository)</span> </span>{
        <span class="hljs-keyword">this</span>.userRepository = userRepository;
    }

    <span class="hljs-meta">@GetMapping</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;User&gt; <span class="hljs-title">getUsers</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.findAll();
    }

    <span class="hljs-meta">@PostMapping</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">createUser</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> User user)</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.save(user);
    }

    <span class="hljs-meta">@PutMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">updateUser</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable</span> Long id, <span class="hljs-meta">@RequestBody</span> User user)</span> </span>{
        user.setId(id);
        <span class="hljs-keyword">return</span> userRepository.save(user);
    }

    <span class="hljs-meta">@DeleteMapping("/{id}")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deleteUser</span><span class="hljs-params">(<span class="hljs-meta">@PathVariable</span> Long id)</span> </span>{
        userRepository.deleteById(id);
    }
}
</code></pre>
<p>Here are a few things to note:</p>
<ul>
<li>You're using the <code>@RestController</code> annotation to mark the class as a controller that handles REST requests.</li>
<li>The <code>@RequestMapping</code> annotation specifies the base URL for the endpoints.</li>
<li>You're injecting the <code>UserRepository</code> into the controller using constructor injection.</li>
<li>Finally, you're implementing your API endpoints for CRUD operations using the <code>@GetMapping</code>, <code>@PostMapping</code>, <code>@PutMapping</code>, and <code>@DeleteMapping</code> annotations.</li>
</ul>
<h3 id="heading-configure-the-database">Configure the Database</h3>
<p>To connect your Spring Boot application to the Neon Postgres database, you need to configure the database URL, username, and password in the <code>application.properties</code> file:</p>
<pre><code>spring.datasource.url=jdbc:postgresql:<span class="hljs-comment">//&lt;db-url&gt;/&lt;db-name&gt;?sslmode=require</span>
spring.datasource.username=&lt;username&gt;
spring.datasource.password=&lt;password&gt;
spring.jpa.hibernate.ddl-auto=update
</code></pre><p>Here, you configured the database URL, username, and password provided by Neon when you created the database. The <code>spring.jpa.hibernate.ddl-auto=update</code> property tells Spring Boot to automatically create the necessary tables or columns based on the entity classes when the application starts.</p>
<h2 id="heading-how-to-deploy-on-azure-app-service">How to Deploy on Azure App Service</h2>
<p>Now that your Spring Boot application is ready, it's time to deploy it on Azure App Service.</p>
<h3 id="heading-create-a-new-web-app">Create a New Web App</h3>
<p>To deploy your Spring Boot application on Azure App Service, you'll first create a new <code>Web App</code>. You can do this through the Azure portal by following these steps:</p>
<ul>
<li>Log in to the <a target="_blank" href="https://portal.azure.com/">Azure portal</a>.</li>
<li>Click on the <code>Create a resource</code> button.</li>
<li>Search for <code>Web App</code> and select the <code>Create</code> option.</li>
<li>Fill in the necessary details like resource group, app name, runtime stack, and region.</li>
<li>Click the <code>Review + create</code> button.</li>
</ul>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf2kmh12t8eucd1qa1pg.png" alt="Form for creating a web app in Azure" width="600" height="400" loading="lazy">
<em>Creating a Web App in Azure</em></p>
<h3 id="heading-deploy-the-application">Deploy the Application</h3>
<p>The Web App takes a couple of minutes to create. Once done, you can deploy your Spring Boot application to Azure App Service.</p>
<p>One of the easiest ways to deploy is to package your Spring Boot application as a JAR file and deploy it to Azure App Service using the Azure CLI.</p>
<p>To do this, run the below commands:</p>
<pre><code>mvn package
az webapp deploy --src-path neon-demo<span class="hljs-number">-0.0</span><span class="hljs-number">.1</span>-SNAPSHOT.jar --resource-group learn-ba1a439c<span class="hljs-number">-71</span>ca<span class="hljs-number">-4</span>cab<span class="hljs-number">-9</span>bb1-f5b1331bab04 --name neon-app
</code></pre><p>Here, you're packaging your Spring Boot application using Maven and deploying the JAR file to Azure App Service using the Azure CLI. You've provided the path to the JAR file, the resource group, and the app name you previously configured.</p>
<h3 id="heading-access-the-application">Access the Application</h3>
<p>Once the deployment is complete, you can access your Spring Boot application on Azure App Service by navigating to the URL of the Web App. Your app is available at neon-app.azurewebsites.net</p>
<p>Let's use _curl _to test the endpoints.</p>
<h4 id="heading-create-a-user">Create a User</h4>
<pre><code>curl -X POST -d <span class="hljs-string">'{"name":"John Doe","email":"john@gmail.com"}'</span> https:<span class="hljs-comment">//neon-app.azurewebsites.net/users</span>
</code></pre><p>Here you provide user data in JSON format to create a new user.</p>
<h4 id="heading-get-users">Get Users</h4>
<p>You can also can test that the user was created by fetching all users:</p>
<pre><code>curl -X GET https:<span class="hljs-comment">//neon-app.azurewebsites.net/users</span>
</code></pre><h2 id="heading-how-to-set-up-autoscaling">How to Set Up Autoscaling</h2>
<p>A production application may experience varying levels of traffic, and it's important to scale the application dynamically based on the load.</p>
<p>Let's explore how you can autoscale your application when needed.</p>
<h3 id="heading-autoscaling-in-azure">Autoscaling in Azure</h3>
<p>Azure App Service provides <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-premium-plan?tabs=portal#plan-and-sku-settings">autoscaling options</a> that let you automatically adjust the number of instances as needed.</p>
<p>You can configure autoscaling rules in the Azure portal by following these steps:</p>
<ul>
<li>Navigate to the Web App in the Azure portal.</li>
<li>Click the <code>Scale out (App Service Plan)</code> option from the left menu.</li>
<li>Configure the autoscaling rules – you can choose predefined rules like traffic or create custom rules based on metrics like CPU usage, memory usage, or custom metrics.</li>
<li>Save.</li>
</ul>
<p>Azure will automatically scale the application based on the configured rules.</p>
<h3 id="heading-autoscaling-in-neon">Autoscaling in Neon</h3>
<p>Since your application is automatically scaled based on the load, you'll want to ensure that the database can handle the increased traffic.</p>
<p>Neon provides <a target="_blank" href="https://neon.tech/docs/introduction/autoscaling">autoscaling options</a> to scale the database dynamically based on the load. You can configure autoscaling rules in the Neon dashboard to ensure the database can handle the increased load.</p>
<p>Follow the below steps to configure autoscaling in Neon:</p>
<ol>
<li>Navigate to the Neon dashboard and select the database. Then select the branch to configure autoscaling.</li>
</ol>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl6s84pqhk2avflpjbgrf.png" alt="Neon project dashboard with branches section highlighted " width="600" height="400" loading="lazy">
<em>Selecting a branch from Neon project dashboard</em></p>
<ol start="2">
<li>Click on the <code>Edit</code> button next to the <code>Compute</code> section. Configure the autoscaling rules based on metrics like CPU usage, memory usage, or custom metrics.</li>
</ol>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkn11nop1zz9xxbfamsr.png" alt="Branch details view in Neon with edit button in the computes section highlighted" width="600" height="400" loading="lazy">
<em>Branch details view in Neon</em></p>
<ol start="3">
<li>Configure the min-max compute size and Save. Neon will automatically scale the database based on the configured rules when needed.</li>
</ol>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmuow8zvndz0dibv2kxt.png" alt="Form to enable autoscaling and select min and max size of the compute" width="600" height="400" loading="lazy">
<em>Setting up autoscaling for compute</em></p>
<p>Ensuring that both the application and the database can scale dynamically based on the load will help you handle varying levels of traffic efficiently.</p>
<h2 id="heading-how-to-configure-database-branches-in-neon">How to Configure Database Branches in Neon</h2>
<p>In a typical development workflow, multiple databases may be used for different purposes like development, testing, and production.</p>
<p>Neon Postgres provides <a target="_blank" href="https://neon.tech/docs/introduction/autoscaling">database branching</a> to create multiple branches for different purposes. Each branch is an instance of the database that you can use independently.</p>
<p>This Git-like feature helps set up a copy of the database for different environments like development, staging, and production. It also helps preserve data for different versions of the application.</p>
<p>Let's explore how you can create and manage branches in Neon Postgres:</p>
<ul>
<li>Navigate to the Neon dashboard and select the database.</li>
<li>In the <code>Branches</code> section, click on the <code>View All</code> button.</li>
<li>You can create a new branch from an existing one by clicking on the <code>Create Branch</code> button. You'll need to provide the branch name and what data to copy from the parent branch.</li>
</ul>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ncdgdrj32etd3gbqurf.png" alt="Branches view with Create branch option visible " width="600" height="400" loading="lazy">
<em>Create branch option</em></p>
<ul>
<li>You can either copy all the data or copy until a point in time or a specific record. This is useful for multiple purposes like restoring data, creating a new environment, or testing new features.</li>
</ul>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7gchucru5qw294icqw3.png" alt="Creating a new branch from an existing branch" width="600" height="400" loading="lazy">
<em>Creating a new branch</em></p>
<ul>
<li>Neon will create a new branch of the database that can be used independently. You can find the URL, username, and password for the new branch in the dashboard. And this happens in real time without any downtime and delays.</li>
</ul>
<p><img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fji79akuf193gtv94yaag.png" alt="Branch-specific connection details " width="600" height="400" loading="lazy">
<em>Branch-specific connection details</em></p>
<p>Now you can use your <code>dev</code> branch for local development and testing, and the <code>main</code> branch for production. This helps in keeping the data separate and ensures that changes in one branch do not affect the other branches.</p>
<h2 id="heading-summary">Summary</h2>
<p>In this article, we built a CRUD application using Spring Boot, Neon Postgres, and Azure App Service.</p>
<p>We explored how to set up the Neon Postgres database, build a basic CRUD application using Spring Boot, deploy the application on Azure App Service, and configure autoscaling for the application and the database.</p>
<p>We also learned about how the database branching feature in Neon Postgres helps you create branches of the database for different environments and purposes.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Perform Load Testing in Spring Boot with Gatling ]]>
                </title>
                <description>
                    <![CDATA[ To evaluate the performance of a system, you need a tool that can simulate its behavior in production.  For this purpose, you can use a software tool based on Scala called Gatling. This article will teach you how to integrate it into a Spring Boot ap... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-integrate-spring-boot-with-gatling/</link>
                <guid isPermaLink="false">66bb4548cd114247c2941f32</guid>
                
                    <category>
                        <![CDATA[ Gatling ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mario Casari ]]>
                </dc:creator>
                <pubDate>Mon, 08 Jul 2024 19:46:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/pexels-markusspiske-177598.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>To evaluate the performance of a system, you need a tool that can simulate its behavior in production. </p>
<p>For this purpose, you can use a software tool based on <a target="_blank" href="https://www.scala-lang.org/">Scala</a> called <a target="_blank" href="https://gatling.io/">Gatling</a>. This article will teach you how to integrate it into a <a target="_blank" href="https://spring.io/projects/spring-boot">Spring Boot</a> application and perform a load test.</p>
<h2 id="heading-main-concepts">Main Concepts</h2>
<p>Gatling is a tool you can use to execute load and performance tests. It can be used as a standalone application or integrated into a Maven or Gradle-based project.</p>
<p>Gatling is based on Scala, the <a target="_blank" href="https://en.wikipedia.org/wiki/Netty_(software)">Netty</a> framework, and the <a target="_blank" href="https://doc.akka.io/docs/akka/current/typed/guide/index.html">Akka</a> toolkit. It has an asynchronous, non-blocking architecture, which allows for high performance with minimum wasting of resources.</p>
<p>You can define tests by Gatling's flexible domain-specific language. You can also use its recorder function with a Graphical User Interface to capture user interactions in the browser and generate Scala scripts that can be modified and launched to perform a simulation.</p>
<p>In this article, you will learn how to integrate Gatling in a Spring Boot web application based on Maven. You will define a load test by its DSL, and then run it using the Gatling Maven plugin.</p>
<p>With Gatling, you can perform performance tests in a variety of ways. For instance, you can implement:</p>
<ul><li><b>Load Testing</b>: to see how a system performs under a specific load</li><li><b>Stress Testing</b>: to find the breaking point of a system, raising the load progressively</li><li><b>Soak Testing</b>: running the system with a steady load for a long time to find its pitfalls</li><li><b>Spike Testing</b>: to see how the system performs when swiftly raising the load to a peak and then going down</li></ul>

<p>The basic components by which Gatling implements the features described above are:</p>
<ul><li><b>Scenarios</b>: a series of steps performed by a virtual user</li><li><b>Feeders</b>: how data is provided to feed the scenarios</li><li><b>Injection</b>: a sort of a blueprint that states how the test is performed, in terms of number of virtual users, how they change in time, and so on</li></ul>

<h2 id="heading-spring-boot-gatling-integration">Spring Boot Gatling Integration</h2>
<p>In this article, you will start with a simple Spring Boot web application and implement and run a load test over it. You can find the source code of this sample application on <a target="_blank" href="https://github.com/mcasari/codingstrain/tree/main/spring-cloud-sample-libraryapp/libraryapp-testing-gatling-test">GitHub</a>.</p>
<p>Imagine you have a library and want to insert new books by their title. You can implement this minimal requirement using JPA by defining a Book entity, a repository class, a service class, and a controller with a <a target="_blank" href="https://codingstrain.com/spring-boot-for-cloud-rest-api-development/">REST</a> service mapping.</p>
<p>The REST service is defined as a POST call to a /book endpoint that saves a new book object. You can see the implementation in the code below:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping("/library")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookController</span> </span>{

    Logger logger = LoggerFactory.getLogger(BookController.class);

    <span class="hljs-meta">@Autowired</span>
    BookService bookService;

    <span class="hljs-meta">@PostMapping(value = "/book", consumes = "application/json", produces = "application/json")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Book <span class="hljs-title">createPerson</span><span class="hljs-params">(<span class="hljs-meta">@RequestBody</span> Book book)</span> </span>{
        <span class="hljs-keyword">return</span> bookService.save(book);
    }

}
</code></pre>
<p>To perform a load test on the above REST endpoint, you need to integrate Gatling. You can do this by setting some Maven dependencies first:</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>io.gatling<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>gatling-app<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.7.2<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">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>io.gatling.highcharts<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>gatling-charts-highcharts<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.7.2<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">dependency</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com.github.javafaker<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>javafaker<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>0.15<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>
</code></pre>
<p>Then you also need a Maven plugin to execute the test:</p>
<pre><code class="lang-xml"><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>io.gatling<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>gatling-maven-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>4.2.9<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">simulationClass</span>&gt;</span>com.codingstrain.springcloud.sample.libraryapp.books.BookSaveSimulation<span class="hljs-tag">&lt;/<span class="hljs-name">simulationClass</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>
</code></pre>
<h2 id="heading-load-test-implementation">Load Test Implementation</h2>
<p>To implement a test, you need to extend the <code>io.gatling.javaapi.core.Simulation</code> class, as in the <code>BookSaveSimulation</code> class below:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.core.CoreDsl.StringBody;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.core.CoreDsl.global;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.core.CoreDsl.rampUsersPerSec;
<span class="hljs-keyword">import</span> <span class="hljs-keyword">static</span> io.gatling.javaapi.http.HttpDsl.http;

<span class="hljs-keyword">import</span> java.time.Duration;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Iterator;
<span class="hljs-keyword">import</span> java.util.Map;
<span class="hljs-keyword">import</span> java.util.stream.Stream;

<span class="hljs-keyword">import</span> com.github.javafaker.Faker;

<span class="hljs-keyword">import</span> io.gatling.javaapi.core.CoreDsl;
<span class="hljs-keyword">import</span> io.gatling.javaapi.core.OpenInjectionStep.RampRate.RampRateOpenInjectionStep;
<span class="hljs-keyword">import</span> io.gatling.javaapi.core.ScenarioBuilder;
<span class="hljs-keyword">import</span> io.gatling.javaapi.core.Simulation;
<span class="hljs-keyword">import</span> io.gatling.javaapi.http.HttpDsl;
<span class="hljs-keyword">import</span> io.gatling.javaapi.http.HttpProtocolBuilder;


<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BookSaveSimulation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Simulation</span> </span>{


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

        setUp(buildPostScenario()
            .injectOpen(injection())
            .protocols(setupProtocol())).assertions(global().responseTime()
          .max()
          .lte(<span class="hljs-number">10000</span>), global().successfulRequests()
          .percent()
          .gt(<span class="hljs-number">90d</span>));
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> ScenarioBuilder <span class="hljs-title">buildPostScenario</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> CoreDsl.scenario(<span class="hljs-string">"Load POST Test"</span>)
            .feed(feedData())
            .exec(http(<span class="hljs-string">"create-book"</span>).post(<span class="hljs-string">"/library/book"</span>)
            .header(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"application/json"</span>)
                .body(StringBody(<span class="hljs-string">"{ \"title\": \"${title}\" }"</span>)));
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Iterator &amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; feedData() {
        Faker faker = <span class="hljs-keyword">new</span> Faker();
        Iterator&amp;lt;Map&amp;lt;String, Object&amp;gt;&amp;gt; iterator;
        iterator = Stream.generate(() -&amp;gt; {
              Map&amp;lt;String, Objectglt; stringObjectMap = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();
            stringObjectMap.put(<span class="hljs-string">"title"</span>, faker.book()
                .title());
              <span class="hljs-keyword">return</span> stringObjectMap;
          })
          .iterator();
        <span class="hljs-keyword">return</span> iterator;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> HttpProtocolBuilder <span class="hljs-title">setupProtocol</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> HttpDsl.http.baseUrl(<span class="hljs-string">"http://localhost:8080"</span>)
          .acceptHeader(<span class="hljs-string">"application/json"</span>)
          .maxConnectionsPerHost(<span class="hljs-number">10</span>)
            .userAgentHeader(<span class="hljs-string">"Performance Test"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> RampRateOpenInjectionStep <span class="hljs-title">injection</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">int</span> totalUsers = <span class="hljs-number">100</span>;
        <span class="hljs-keyword">double</span> userRampUpPerInterval = <span class="hljs-number">10</span>;
        <span class="hljs-keyword">double</span> rampUpIntervalInSeconds = <span class="hljs-number">30</span>;

        <span class="hljs-keyword">int</span> rampUptimeSeconds = <span class="hljs-number">300</span>;
        <span class="hljs-keyword">int</span> duration = <span class="hljs-number">300</span>;
        <span class="hljs-keyword">return</span> rampUsersPerSec(userRampUpPerInterval / (rampUpIntervalInSeconds)).to(totalUsers)
            .during(Duration.ofSeconds(rampUptimeSeconds + duration));
    }
}
</code></pre>
<p>The <code>BoookSaveSimulation</code> class uses its constructor to do all the settings using the parent class <code>setUp</code> method. It first implements a scenario. Since the test's purpose is to simulate a real situation in production, the scenario represents the steps performed by a configured number of virtual users interacting with the system.</p>
<p>The scenario in the example executes a POST call to the /library/book endpoint, sending a single title parameter in the payload. The invoked service will save a new book by the passed title value. A class named <code>com.github.javafaker.Faker</code> produces title values automatically and implements the feeder component described earlier in the <code>Main Concepts</code> section.</p>
<p>Then the <code>injectOpen</code> method defines how the virtual users are added to the simulation. The injectOpen method implements the injection part using the so-called open mode. There are two different models of injection, <code>open</code> and <code>closed</code>.</p>
<p>The open model simulates a scenario in which new users can be added constantly and independently from the execution state of the others. This is the model used in this article's example. On the other hand, in the closed model, new users can be added only when all the others have terminated their tasks. This helps simulate a steady load on the system.</p>
<p>The open injection configuration in the example sets a total number of 100 users that are added progressively 10 at a time, every 30 seconds. Once all users have been added, the execution continues for 300 seconds.</p>
<p>The protocols method sets up the base URL, the data type expected in the response, the maximum number of connections per host, and the User-Agent header.</p>
<p>The last part of this set-up phase defines a couple of assertions to consider the test passed: a maximum response time lower than 10 seconds and a percentage of successful requests greater than 90%.</p>
<h2 id="heading-how-to-run-the-test">How to Run the Test</h2>
<p>To run the test, you first have to start the Spring Boot web application. You can do this, for instance, by going to the project base directory and execute the following command: <code>mvn spring-boot:run</code>. </p>
<p>Once the application is started, you can run the Gatling simulation by executing <code>mvn gatling:test</code>.</p>
<h2 id="heading-how-to-see-the-results">How to See the Results</h2>
<p>Once the test is terminated, you will find an index.html in the /target/gatling directory with all the measurements and several graphs.</p>
<p>The figure below displays all the results. It shows a list of the assertions and their outcome. Then, you can see the total number of requests, and how many requests have a positive or negative result. You have useful information about the response time: minimum, maximum, average, and standard deviation, and you also have the 50th, 75th, 95th, and 99th percentiles.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Summary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Summary of the test results</em></p>
<p>A chart shows the number of requests, with positive and negative outcomes, in a particular response time range, as in the following figure.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/GlobalInfo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Number of requests in particular response time ranges</em></p>
<p>Another graph shows the number of requests per second and how it changes depending on the number of active users.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/RequestsPerSecond.png" alt="Image" width="600" height="400" loading="lazy">
<em>Number of request per second and active users over time</em></p>
<p>You can also see in the next figure how the percentiles change over time, and with the number of active users at each point in time.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/06/Percentiles.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Evaluating the performance of a system is a complex task. Gatling makes things easy enough to integrate this kind of task with continuous integration. It gives you a comprehensive view and allows you to tweak the tests to find weaknesses and suggest solutions.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement an OAuth2 Resource Server with Spring Security ]]>
                </title>
                <description>
                    <![CDATA[ Hey everyone! Imagine you are building an awesome application, with lots of cool features. Picture a backend server at its core that hosts a majority of the business logic and exposes functionality through APIs. Once you have planned out your APIs, t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/oauth2-resourceserver-with-spring-security/</link>
                <guid isPermaLink="false">66d8516039c4dccc43d4d4c3</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kunal Nalawade ]]>
                </dc:creator>
                <pubDate>Wed, 08 May 2024 15:39:37 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/article-cover.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hey everyone! Imagine you are building an awesome application, with lots of cool features. Picture a backend server at its core that hosts a majority of the business logic and exposes functionality through APIs.</p>
<p>Once you have planned out your APIs, there's one crucial step you need to take care of: securing your APIs. You don't want your APIs exposed to anyone on the internet (unless you are building for open source).</p>
<p>Authentication ensures that your APIs can only be accessed by authenticated users of your application. A user can be authenticated with username and password, or via access token.</p>
<p>In this post, we are going to see how to secure your APIs using OAuth2 and access tokens. I am assuming you have a basic knowledge of Java and Spring Boot. If not, then you can <a target="_blank" href="https://www.freecodecamp.org/news/learn-app-development-with-spring-boot-3/">check out this course on freeCodeCamp's YouTube channel</a>.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-oauth2">What is OAuth2?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-the-spring-boot-application">How to Set Up the Spring Boot Application</a></p>
</li>
<li><p><a class="post-section-overview" href="#configuration">Web Security Configuration</a></p>
</li>
<li><p><a class="post-section-overview" href="#write-apis-in-controller-class">Public and Private APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-the-apis">Testing APIs with and without Access Token</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-get-the-users-details-from-the-access-token">How to Get the User's Details From the Access Token</a></p>
</li>
</ol>
<h2 id="heading-what-is-oauth2">What is OAuth2?</h2>
<p>OAuth2 is a framework that lets third-party applications access your service on behalf of an end user. It is widely used for authentication and authorization in modern applications.</p>
<p>There are four components in the OAuth2 framework:</p>
<ul>
<li><p><strong>Resource Owner</strong>: The end-user of your application.</p>
</li>
<li><p><strong>Authorization Server</strong>: The third-party application that authenticates the user and issues an access token after successful authentication.</p>
</li>
<li><p><strong>Client</strong>: The user interface through which the user wants to access your resources. The client could be a mobile app, web app, or a desktop app. The client requires an access token to access your APIs.</p>
</li>
<li><p><strong>Resource Server</strong>: The server hosting the protected resources. It validates the access token and grants access to the resources if authentication is successful.</p>
</li>
</ul>
<p>The user, through the client, requests an access token from the authorization server. If authentication is successful, the client uses this token to access the protected APIs exposed by the resource server.</p>
<p>In this post, we are only going to focus on implementing the resource server.</p>
<h2 id="heading-how-to-set-up-the-spring-boot-application">How to Set Up the Spring Boot Application</h2>
<p>To set up your application, navigate to <a target="_blank" href="https://start.spring.io/">Spring Initializr</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-44.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Spring Initializr</em></p>
<p>Choose <em>Gradle</em> or <em>Maven</em> for the project, the Spring Boot version, and the name of the project. Add the following dependencies: <em>spring-boot-starter-web</em> and <em>oauth2-resource-server</em>.</p>
<p>Click on <em>Generate</em> to download the Spring Boot application and once downloaded, extract the zip file. You should now have a running Spring Boot application with the dependencies fully loaded. Open IntelliJ (or any IDE of your choice) and select this project to start working.</p>
<p>You can find the complete code for this tutorial on <a target="_blank" href="https://github.com/KunalN25/my-tutorials/tree/main/java-springboot/oauth2-resource-server-tutorial">GitHub</a>.</p>
<h2 id="heading-web-security-configuration">Web Security Configuration</h2>
<p>First, open <code>application.properties</code> and add the following property:</p>
<pre><code class="lang-python">spring.security.oauth2.resourceserver.jwt.issuer-uri: ${JWT_ISSUER_URI}
</code></pre>
<p>You can find the <em>issuer-uri</em> in the open-id configuration of the OAuth2 service that you are using. For instance, check out the <a target="_blank" href="https://accounts.google.com/.well-known/openid-configuration">Google OAuth2</a> config.</p>
<p>Next, let's configure Spring Security.</p>
<p>To implement the resource server, you need to have Spring Security as one of your dependencies. Here, we don't need to add it separately since the <em>oauth2-resource-server</em> uses Spring Security.</p>
<p>When you add Spring Security in your dependencies, Spring Boot enables authentication for each API you expose. The default one is username and password-based authentication.</p>
<p>This happens because Spring Security has its own <code>SecurityAutoConfiguration</code> class that contains the default security configuration. But, we haven't added Spring Security in our dependencies.</p>
<p>Since we do not want username and password-based authentication, we need to disable the auto configuration. Go to the main class and add the following exclusion:</p>
<pre><code class="lang-java"><span class="hljs-meta">@SpringBootApplication(exclude = { SecurityAutoConfiguration.class})</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Oauth2ResourceServerTutorialApplication</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(Oauth2ResourceServerTutorialApplication.class, args);
    }
}
</code></pre>
<p>If you run the application now, it throws an error.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/04/image-45.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Error without configuration</em></p>
<p>Let's add our own configuration now. Create a new Java class <code>SecurityConfig</code> with the following annotations:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Configuration</span>
<span class="hljs-meta">@EnableWebSecurity</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecurityConfig</span> </span>{
    <span class="hljs-comment">// Beans here</span>
}
</code></pre>
<p><code>@Configuration</code> indicates that this is a configuration class that contains several Bean methods, that are responsible for creating beans. <a target="_blank" href="https://www.baeldung.com/spring-bean">Beans</a> are simply objects that form the building blocks of a Spring Boot application. <code>@EnableWebSecurity</code> tells Spring Boot to enable Web Security with your configurations.</p>
<p>Create a method that returns a bean of type <code>SecurityFilterChain</code>. The security filter chain bean intercepts incoming requests and applies custom filters to them. This is where you can apply different kinds of authorization to different requests.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Bean</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> SecurityFilterChain <span class="hljs-title">filterChain</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        http
                .authorizeHttpRequests((authz) -&gt; authz
                        .requestMatchers(<span class="hljs-string">"/public/**"</span>).permitAll()
                        .anyRequest().authenticated()
                )
                .oauth2ResourceServer(oauth2 -&gt; oauth2.jwt(Customizer.withDefaults()));
        <span class="hljs-keyword">return</span> http.build();
    }
</code></pre>
<p>Let's understand the key parts of this code:</p>
<ul>
<li><p>The <code>filterChain()</code> method takes an <code>HttpSecurity</code> object as an argument. This class from Spring Security allows you to configure requests.</p>
</li>
<li><p>The method <code>authorizeHttpRequests()</code> takes an object that we have represented as a lambda expression.</p>
</li>
<li><p>We have used the <code>requestMatchers()</code> method to match a route that will be accessible without authentication. In our case, any route starting from <code>/public</code> will be accessible to anyone. Requests to any other route will need authentication.</p>
</li>
<li><p>The <code>oauth2ResourceServer()</code> method sets up our application as an OAuth2 resource server. Here, we specify that JWT authentication will be used with default customizers.</p>
</li>
<li><p>Lastly, <code>http.build()</code> builds the <code>HttpSecurity</code> object and returns it.</p>
</li>
</ul>
<p>In this project, we have configured web security in the above manner. But if you have any other requirements you may need a different configuration. For example, if you have privileged roles like admin in your application, you can specify which routes each role can access, and so on.</p>
<p>Visit the <a target="_blank" href="https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html">JWT resource server</a> docs to understand different ways you can customize web security.</p>
<h2 id="heading-write-apis-in-the-controller-class">Write APIs in the Controller Class</h2>
<p>Let's write two simple APIs. Create a class <code>MainController</code> that will expose these APIs:</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">MainController</span> </span>{

    <span class="hljs-meta">@GetMapping("/public")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">homePage</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello from Spring boot app"</span>;
    }

    <span class="hljs-meta">@GetMapping("/private")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">privateRoute</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Private Route"</span>;
    }
}
</code></pre>
<p>The <code>@RestController</code> indicates that this class will handle HTTP requests and return the data to the client, typically in JSON format. We have written a public and a private API.</p>
<p>Save the file and run the application.</p>
<h2 id="heading-testing-the-apis">Testing the APIs</h2>
<p>Let's test the above APIs using Postman, without an authorization header.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>/public route</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>/private route</em></p>
<p>In the above two API calls, the <code>/public</code> route returned a response, while the <code>/private</code> route threw an error with a status of <code>401 Unauthorized</code>.</p>
<p>This is because, in our configuration, we have made all routes starting with <code>/public</code> accessible without authentication. All the other routes would need some form of authentication. In our case, we need a Bearer Token to access the private route.</p>
<p>Let's include an authorization header in the request to the <code>/private</code> endpoint.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>/private route request with access token</em></p>
<p>When we include an authorization header with the access token, the private route returns a response. For this, and any other routes not starting with <code>/public</code>, we need to pass an access token in the header.</p>
<p>We are not going to see how to obtain an access token, since we are only focussing on the resource server. The OAuth2 Client is responsible for obtaining an access token. I'll cover that in a future post.</p>
<h2 id="heading-how-to-get-the-users-details-from-the-access-token">How to Get the User's Details From the Access Token</h2>
<p>When you make a request to a private route, the security filter intercepts this request and looks for a Bearer Token. If a token exists, it decodes the token and extracts the authentication information from the token. You can understand this whole process in detail from the <a target="_blank" href="https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/index.html">OAuth2 Resource Server</a> docs.</p>
<p>If the token is valid and authentication is successful, the authentication data is set on the <a target="_blank" href="https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html#servlet-authentication-securitycontextholder">SecurityContextHolder</a> class. The <code>SecurityContextHolder</code> contains the details of the authenticated user. We use this class to extract the user's information such as name, email, and so on.</p>
<p>Let's see how we can get these user details. First, we get an <a target="_blank" href="https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html#servlet-authentication-authentication">Authentication</a> object from the <code>SecurityContextHolder</code>:</p>
<pre><code class="lang-java">Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
</code></pre>
<p>Then, we use the <code>getPrincipal()</code> that returns an object:</p>
<pre><code class="lang-java">Object principal = authentication.getPrincipal();
</code></pre>
<p>Since we are using JWT Authentication, the above object can be type-casted into an object of type <a target="_blank" href="https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/jwt/Jwt.html">Jwt</a>. The object contains the following fields:</p>
<pre><code class="lang-python">{
    <span class="hljs-string">"tokenValue"</span>: token_value,
    <span class="hljs-string">"issuedAt"</span>: <span class="hljs-string">""</span>,
    <span class="hljs-string">"expiresAt"</span>: <span class="hljs-string">""</span>,
    <span class="hljs-string">"headers"</span>: {...},
    <span class="hljs-string">"claims"</span>: {        
        <span class="hljs-string">"name"</span>: full_name,
        <span class="hljs-string">"email"</span>: user_email,
        <span class="hljs-string">"given_name"</span>: first_name,
        <span class="hljs-string">"family_name"</span>: last_name,
        <span class="hljs-string">"picture"</span>: picture_link,
        ...other fields
    },
    <span class="hljs-string">"subject"</span>: <span class="hljs-string">""</span>,
    <span class="hljs-string">"id"</span>: null,
    <span class="hljs-string">"issuer"</span>: issuer_link,
    <span class="hljs-string">"audience"</span>: [...],
    <span class="hljs-string">"notBefore"</span>: null
}
</code></pre>
<p>Here, we can get the user data from the <code>claims</code> field:</p>
<pre><code class="lang-java">Map&lt;String, Object&gt; claims = ((Jwt) principal).getClaims();
</code></pre>
<p>Using the above map, we can get the user's information using the corresponding key value. Let's write this logic in a separate class <code>CurrentAuthContext</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">CurrentAuthContext</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Map&lt;String, Object&gt; <span class="hljs-title">extractClaim</span><span class="hljs-params">()</span> </span>{
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Object principal = authentication.getPrincipal();
        Map&lt;String, Object&gt; claims = ((Jwt) principal).getClaims();
        <span class="hljs-keyword">return</span> claims;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">getUserEmail</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> (String) extractClaim().get(<span class="hljs-string">"email"</span>);
    }
}
</code></pre>
<p>You can add more methods to get the details you need. To get the user email anywhere in the application, just call <code>CurrentAuthContext.getUserEmail()</code> or any other method returning the value you need.</p>
<p>I haven't implemented custom error handling here. You can reach out to me with different ways to implement custom error handling.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>OAuth2 provides a robust framework for securing your APIs while providing access to authorized users. In this post, we started with understanding OAuth2 and its components.</p>
<p>Spring Security is a fundamental part of the Spring OAuth2 Resource Server. We learned how to implement security configurations as per our requirements. Then, we defined public and private APIs and tested them with and without an access token.</p>
<p>A private API can only be accessed with an access token passed through the authorization header. We also implemented some logic to extract the user's information from the access token with the <code>SecurityContextHolder</code> class.</p>
<p>I attached reference links to docs at various places for further understanding of these concepts. That's all for today. I hope this helps in your future projects.</p>
<p>If you are unable to understand the content or find the explanation unsatisfactory, reach out to me. New ideas are always appreciated! Feel free to connect with me on Twitter. Till then, Goodbye!!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn App Development with Spring Boot 3 ]]>
                </title>
                <description>
                    <![CDATA[ Spring Boot 3 is an advanced framework that simplifies the development of new Spring applications through convention over configuration, providing a range of out-of-the-box functionalities for building enterprise-grade applications efficiently. We ju... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-app-development-with-spring-boot-3/</link>
                <guid isPermaLink="false">66b203f4a8b92c9329236480</guid>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 19 Mar 2024 14:57:37 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/javaspringboot.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Spring Boot 3 is an advanced framework that simplifies the development of new Spring applications through convention over configuration, providing a range of out-of-the-box functionalities for building enterprise-grade applications efficiently.</p>
<p>We just posted a course on the freeCodeCamp.org YouTube channel that will teach you how to develop apps with Spring Boot and Java. Dan Vega developed this course. Dan is a spring developer advocate, course creator, and speaker.</p>
<p>The course is designed to guide beginners through the nuances of web application development using Spring Boot 3, the cornerstone framework for Java applications. It's a blend of theory and practical application, where you start from the grassroots and ascend to creating sophisticated web applications.</p>
<h2 id="heading-module-breakdown">Module Breakdown</h2>
<p>Here is a description of each module in this course.</p>
<h3 id="heading-module-1-course-introduction">Module 1: Course Introduction</h3>
<p>Dive into the world of Spring Boot 3, starting with an overview of the course structure and objectives. Understand the prerequisites, including Java fundamentals and the necessary development tools like JDK 17+ and your preferred IDE or text editor. This module sets the stage, ensuring you're well-equipped to embark on this learning journey.</p>
<h3 id="heading-module-2-create-your-project">Module 2: Create Your Project</h3>
<p>Kickstart your project with a detailed exploration of how to use start.spring.io for project initialization. This module covers the essentials of Java Build Tools, Maven and Gradle, and best practices for organizing your code, including where to place your code files and the importance of avoiding the default package. Learn the nuances of running your application through an IDE or Maven, and get acquainted with Spring Boot DevTools.</p>
<h3 id="heading-module-3-rest-api">Module 3: REST API</h3>
<p>Delve into creating a REST API, where you'll learn to construct a web application that communicates effectively with clients. Explore the various components of Spring, like @Component, Controller, RestController, Service, and Repository, and understand their roles in your application. This module also covers the basics of CRUD operations in an in-memory setting and introduces you to the principles of dependency injection and data validation.</p>
<h3 id="heading-module-4-working-with-databases">Module 4: Working with Databases</h3>
<p>This module introduces you to integrating and manipulating databases within your Spring Boot application. You'll start with the H2 Database, progressing to more complex interactions using the JDBC Client. Additionally, you'll learn how to elevate your application with Docker Compose and PostgreSQL, ensuring your app can scale and interact with more sophisticated data storage solutions.</p>
<h3 id="heading-module-5-rest-clients">Module 5: Rest Clients</h3>
<p>Explore the construction and utilization of REST clients, crucial for enabling your application to communicate with other web services. This module will guide you through setting up and configuring rest clients to interact with external APIs, enhancing the capability and reach of your application.</p>
<h3 id="heading-module-6-testing">Module 6: Testing</h3>
<p>Ensure your application's reliability and stability by mastering testing with the Spring Boot Testing Toolkit. This module emphasizes the importance of testing in the development lifecycle, teaching you how to create and implement a comprehensive testing suite to validate your application's functionality and performance.</p>
<h2 id="heading-embark-on-your-development-journey">Embark on Your Development Journey</h2>
<p>This course is more than just a learning experience; it's a gateway to the vast world of web application development, offering you the tools and knowledge to build your own web applications with confidence. Whether you're starting from scratch or looking to refine your skills, this course is designed to provide a structured, engaging, and informative path to mastering Spring Boot 3.</p>
<p>Watch the full course on <a target="_blank" href="https://youtu.be/31KTdfRH6nY">the freeCodeCamp.org YouTube channel</a> (3.5 hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/31KTdfRH6nY" 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[ Learn Spring Boot and Spring Data JPA ]]>
                </title>
                <description>
                    <![CDATA[ By mastering Spring Boot and Spring Data JPA, you'll be equipped to build efficient, scalable, and secure applications with ease, making you a valuable asset in the job market and a more effective developer. We just published a comprehensive video co... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-spring-boot-and-spring-data-jpa/</link>
                <guid isPermaLink="false">66b2050d39b555ffda8bfea8</guid>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring data ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 06 Feb 2024 16:05:20 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/springboot.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By mastering Spring Boot and Spring Data JPA, you'll be equipped to build efficient, scalable, and secure applications with ease, making you a valuable asset in the job market and a more effective developer.</p>
<p>We just published a comprehensive video course on the freeCodeCamp.org YouTube channel that teaches Spring Boot and Spring Data JPA, two pivotal technologies in the Java ecosystem. Bouali Ali created this course. Bouali is an experienced developer and teacher.</p>
<p>Spring Boot is an open-source, micro-framework from the larger Spring Framework, designed to simplify the bootstrapping and development of new Spring applications. Its primary goal is to ease the development process by offering a range of out-of-the-box features for configuration, along with embedded servers to facilitate a straightforward setup of web applications. Spring Boot's convention over configuration approach significantly reduces the amount of manual configuration required, making it a preferred choice for developers aiming to deploy applications quickly.</p>
<p>Spring Data JPA, on the other hand, is a part of the larger Spring Data family, aiming to simplify data access within SQL databases. It abstracts boilerplate CRUD operations, providing a more straightforward way to interact with databases through the Java Persistence API (JPA). Spring Data JPA integrates seamlessly with Spring Boot, offering an intuitive approach to handling database operations, reducing the complexity and the amount of code developers need to write.</p>
<p>This course is designed for both beginners and experienced developers who wish to deepen their understanding of Spring Boot and Spring Data JPA.  Here's an overview of the key topics covered in the course:</p>
<h4 id="heading-introduction-to-spring-framework-and-spring-boot">Introduction to Spring Framework and Spring Boot</h4>
<ul>
<li>Overview of Spring Framework</li>
<li>Introduction to Spring Boot</li>
<li>Setting up a Spring Boot project</li>
<li>Understanding Spring Boot auto-configuration</li>
</ul>
<h4 id="heading-spring-boot-basics">Spring Boot Basics</h4>
<ul>
<li>Building RESTful web services with Spring Boot</li>
<li>Spring Boot application properties</li>
<li>Logging with Spring Boot</li>
<li>Building a CRUD API</li>
</ul>
<h4 id="heading-database-access-with-spring-data-jpa">Database Access with Spring Data JPA</h4>
<ul>
<li>Configuring a data source in Spring Boot</li>
<li>Introduction to Spring Data JPA</li>
<li>Implementing repositories</li>
<li>Entity relationships and cascading</li>
<li>Transactions and locking</li>
</ul>
<h4 id="heading-advanced-spring-boot-features">Advanced Spring Boot Features</h4>
<ul>
<li>Securing Spring Boot applications with Spring Security</li>
<li>Token-based authentication</li>
<li>Spring Boot with OAuth2</li>
<li>Microservices with Spring Boot</li>
<li>Deploying Spring Boot applications</li>
</ul>
<h4 id="heading-testing">Testing</h4>
<ul>
<li>Writing unit tests for Spring Boot applications</li>
<li>Integration testing with Spring Boot</li>
</ul>
<h4 id="heading-spring-boot-best-practices">Spring Boot Best Practices</h4>
<ul>
<li>Effective logging practices</li>
<li>Exception handling</li>
<li>Application monitoring with Actuator</li>
<li>Tips for production-ready applications</li>
</ul>
<p>With a blend of theoretical concepts and practical demonstrations, the course aims to equip you with the knowledge and skills required to build robust, efficient applications. Watch the full course <a target="_blank" href="https://www.youtube.com/watch?v=5rNk7m_zlAg">on the freeCodeCamp.org YouTube channel</a> (13-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5rNk7m_zlAg" 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 Monitor Python APIs using Pyctuator and SpringBootAdmin ]]>
                </title>
                <description>
                    <![CDATA[ Actuator endpoints help us monitor our services. By using actuators, we can gain a lot of information about what’s going on. SpringBoot has a number of in-built actuators, and it also allows us to create our own Actuator Endpoint. For frameworks writ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-monitor-python-apis-using-pyctuator-and-springbootadmin/</link>
                <guid isPermaLink="false">66d460f03dce891ac3a96810</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sameer Shukla ]]>
                </dc:creator>
                <pubDate>Fri, 02 Sep 2022 15:02:51 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/Screen-Shot-2022-09-01-at-12.18.52-AM.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Actuator endpoints help us monitor our services. By using actuators, we can gain a lot of information about what’s going on.</p>
<p>SpringBoot has a number of in-built actuators, and it also allows us to create our own Actuator Endpoint.</p>
<p>For frameworks written in Python like Flask or FastAPI, we can incorporate actuators by integrating a library called Pyctuator.</p>
<p>In this article I am going to explain how to monitor applications written in FastAPI using the Pyctuator library. I'll also show you how to manage the actuator endpoints using the SpringBootAdmin server.</p>
<h2 id="heading-what-are-actuators">What are Actuators?</h2>
<p>We use actuators for monitoring and managing application usage in production. This usage information gets exposed to us via REST endpoints.</p>
<p>For example, we can access the application logs in production, environment details, and HTTP traces. And if something has gone wrong within the application, we can even access the applications “threaddump” for debugging purposes.</p>
<p>Here are some examples of few important actuator endpoints:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-16.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Actuators</em></p>
<h2 id="heading-what-is-pyctuator">What is Pyctuator?</h2>
<p>Actuators become popular because of SpringBoot, but you can implement them in frameworks like FastAPI or Flask by integrating a module called Pyctuator.</p>
<p>Pyctuator is a Python Module, which is a partial implementation of SpringBoot Actuators. Pyctuator is managed by SolarEdge.</p>
<p>Some of the actuators supported by Pyctuators are:</p>
<ul>
<li><p>/health: This endpoint in Pyctuator has built-in monitoring for Redis and MySQL</p>
</li>
<li><p>/env</p>
</li>
<li><p>/metrics</p>
</li>
<li><p>/logfile</p>
</li>
<li><p>/threaddump</p>
</li>
<li><p>/httptrace</p>
</li>
<li><p>/loggers</p>
</li>
</ul>
<h2 id="heading-what-is-springbootadmin">What is SpringBootAdmin?</h2>
<p>Imagine a service having all these actuators for checking metrics, httptrace, threaddump and so on. It would be pretty tedious to invoke each one of them individually to check what’s going on within the service. And if we have many services and each one of them has its own actuator endpoints, this makes monitoring even more difficult.</p>
<p>That’s where you can use SpringBootAdmin to manage and monitor applications.</p>
<p>In a nutshell, SpringBootAdmin provides a nice dashboard for all the actuator endpoints in one place.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-30.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Admin Dashboard</em></p>
<h2 id="heading-use-case-for-pyctuator">Use-Case for Pyctuator</h2>
<p>The use-case is straightforward: we are going to develop a RESTful service using FastAPI framework and configure the actuators in the service using the Pyctuator module.</p>
<p>The service has 3 endpoints as shown in the API-Docs (Swagger) below</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-31.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>API-Docs</em></p>
<ul>
<li><p>GET /users: Return all the users that exists in the system.</p>
</li>
<li><p>POST /users: Create user</p>
</li>
<li><p>GET /users/{id}: Return a user with a given id</p>
</li>
</ul>
<p>You can find the code <a target="_blank" href="https://github.com/sameershukla/fastapi-pyctuator">here</a>.</p>
<p>In the User-Service we are going to enable the actuators using Pyctuator and monitor them using SpringBootAdmin dashboard. We are also going to explore how we can enhance the /health actuator for monitoring Redis.</p>
<p>For configuring the Actuators, first we need to install “pyctuator”. You can do that using the command “pip install pyctuator”.</p>
<p>After installation, simply instantiating the Pyctuator object is the entry point for seeing in-built actuators within a web-framework.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-47.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Pyctuator Constructor</em></p>
<p>Before instantiating Pyctuator, if you access the /pyctuator endpoint you will get the “Not Found” message:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-91.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Without Pyctuator Configuration</em></p>
<p>After instantiation, on accessing the /pyctuator endpoint you will see all the actuators enabled by default. This is because we have defined "pyactuator_endpoint_url" within Pyctuator.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-93.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>After Pyctuator Configuration</em></p>
<p>I strongly recommend going through the Pyctuator object as it explains what the mandatory and optional arguments are that we need to provide.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-114.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Understanding Constructor parameters</em></p>
<p>The mandatory parameters are:</p>
<ul>
<li><p>app – instance of FastAPI or Flask</p>
</li>
<li><p>the application name – displayed in the info section in SpringBootAdmin</p>
</li>
<li><p>“pyctuator_endpoint_url” – what we have seen which returns all the actuator endpoints</p>
</li>
<li><p>“registration_url” – you will understand this one shortly.</p>
</li>
</ul>
<h2 id="heading-how-to-enhance-the-health-endpoint">How to Enhance the /health Endpoint</h2>
<p>You can enhance the /health endpoint in Pyctuator to monitor Redis or MySQL databases. Say you are using Redis in your application – then we need to use RedisHealthProvider and pass the redis instance to it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-174.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Redis Health</em></p>
<h2 id="heading-how-to-start-the-springbootadmin-server">How to Start the SpringBootAdmin Server</h2>
<p>To run the SpringBootAdmin server on local, we have two options: first, we can do it by creating SpringBootAdmin manually by going to start.spring.io and adding libraries.</p>
<p>Spring Web &amp; Spring Boot Admin (Server):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-175.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Creating SpringBootAdmin</em></p>
<p>The second option is to run a Docker image:</p>
<pre><code class="lang-docker">docker <span class="hljs-keyword">run</span><span class="bash"> --rm --name spring-boot-admin -p 8080:8080 michayaak/spring-boot-admin:2.2.3-1</span>
</code></pre>
<p>Once the admin server is up, we need to provide the “registration_url” to the Pyctuator Constructor as discussed earlier.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-178.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>URL registration in SpringBootAdmin</em></p>
<p>The Admin Server is running on localhost:8080 and this should register our application to SpringBootAdmin. We can access all the actuator endpoints in one place:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-181.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Dashboard</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-182.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>All Configured Actuator Endpoints</em></p>
<p>I executed the /users endpoint few times and now HTTP Traces on the Admin side showcases all the Request-Response exchange details.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-191.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>HTTP Traces</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Actuators are extremely helpful in monitoring and debugging applications in production. By accessing endpoints we can get details on thread dumps, heap dumps, HTTP Traces and so on.</p>
<p>Pyctuator simplifies having actuators in Python APIs to a great extent. By simply importing the library and defining an object, all the actuators are ready for us within our application.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Perform Integration Testing using JUnit 5 and TestContainers with SpringBoot ]]>
                </title>
                <description>
                    <![CDATA[ TestContainers is a library that helps you run module-specific Docker containers to simplify Integration Testing. These Docker containers are lightweight, and once the tests are finished the containers get destroyed. In the article we are going to un... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/integration-testing-using-junit-5-testcontainers-with-springboot-example/</link>
                <guid isPermaLink="false">66d460f437bd2215d1e245c9</guid>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Software Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sameer Shukla ]]>
                </dc:creator>
                <pubDate>Fri, 26 Aug 2022 15:46:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/testcontainers-logo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>TestContainers is a library that helps you run module-specific Docker containers to simplify Integration Testing.</p>
<p>These Docker containers are lightweight, and once the tests are finished the containers get destroyed.</p>
<p>In the article we are going to understand what the TestContainers is and how it helps you write more reliable Tests.</p>
<p>We are also going to understand the important components (Annotations and Methods) of the library which help you write the Tests.</p>
<p>Finally, we will also learn to write a proper Integration Test in SpringBoot using the TestContainers library and its components.</p>
<h2 id="heading-limitations-of-testing-with-an-h2-in-memory-database">Limitations of Testing with an H2 In-Memory Database</h2>
<p>The most common approach to Integration Testing today is to use an H2 in-memory database. But there are certain limitations to this method.</p>
<p>First of all, say we are using version 8.0 of MySQL in production, but our integration tests are using H2. We can never execute our tests for the database version running on Production.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-303.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>SpringBoot app with MySQL DB and H2</em></p>
<p>‌Secondly, the test cases are less reliable because in production we are using an altogether different database and the tests are pointing to H2. The application may run into issues in production, but the integration tests may succeed.</p>
<p>I was trying to access my RESTful service on local and faced this error:</p>
<p>“<strong>Caused by: org.postgresql.util.PSQLException: FATAL: database "example_db" does not exist</strong>”.</p>
<p>It happened because of a permission issue, but the tests on local worked fine.</p>
<p>And finally, as documented <a target="_blank" href="http://h2database.com/html/features.html#compatibility">here</a>, H2 is compatible with other databases only up to a certain point. There are few areas where H2 is incompatible. If you need to use “nativeQueries” in a SpringBoot application, for example, then using H2 may cause problems.</p>
<h2 id="heading-enter-the-testcontainers-library">Enter the TestContainers Library</h2>
<p>By using TestContainers we can overcome the limitations of H2.</p>
<ul>
<li><p>Integration tests will point to the same version of the database as it’s in production. So we can tie our TestContainer Database Image to the same version running on production.</p>
</li>
<li><p>Integration tests are lot more reliable because both application and tests are using the same database type and version and there won't be any compatibility issues in Testcases.</p>
</li>
</ul>
<h2 id="heading-what-is-testcontainers">What is TestContainers?</h2>
<p>The TestContainers library is a wrapper API over Docker. When we write code to create a container behind the scenes it may be translated to some Docker command, for example‌:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-283.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>MySQLContainer Creation</em></p>
<p>This code may be translated to something like the following:</p>
<pre><code class="lang-docker">docker <span class="hljs-keyword">run</span><span class="bash"> -d --env MYSQL_DATABASE=example_db --env MYSQL_USER=<span class="hljs-built_in">test</span> --env MYSQL_PASSWORD=<span class="hljs-built_in">test</span> ‘mysql:latest’</span>
</code></pre>
<p>TestContainers has a method name “withCommand”. You use it to set the command that should be run inside the Docker container which confirms that TestContainers is a wrapper API over Docker.</p>
<p>TestContainers downloads the MySQL, Postgres, Kafka, Redis images and runs in a container. The MySQLContainer will run a MySQL Database in a container and the Testcases can connect to it on the local machine. Once the execution is over the Database will be gone – it just deletes it from the machine. In the Testcases we can start as many container images as we want.</p>
<p>TestContainers supports JUnit 4, JUnit 5 and Spock. If you go to the TestContainers.org website, just visit the QuickStart section that explains how to use it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-284.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>TestContainers.org how to start with Test Framework</em></p>
<p>TestContainers supports almost every Database from MySQL and Postgres to CockroachDB. You can find more info about this on the TestContainers.org website under the Modules section:‌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-285.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>TestContainers support for Database Modules</em></p>
<p>‌TestContainers also supports Cloud Modules like GCloud Module and Azure Module as well. If your application is running on Google Cloud, then TestContainers has support for Cloud Spanner, Firestore, Datastore and so on.‌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-286.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>TestContainers support for GCloud Module</em></p>
<p>In the article so far, we have discussed only about Databases, but TestContainers supports various other components like Kafka, SOLR, Redis, and more.</p>
<h2 id="heading-how-to-use-the-testcontainers-library">How to Use the TestContainers Library</h2>
<p>In this article we are going to explore TestContainers with JUnit 5. To implement TestContainers we need to understand a few important TestContainers annotations, methods, and the libraries that we need to implement in our project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-288.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>TestContainers libraries</em></p>
<h3 id="heading-annotations-in-testcontainers">Annotations in TestContainers</h3>
<p>Two important annotations are required in our Tests for TestContainers to work: @TestContainers and @Container.</p>
<p>@TestContainer is JUnit-Jupiter extension which automatically starts and stops the containers that are used in the tests. This annotation finds the fields that are marked with @Container and calls the specific Container life-cycle methods. Here, MySQLContainer life-cycle methods will be invoked.‌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-289.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>MySQLContainer</em></p>
<p>The MySQLContainer is declared as static because if we declare Container as static then a single container is started and it will be shared across all the test methods.</p>
<p>If it’s an instance variable, then a new container is created for each test method.</p>
<h2 id="heading-testcontainers-library-methods">TestContainers Library Methods</h2>
<p>There are few important methods in TestContainers library that you'll use in the tests. They're good to know before using the library.</p>
<ul>
<li><p><strong>withInitScript</strong>: Using ‘withInitScript’ we can execute the .SQL to define the schema, tables, and plus add the data into the database. In short, this method is used to run the .SQL to populate the database.</p>
</li>
<li><p><strong>withReuse</strong> (true): Using “withReuse” method we can enable the reuse of containers. This method works well in conjunction with enabling the “testcontainers.reuse.enable:true” property in the “.testcontainers.properties” file.</p>
</li>
<li><p><strong>start</strong>: we use this to start the container.</p>
</li>
<li><p><strong>withClasspathResourceMapping</strong>: This maps a resource (file or directory) on the classpath to a path inside the container. This will only work if you are running your tests outside a Docker container.</p>
</li>
<li><p><strong>withCommand</strong>: Set the command that should be run inside the Docker container.</p>
</li>
<li><p><strong>withExposedPorts</strong>: Used to set the port that the container listens on.</p>
</li>
<li><p><strong>withFileSystemBind</strong>: Used to map a file / directory from the local filesystem into the container.</p>
</li>
</ul>
<h2 id="heading-testcontainers-use-case">TestContainers Use Case</h2>
<p>In the example we'll look at now, the application will communicate only with the database and write the integration tests for it using TestContainers. Then we'll extend the use-case by implementing Redis in between.</p>
<p>If the data exists in the Redis cache it will be returned, otherwise it'll dip into the database for saving and retrieval based on the Key.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-308.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Use-Case</em></p>
<p>The service is simple. It has 2 endpoints – the first one is to create a user and the second one is to find a user by email. If the user is found it is returned, otherwise we get a 404. The service class code looks something like this:‌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-291.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Service Component</em></p>
<p>We are going to write tests for this class. You can find the entire codebase <a target="_blank" href="https://github.com/sameershukla/testcontainers_demo">here</a>:‌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-292.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Test Class</em></p>
<p>The test class is marked with @TestContainers annotation which starts/stops the container. We use the @Container annotation to call the specific container's life-cycle methods.</p>
<p>Also, the “MySQLContainer” is declared as static because then a single container is started. Then it gets shared across all the test methods (we have already discussed the importance of these annotations).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-293.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>BeforeAll</em></p>
<p>Next we need to write a setup method marked with @BeforeAll, where we have enabled the “withReuse” method. This helps us reuse the existing containers. We are using the “withInitScript” method to execute the “.sql” file and then starting the container.‌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-294.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Overwriting Properties</em></p>
<p>‌@DynamicPropertySource helps us override the properties declared in the properties file. We write this method to allow TestContainers to create the URL, username, and password on its own – otherwise we may face errors.</p>
<p>For example on removing username and password we may face an ‘Access denied’ error which may confuse us. So it’s better to allow TestContainer to assign these properties dynamically on its own.</p>
<p>That’s it – we are ready to run the Testcases:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-295.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Test Cases</em></p>
<p>Execute @AfterAll to stop the container, otherwise it may keep running on your local machine if you don't explicitly stop it. ‌</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-296.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-use-genericcontainer">How to Use GenericContainer</h2>
<p>‌‌GenericContainer is the most flexible container. It makes it easy to run any container images within GenericContainer.</p>
<p>Now we have Redis in place, all we need to do in our Testcase is to spin up a GenericContainer with the Redis image.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-297.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>GenericContainer for Redis</em></p>
<p>Then we start the Generic Redis container in @BeforeAll and stop it with the @AfterAll tear down method.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-298.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Starting Containers</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-299.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Stopping Containers</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>It's extremely easy to use TestContainers in our application to write better tests. The learning curve is not too steep and it has support for various different modules from a variety of databases like Kafka, Redis and others.</p>
<p>Writing tests using TestContainers makes our tests lot more reliable. The only flip side is that the tests are slow compared to H2. This is because H2 is in memory and TestContainers takes time to download the image, run the container, and execute the entire setup we have discussed in this article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Spring Boot Tutorial – How to Build Fast and Modern Java Apps ]]>
                </title>
                <description>
                    <![CDATA[ By Yiğit Kemal Erinç In this article I am going to walk you through building a prototype with Spring Boot. Think of it like building a project for a hackathon or a prototype for your startup in limited time.  In other words, we are not trying to buil... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/spring-boot-tutorial-build-fast-modern-java-app/</link>
                <guid isPermaLink="false">66d45e4b182810487e0ce161</guid>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 20 Sep 2021 19:43:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/pexels-ramdas-ware-102896.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Yiğit Kemal Erinç</p>
<p>In this article I am going to walk you through building a prototype with Spring Boot. Think of it like building a project for a hackathon or a prototype for your startup in limited time. </p>
<p>In other words, we are not trying to build something perfect – but rather something that works.</p>
<p>If you get stuck in any part of this tutorial or if I have forgotten to mention something, you can check out the GitHub repository I have included in the <strong>Conclusion</strong>.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Foundations of Java and OOP</li>
<li>Basic knowledge of relational databases (one-to-many, many-to-many, and so on)</li>
<li>Fundamentals of Spring would be helpful</li>
<li>Basic level HTML</li>
</ul>
<p>Also make sure you have the following:</p>
<ul>
<li><a target="_blank" href="https://www.oracle.com/java/technologies/javase-downloads.html">JDK (Java Development Kit)</a> latest</li>
<li><a target="_blank" href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a> or some other Java IDE</li>
</ul>
<h2 id="heading-what-are-we-building">What are we building?</h2>
<p>We will build an amenity reservation system where users will log in and reserve a time to use a service such as fitness center, pool, or sauna. </p>
<p>Each amenity will have a certain capacity (number of people that can use the service at the same time) so that people can make use of the amenities safely during the Covid-19 pandemic.</p>
<h3 id="heading-list-of-features-for-the-app">List of Features for the App</h3>
<p>We can think of our app as the reservation system for an apartment complex. </p>
<ul>
<li>Users should be able to log in.</li>
<li>We will assume that the accounts of residents are pre-created and there will be no sign-up feature.</li>
<li>Users should be able to view their reservations. </li>
<li>Users should be able to create new reservations by selecting the amenity type, date, and time.</li>
<li><strong>Only logged-in</strong> <strong>users</strong> should be able to see the reservations page and create reservations.</li>
<li>We should check the capacity and only create new reservations if the current number of reservations does not exceed the capacity.</li>
</ul>
<h3 id="heading-technologies-well-use">Technologies We'll Use</h3>
<p>We will learn about a lot of useful technologies that will make you more efficient as a Spring Boot developer. I will briefly mention what they are and what they are good for and then we will see them in action.</p>
<ul>
<li>Bootify</li>
<li>Hibernate</li>
<li>Spring Boot</li>
<li>Maven</li>
<li>JPA</li>
<li>Swagger</li>
<li>H2 In-Memory Database</li>
<li>Thymeleaf</li>
<li>Bootstrap</li>
<li>Spring Security</li>
</ul>
<h2 id="heading-why-spring-boot">Why Spring Boot?</h2>
<p>The Spring framework is generally used for enterprise level/large scale jobs. It is not usually the first option that comes to mind for smaller projects – but I will argue that it can be quite fast for prototyping. </p>
<p>It has the following advantages:</p>
<ul>
<li>Annotation-based development generates a lot of code for you behind the scenes. And especially with the availability of libraries like Lombok, it has became a lot easier to focus on the business logic.</li>
<li>It has nice in-memory database support, so that we don't need to create a real database and connect to it. (H2)</li>
<li>It has a mature ecosystem so you can readily find answers to most questions.</li>
<li>Almost "no configuration" is required. With the help of Spring Boot, we get rid of ugly XML configurations on the Spring side of things and configuring your application is really easy.</li>
<li>There's a lot happening behind the scenes. Spring provides so much magic and does so many things to get things going. So you don't usually need to care about that stuff and can just let the framework handle things.</li>
<li>We have <a target="_blank" href="https://github.com/spring-projects/spring-security">Spring Security.</a> Having one of the most comprehensive, battle-tested security frameworks on your side gives you more confidence in the security of your application. It also takes care of a good share of the hard work for you.</li>
</ul>
<h2 id="heading-how-to-create-the-project-with-bootify">How to Create the Project with Bootify</h2>
<p>To create the project, you will use <a target="_blank" href="https://bootify.io/"><strong>Bootify</strong></a>. It's a freemium service that makes Spring Boot development faster by generating a lot of boilerplate code for you and letting you focus on business logic instead.</p>
<p><strong>Bootify</strong> allows us to specify our preferences and automatically imports the dependencies similar to <strong>Spring Initializr</strong>. </p>
<p>But there is more than that. You can also specify your entities and it will generate the corresponding model and DTO classes. It can even generate the service and controller level code for common <strong>CRUD</strong> operations.</p>
<p>I believe it is a more convenient tool for API development than it is for MVC apps since it generates REST API code by default. But it will still make our lives easier even with a Spring Boot MVC application that contains views. We will just need to make some adjustments to the generated code.</p>
<p>Let's open the <strong>Bootify</strong> website and click the "Start Project" button at the top right corner.</p>
<p>You should select:</p>
<ul>
<li><strong>Maven</strong> as the build type</li>
<li>Java version: 14</li>
<li>Tick enable <strong>Lombok</strong></li>
<li>DBMS: <strong>H2</strong> database</li>
<li>Tick <strong>add</strong> <strong>dateCreated/lastUpdated</strong> to entities</li>
<li>Packages: Technical</li>
<li>Enable <strong>OpenAPI/Swagger UI</strong></li>
<li>Add <strong>org.springframework.boot:spring-boot-devtools</strong> to further dependencies</li>
</ul>
<p>After you are done, you should see this:</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/screencapture-bootify-io-app-8U9U2BBTLEAX-2021-04-09-16_06_29-1024x754.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now let's specify our entities. Start by clicking the <strong>Entities</strong> tab on the left menu.</p>
<p>We will have the following entities and relations:</p>
<ol>
<li><strong>Reservation</strong> that contains the data related to each reservation such as reservation date, reservation starting time, ending time, and the user who owns this reservation.</li>
<li>The <strong>User</strong> entity that contains our user model and will have relations with <strong>Reservation</strong>.</li>
<li>The <strong>Amenity</strong> entity to hold the type of Amenity and its capacity (maximum number of reservations for a certain time, for example 2 people can use and reserve the Sauna for the same time).</li>
</ol>
<p>Let's define our <strong>Reservation</strong> entity as follows and keep "Add REST endpoints" checked (even though we will modify the output). Then click the Save button.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-1-1024x577.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We will specify the relations later, so the only field that our user entity has is the id field.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-1024x445.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We could create an entity for Amenities to store the data of the amenity name and its capacity and then we could reference it from the <strong>Reservation</strong>. But the relationship between Amenity and Reservation would be one-to-one. </p>
<p>So instead, for the sake of simplicity, we will create an enum called <strong>AmenityType</strong> and store the <strong>AmenityType</strong> inside <strong>Reservation</strong>.</p>
<p>Now let's create a relationship between the <strong>User</strong> and <strong>Reservation</strong> entities by clicking the + button next to the <strong>Relations</strong> menu.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Menu to create relations</em></p>
<p>It will be a <strong>Many-to-one</strong> relationship since a user can have many reservations but a reservation must have one and only one user. We will make sure this is the case by checking the required box.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-3-1024x507.png" alt="Image" width="600" height="400" loading="lazy">
<em>User-Reservation Relation</em></p>
<p>We click "Save Changes" and we are done. Your final model should look like this:</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-4-1024x481.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Now click the download button on the left menu to download the generated project code so we can start working on it. You can see the first commit on the project repository to compare with yours if you have any problems.</p>
<p>After you download the project, open it in an IDE – I'll use <strong>IntelliJ IDEA</strong>. Your file structure should look like this:</p>
<pre><code>├── amenity-reservation-system.iml
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── amenity_reservation_system
│       │           ├── AmenityReservationSystemApplication.java
│       │           ├── HomeController.java
│       │           ├── config
│       │           │   ├── DomainConfig.java
│       │           │   ├── JacksonConfig.java
│       │           │   └── RestExceptionHandler.java
│       │           ├── domain
│       │           │   ├── Reservation.java
│       │           │   └── User.java
│       │           ├── model
│       │           │   ├── ErrorResponse.java
│       │           │   ├── FieldError.java
│       │           │   ├── ReservationDTO.java
│       │           │   └── UserDTO.java
│       │           ├── repos
│       │           │   ├── ReservationRepository.java
│       │           │   └── UserRepository.java
│       │           ├── rest
│       │           │   ├── ReservationController.java
│       │           │   └── UserController.java
│       │           └── service
│       │               ├── ReservationService.java
│       │               └── UserService.java
│       └── resources
│           └── application.yml
└── target
    ├── classes
    │   ├── application.yml
    │   └── com
    │       └── amenity_reservation_system
    │           ├── AmenityReservationSystemApplication.class
    │           ├── HomeController.class
    │           ├── config
    │           │   ├── DomainConfig.class
    │           │   ├── JacksonConfig.class
    │           │   └── RestExceptionHandler.class
    │           ├── domain
    │           │   ├── Reservation.class
    │           │   └── User.class
    │           ├── model
    │           │   ├── ErrorResponse.class
    │           │   ├── FieldError.class
    │           │   ├── ReservationDTO.class
    │           │   └── UserDTO.class
    │           ├── repos
    │           │   ├── ReservationRepository.class
    │           │   └── UserRepository.class
    │           ├── rest
    │           │   ├── ReservationController.class
    │           │   └── UserController.class
    │           └── service
    │               ├── ReservationService.class
    │               └── UserService.class
    └── generated-sources
        └── annotations
</code></pre><h2 id="heading-how-to-test-and-explore-the-generated-code">How to Test and Explore the Generated Code</h2>
<p>Let's take our time to experiment with the generated code and understand it layer by layer.</p>
<p>The <strong>Repos</strong> folder contains the code for the data access layer, namely our repositories. We will use <strong>JPA</strong> methods to retrieve our data, which are pre-made query methods you can use by defining them inside the repository interface. </p>
<p>Notice that our repository classes extend the <strong>JpaRepository</strong> interface. This is the interface that allows us to use the mentioned methods. </p>
<p>JPA queries follow a certain convention, and when we create the method that obeys the conventions, it will automatically know what data you want to retrieve, behind the scenes. If you don't yet get it, do not worry, we will see examples.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-5-1024x719.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example keywords, sample phrases and their corresponding JPQL snippets (queries)</em></p>
<p>The <strong>Model</strong> classes present our data model, and which classes will have which fields. </p>
<p>Each model class corresponds to a database table with the same name and the fields in the model class will be columns in the corresponding table. </p>
<p>Notice the annotation <strong>@Entity</strong> on top of our model classes. This annotation is handled by <a target="_blank" href="https://hibernate.org/"><strong>Hibernate</strong></a> and whenever Hibernate sees <strong>@Entity</strong>, it will create a table using the name of our class as table name. </p>
<p>If you are wondering, "What is Hibernate anyways?", it is an <strong>object-relational-mapping</strong> (ORM) tool for Java that allows us to map the <strong>POJOs</strong> (Plain Old Java Object) to database tables. It can also provide features such as data validation constraints, but we will not go deep into Hibernate in this post since it is a vast topic on its own. </p>
<p>An awesome feature of Hibernate is that it handles all table creation and deletion operations so you don't have to use additional <strong>SQL</strong> scripts.</p>
<p>We also represent the relationships between objects in model classes. To see an example, take a look at our <strong>User</strong> class:</p>
<pre><code class="lang-java">    <span class="hljs-meta">@OneToMany(mappedBy = "user")</span>
    <span class="hljs-keyword">private</span> Set&lt;Reservation&gt; userReservations;
</code></pre>
<p>It has a <strong>userReservations</strong> object that holds a set of references that resembles the reservations of this particular user. In the <strong>Reservation</strong> class we have the reverse-relation as:</p>
<pre><code class="lang-java"><span class="hljs-meta">@ManyToOne(fetch = FetchType.LAZY)</span>
<span class="hljs-meta">@JoinColumn(name = "user_id", nullable = false)</span>
<span class="hljs-keyword">private</span> User user;
</code></pre>
<p>Having references on both sides makes it possible to access the other side of the relationship (user object to reservation and vice versa).</p>
<p><strong>Controllers</strong> will handle the requests that are passed to this controller by the request handler and return the corresponding views, in this case. </p>
<p>The controllers that were generated by Bootify are configured to return JSON responses, and we will modify them in the next section to return our views.</p>
<p><strong>Services</strong> will hold the logic of our application. The best practice is to keep controllers thin by keeping the business logic in a separate place, the service classes. </p>
<p>Controllers should not interact with the repositories directly, but instead call the service which will interact with the repository, perform any additional operation, and return the result to the controller.</p>
<h3 id="heading-lets-try-out-the-api">Let's Try Out the API</h3>
<p>Now, let's get to the fun part and try our API to see it on action. Run the Spring application on your favorite IDE. Open your browser and go to this address:</p>
<pre><code>http:<span class="hljs-comment">//localhost:8080/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config#/</span>
</code></pre><p>Swagger automatically documents our code and allows you to send requests easily. You should be seeing this:</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/screencapture-localhost-8080-swagger-ui-index-html-2021-04-17-21_27_48-1024x914.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let's first create a user by sending a <strong>POST</strong> request to <strong>UserController</strong>. We will do that by clicking the last box (the green one) under user-controller list.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/Screen-Shot-2021-04-17-at-21.30.41-1024x565.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Swagger</strong> shows us the parameters that this endpoint expects – only the id for now – and also the responses that the API returns. </p>
<p>Click the "Try it out" button at the top right corner. It asks you to enter an id. I know it is nonsense and the code will not even use this id you enter, but we will fix that in the next section (it is just a problem with the generated code). </p>
<p>For the sake of experimenting, enter any number, like 1 for the id, and click the execute button.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/screencapture-localhost-8080-swagger-ui-index-html-2021-04-17-21_39_32-547x1024.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The response body contains the id of the created object. We can confirm that it is created on the database by checking the H2 console. </p>
<p>But before doing that, we need to make a minor adjustment to the <strong>application.yml</strong> file which contains the application settings and configuration. Open your <strong>application.yml</strong> file and paste in the following code:</p>
<pre><code>spring:
  datasource:
    url: ${<span class="hljs-attr">JDBC_DATABASE_URL</span>:jdbc:h2:mem:amenity-reservation-system}
    <span class="hljs-attr">username</span>: ${<span class="hljs-attr">JDBC_DATABASE_USERNAME</span>:sa}
    <span class="hljs-attr">password</span>: ${<span class="hljs-attr">JDBC_DATABASE_PASSWORD</span>:}
  <span class="hljs-attr">dbcp2</span>:
    max-wait-millis: <span class="hljs-number">30000</span>
    validation-query: <span class="hljs-string">"SELECT 1"</span>
    validation-query-timeout: <span class="hljs-number">30</span>
  <span class="hljs-attr">jpa</span>:
    hibernate:
      ddl-auto: update
    open-<span class="hljs-keyword">in</span>-view: <span class="hljs-literal">false</span>
    <span class="hljs-attr">properties</span>:
      hibernate:
        jdbc:
          lob:
            non_contextual_creation: <span class="hljs-literal">true</span>
        <span class="hljs-attr">id</span>:
          new_generator_mappings: <span class="hljs-literal">true</span>
<span class="hljs-attr">springdoc</span>:
  pathsToMatch: <span class="hljs-regexp">/api/</span>**
</code></pre><p>Then we should be able to access the H2 console by going to this address:</p>
<pre><code>http:<span class="hljs-comment">//localhost:8080/h2-console/</span>
</code></pre><p><img src="https://erinc.io/wp-content/uploads/2021/04/image-6-1024x724.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here you need to check that the username is "sa" and click the Connect button.</p>
<p>Click the USER table on the left menu and the console will write the select all query for you.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-7-1024x573.png" alt="Image" width="600" height="400" loading="lazy">
<em>H2 Admin Panel</em></p>
<p>Let's click the <strong>Run</strong> button that is above the query.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-8-1024x466.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can see that the <strong>User</strong> object is indeed created – great!</p>
<p>We already have a working API at this point and we have not written a single line of code.</p>
<h3 id="heading-how-to-adjust-the-code-for-our-use-case">How to Adjust the Code for our Use Case</h3>
<p>As I mentioned earlier, the generated code does not fully suit our use case and we need to make some adjustments to it. </p>
<p>Let's remove the model folder which contains DTOs and stuff that we will not use. We will show the data inside views instead.</p>
<pre><code>cd src/main/java/com/amenity_reservation_system/ 
rm -rf model
</code></pre><p>We will have a lot of errors now since the code uses the DTO classes, but we will get rid of most of it after removing the controller classes. </p>
<p>We will delete the controllers because we do not want to expose the functionality of modifying our data anymore. Our users should be able to do that by interacting with our UI, and we will create new controllers to return the view components in the next section.</p>
<pre><code>rm -rf rest
</code></pre><p>Finally, we need to do some refactoring to our service classes since the DTO classes are not present anymore:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.service;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.domain.User;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.UserRepository;
<span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.stream.Collectors;
<span class="hljs-keyword">import</span> org.springframework.http.HttpStatus;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;
<span class="hljs-keyword">import</span> org.springframework.web.server.ResponseStatusException;


<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> <span class="hljs-keyword">final</span> UserRepository userRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserService</span><span class="hljs-params">(<span class="hljs-keyword">final</span> UserRepository userRepository)</span> </span>{
        <span class="hljs-keyword">this</span>.userRepository = userRepository;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;User&gt; <span class="hljs-title">findAll</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.findAll();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">get</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Long id)</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.findById(id)
                .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResponseStatusException(HttpStatus.NOT_FOUND));
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> Long <span class="hljs-title">create</span><span class="hljs-params">(<span class="hljs-keyword">final</span> User user)</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.save(user).getId();
    }

    <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">(<span class="hljs-keyword">final</span> Long id, <span class="hljs-keyword">final</span> User user)</span> </span>{
        <span class="hljs-keyword">final</span> User existingUser = userRepository.findById(id)
                .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResponseStatusException(HttpStatus.NOT_FOUND));

        userRepository.save(user);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">delete</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Long id)</span> </span>{
        userRepository.deleteById(id);
    }
}
</code></pre>
<p>We basically removed the DTO-related code from the <strong>UserService</strong> class and replaced the return types with <strong>User</strong>. Let's do the same for <strong>ReservationService</strong>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.service;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.domain.Reservation;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.domain.User;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.ReservationRepository;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.UserRepository;
<span class="hljs-keyword">import</span> java.util.List;
<span class="hljs-keyword">import</span> java.util.stream.Collectors;
<span class="hljs-keyword">import</span> org.springframework.http.HttpStatus;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;
<span class="hljs-keyword">import</span> org.springframework.web.server.ResponseStatusException;


<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">ReservationService</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ReservationRepository reservationRepository;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserRepository userRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ReservationService</span><span class="hljs-params">(<span class="hljs-keyword">final</span> ReservationRepository reservationRepository,
            <span class="hljs-keyword">final</span> UserRepository userRepository)</span> </span>{
        <span class="hljs-keyword">this</span>.reservationRepository = reservationRepository;
        <span class="hljs-keyword">this</span>.userRepository = userRepository;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> List&lt;Reservation&gt; <span class="hljs-title">findAll</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> reservationRepository.findAll();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> Reservation <span class="hljs-title">get</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Long id)</span> </span>{
        <span class="hljs-keyword">return</span> reservationRepository.findById(id)
                .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResponseStatusException(HttpStatus.NOT_FOUND));
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> Long <span class="hljs-title">create</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Reservation reservation)</span> </span>{
        <span class="hljs-keyword">return</span> reservationRepository.save(reservation).getId();
    }

    <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">(<span class="hljs-keyword">final</span> Long id, <span class="hljs-keyword">final</span> Reservation reservation)</span> </span>{
        <span class="hljs-keyword">final</span> Reservation existingReservation = reservationRepository.findById(id)
                .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> ResponseStatusException(HttpStatus.NOT_FOUND));
        reservationRepository.save(reservation);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">delete</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Long id)</span> </span>{
        reservationRepository.deleteById(id);
    }

}
</code></pre>
<p>Let's also remove the config classes:</p>
<pre><code>rm -rf config
</code></pre><p>And rename the domain folder to model. If you are using an IDE, I strongly advise that you use your IDE's rename functionality to rename this folder since it will automatically rename the imports to match the new package name.</p>
<pre><code>mv domain model
</code></pre><p>Also, make sure that your model classes (<strong>User</strong> and <strong>Reservation</strong>) have the right package name after this operation. The first line of these two files should be:</p>
<pre><code>package com.amenity_reservation_system.model;
</code></pre><p>If it stays as domain package, you may have errors.</p>
<p>At this point, you should be able to compile and run the project without any problems.</p>
<h2 id="heading-how-to-create-the-controllers-and-view-files-to-show-data">How to Create the Controllers and View Files to Show Data</h2>
<p><strong>Thymeleaf</strong> is a template engine for Spring that allows us to create UIs and display our model data to the users. </p>
<p>We can access the Java objects inside the Thymeleaf template, and we can also use plain old HTML, CSS and JavaScript. If you know about JSPs, this is JSP on steroids.</p>
<p>Let's create some Thymeleaf templates that will not do anything but show the data for now. We will style them in the next section. We will also create the controllers that will return these views.</p>
<p>Before getting started with the Thymeleaf templates, we need to add a Maven dependency for Spring Boot Thymeleaf. Your dependencies should look like this in your <strong>pom.xml</strong> file:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">project</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0"</span> <span class="hljs-attr">xmlns:xsi</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema-instance"</span>
        <span class="hljs-attr">xsi:schemaLocation</span>=<span class="hljs-string">"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">modelVersion</span>&gt;</span>4.0.0<span class="hljs-tag">&lt;/<span class="hljs-name">modelVersion</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">parent</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-parent<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.4.4<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">relativePath</span> /&gt;</span><span class="hljs-comment">&lt;!-- lookup parent from repository --&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">parent</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>com<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>amenity-reservation-system<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>0.0.1-SNAPSHOT<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">name</span>&gt;</span>amenity-reservation-system<span class="hljs-tag">&lt;/<span class="hljs-name">name</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">properties</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">java.version</span>&gt;</span>14<span class="hljs-tag">&lt;/<span class="hljs-name">java.version</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">properties</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">dependencies</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-starter-web<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>
        <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-validation<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>
        <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-data-jpa<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>
        <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.h2database<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>h2<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>runtime<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">dependency</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springdoc<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>springdoc-openapi-ui<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.2<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">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-devtools<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>
        <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.projectlombok<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>lombok<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.18.20<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>provided<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">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-test<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">dependency</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">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-thymeleaf<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>

    <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-tag">&lt;<span class="hljs-name">plugin</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>org.springframework.boot<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>spring-boot-maven-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">plugins</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">build</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">project</span>&gt;</span>
</code></pre>
<p>You can just copy and paste the inner content of the dependencies tag. Now let's tell Maven to install the dependencies:</p>
<pre><code>mvn clean install
</code></pre><p>We are now ready to create our views. Let's create a directory under resources to hold our view template files like this:</p>
<pre><code>cd ../../../resources
mkdir templates
</code></pre><p>And create a view file:</p>
<pre><code>cd templates
touch index.html
</code></pre><p>Copy and paste the following snippet into it. This file will be our home page in the future.</p>
<pre><code>&lt;!DOCTYPE HTML&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">"http://www.thymeleaf.org"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>/&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Amenities Reservation App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">th:rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css} "</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
hello world!
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/jquery/3.0.0/jquery.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/popper.js/1.12.9-1/umd/popper.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre><p>We also need to create a controller that will return us this view so we can see it in the browser.</p>
<pre><code>cd ../java/com/amenity_reservation_system
mkdir controller &amp;&amp; cd controller
touch HomeController
</code></pre><p>Paste this code into the HomeController:</p>
<pre><code>package com.amenity_reservation_system.controller;

<span class="hljs-keyword">import</span> org.springframework.stereotype.Controller;
<span class="hljs-keyword">import</span> org.springframework.ui.Model;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.GetMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.ResponseBody;


@Controller
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeController</span> </span>{

    @GetMapping(<span class="hljs-string">"/"</span>)
    public <span class="hljs-built_in">String</span> index(Model model) {

        <span class="hljs-keyword">return</span> <span class="hljs-string">"index"</span>;
    }
}
</code></pre><p>Notice how we annotate our method with <strong>@Controller</strong> instead of <strong>@RestController</strong> this time. The @RestController annotation implies that the controller will return a REST response whereas a <strong>@Controller</strong> can return pre-rendered (SSR) views/HTML.</p>
<p>When a request arrives in our application, Spring will automatically run this controller method. Then it will find the <strong>index.html</strong> file we previously created under the resources and send that file to the client.</p>
<p>Let's confirm that it is working by sending a request to our application. Do not forget to restart first, then send this request:</p>
<pre><code>GET localhost:<span class="hljs-number">8080</span>
</code></pre><p>You should be able to see the Hello World message on the browser.</p>
<h2 id="heading-how-to-define-different-types-of-amenities">How to Define Different Types of Amenities</h2>
<p>We have the <strong>Reservation</strong> class but we have not created a way to specify which type of amenity is getting reserved (the pool, sauna, or gym).</p>
<p>There are multiple ways to do this. One of them would be to create an entity called Amenity to store shared data among entities. Then we'd create <strong>PoolAmenity</strong>, <strong>SaunaAmenity</strong>, and <strong>GymAmenity</strong> classes which would then extend the Amenity class. </p>
<p>This is a nice and extendable solution but it feels a bit like overkill for our simple application, since we do not have much data specific to the amenity type. We are only going to have a capacity for each amenity type.</p>
<p>To keep things simple and not to bother ourselves with table inheritance and other complicated stuff, let's just create an enum to indicate the amenity type as a String and let each reservation have one of these.</p>
<p>Let's switch to the model directory from the controller directory and create the enum for <strong>AmenityType</strong>:</p>
<pre><code>cd ../model
touch AmenityType.java
</code></pre><pre><code>public enum AmenityType {
    POOL(<span class="hljs-string">"POOL"</span>), SAUNA(<span class="hljs-string">"SAUNA"</span>), GYM(<span class="hljs-string">"GYM"</span>);

    private final <span class="hljs-built_in">String</span> name;

    private AmenityType(<span class="hljs-built_in">String</span> value) {
        name = value;
    }

    @Override
    public <span class="hljs-built_in">String</span> toString() {
        <span class="hljs-keyword">return</span> name;
    }
}
</code></pre><p>In this enum, we define a name variable to hold the name of the enum and create a private constructor to only allow a limited set of types. Notice that the type declarations call the constructor from within the class with their name values.</p>
<p>Now we need to modify the Reservation class to hold a reference to <strong>AmenityType</strong>:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Enumerated(EnumType.STRING)</span>
<span class="hljs-meta">@Column(nullable = false)</span>
<span class="hljs-keyword">private</span> AmenityType amenityType;
</code></pre>
<p>We use the <strong>@Enumerated</strong> annotation to describe how we want to store the enum in our database. We'll also make it not nullable because every <strong>Reservation</strong> must have an <strong>AmenityType</strong>.</p>
<h2 id="heading-how-to-show-a-users-reservations">How to Show a User's Reservations</h2>
<p>What is the most crucial feature for our app? Creating reservations and showing a user's reservations. </p>
<p>We do not have a way to authenticate users yet, so we can't really ask the user to login and then show their reservations. But we still want to implement and test the functionality to reserve an amenity and show reservations.</p>
<p>For that purpose, we can ask Spring to put some initial data into our database whenever the application runs. Then we can query that data to test if our queries actually work. We can then proceed to call these services from our <strong>Views</strong> and add authentication to our application in the next sections.</p>
<p>We will use a <strong>CommandLineRunner</strong> bean to run the initial code. Whenever Spring Container finds a bean of type CommandLineRunner it will run the code inside it. Before that step, let's add a few methods to our model classes to make object creation easier and less verbose.</p>
<p>Take a look at the model classes' annotations and you should see annotations like <strong>@Getter</strong> and <strong>@Setter</strong>. These are <strong>Lombok</strong> annotations.</p>
<p>Lombok is an annotation processor we can use to make our coding experience better by letting it generate code for us. When we annotate a class with <strong>@Getter</strong> and <strong>@Setter</strong>, it generates the getters and setters for each field of this class. </p>
<p>Spring uses getter and setter methods for many trivial operations behind the scenes so these are almost always required. And creating them for every entity easily becomes a hassle without the help of Lombok. </p>
<p>Lombok can do more than that though. We will also add the following annotations to our <strong>Reservation</strong> and <strong>User</strong> classes:</p>
<pre><code>@Builder
@NoArgsConstructor
@AllArgsConstructor
</code></pre><p>With these annotations, Lombok implements the builder creational pattern for this class and also creates 2 constructors: One with no arguments (default constructor) and another one with all arguments. I think it is awesome that we can do so much by adding just a few annotations. </p>
<p>We are now ready to add some initial data. Go to your main class (<strong>AmenityReservationSystemApplication.java</strong>) and add this method:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.AmenityType;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.Reservation;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.User;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.ReservationRepository;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.UserRepository;
<span class="hljs-keyword">import</span> org.springframework.boot.CommandLineRunner;
<span class="hljs-keyword">import</span> org.springframework.boot.SpringApplication;
<span class="hljs-keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;

<span class="hljs-keyword">import</span> java.text.DateFormat;
<span class="hljs-keyword">import</span> java.text.SimpleDateFormat;
<span class="hljs-keyword">import</span> java.time.LocalDate;
<span class="hljs-keyword">import</span> java.time.LocalTime;
<span class="hljs-keyword">import</span> java.time.ZoneId;
<span class="hljs-keyword">import</span> java.util.Date;


<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">AmenityReservationSystemApplication</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(AmenityReservationSystemApplication.class, args);
    }

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> CommandLineRunner <span class="hljs-title">loadData</span><span class="hljs-params">(UserRepository userRepository,
                                      ReservationRepository reservationRepository)</span> </span>{
        <span class="hljs-keyword">return</span> (args) -&gt; {
            User user = userRepository.save(<span class="hljs-keyword">new</span> User());
            DateFormat dateFormat = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"dd/MM/yyyy HH:mm:ss"</span>);
            Date date = <span class="hljs-keyword">new</span> Date();
            LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            Reservation reservation = Reservation.builder()
                    .reservationDate(localDate)
                    .startTime(LocalTime.of(<span class="hljs-number">12</span>, <span class="hljs-number">00</span>))
                    .endTime(LocalTime.of(<span class="hljs-number">13</span>, <span class="hljs-number">00</span>))
                    .user(user)
                    .amenityType(AmenityType.POOL)
                    .build();

            reservationRepository.save(reservation);
        };
    }
}
</code></pre>
<p>If you get an error about saving operations such as "Inferred type 'S' for parameter ... does not match", it's because we renamed the domain directory to model. Go to the repository classes and fix the paths of imports to <strong>model.User</strong> and <strong>model.Reservation</strong>.</p>
<p>Notice how we used the <strong>builder pattern</strong> to create the reservation object easily. When the object creation gets complex and a constructor requires so many parameters, it's easy to forget the order of parameters or just mess up the order. </p>
<p>Without the builder pattern, we would either need to call a constructor with so many parameters or call the default constructor and write #properties code to call the setters.</p>
<p>After you are done, run your application again to insert the initial data and connect to <strong>H2 console</strong> as we learned before to confirm that our date is indeed inserted. If you do not have any errors, you should be able to see that the user and the reservation are inserted successfully.</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/04/image-9-1024x325.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We have inserted a reservation to be able to test the functionality to list the reservations but our views currently do not have a way to show the reservations and add reservations. We need to create the UI for that. </p>
<p>We do not have an authentication or sign-up mechanism yet, so act like the user with ID 10001 is logged in. Later we will improve on that by dynamically checking who is logged in and showing a different page if the user is not logged in.</p>
<h3 id="heading-how-to-create-views-with-thymeleaf">How to Create Views with Thymeleaf</h3>
<p>Let's get started by creating a simple home page and a navbar for ourselves. We will use Thymeleaf fragments for the navbar code. </p>
<p>Thymeleaf fragments allow us to create reusable component-like structures similar to React/Vue components if you are familiar with them. Let's create a folder for our fragments under templates and call it fragments.</p>
<pre><code>mkdir fragments
touch nav.html
</code></pre><p>We will put our navbar inside <strong>nav.html</strong> file. Copy and paste the following code:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">"http://www.thymeleaf.org"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">th:fragment</span>=<span class="hljs-string">"nav"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar navbar-expand navbar-dark bg-primary"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-nav w-100"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand text-color"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Amenities Reservation System<span class="hljs-tag">&lt;/<span class="hljs-name">a</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">nav</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>It is not doing much in its current state, but we may add a login button or some links in the future. </p>
<p>Now let's create a simple home page that will serve the users that are not logged in. We will have our navbar fragment on top and have a login button to ask the user to log in before using the app.</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">HTML</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">"http://www.thymeleaf.org"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>/&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Amenities Reservation App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">th:rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css} "</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</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">th:insert</span>=<span class="hljs-string">"fragments/nav :: nav"</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">class</span>=<span class="hljs-string">"text-light"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('https://source.unsplash.com/1920x1080/?nature');
                                   position: absolute;
                                   left: 0;
                                   top: 0;
                                   opacity: 0.6;
                                   z-index: -1;
                                   min-height: 100vh;
                                   min-width: 100vw;"</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">class</span>=<span class="hljs-string">"container"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-top: 20vh; display: flex; flex-direction: column; align-items: center;"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display-3"</span>&gt;</span>Reservation management made easy.<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit.
            Numquam in quia natus magnam ducimus quas molestias velit vero maiores.
            Eaque sunt laudantium voluptas. Fugiat molestiae ipsa delectus iusto vel quod.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/reservations"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-success btn-lg my-2"</span>&gt;</span>Reserve an Amenity<span class="hljs-tag">&lt;/<span class="hljs-name">a</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">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/jquery/3.0.0/jquery.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/popper.js/1.12.9-1/umd/popper.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>It should look like this:</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/05/image-1024x533.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We will create another page to show if the user is already logged in. To keep it simple we will also treat it as a home page, and if the user is logged in, they will be able to see their reservations on the home page. </p>
<p>It is also good in terms of practicality for the user since it decreases the steps they need to take to view their reservations. </p>
<p>We will now create this page as another endpoint. But after adding the login to our application we will show this previous page if the user is not logged in and the next page if they are logged in, dynamically.</p>
<p>Before we start working on our new page, let's add another mapping to <strong>HomeController</strong> that will return our new page. We will later merge these two controllers:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.domain.User;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.service.UserService;
<span class="hljs-keyword">import</span> org.springframework.beans.factory.annotation.Autowired;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Controller;
<span class="hljs-keyword">import</span> org.springframework.ui.Model;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.GetMapping;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.ResponseBody;


<span class="hljs-meta">@Controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeController</span> </span>{

    <span class="hljs-keyword">final</span> UserService userService;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">HomeController</span><span class="hljs-params">(UserService userService)</span> </span>{
        <span class="hljs-keyword">this</span>.userService = userService;
    }

    <span class="hljs-meta">@GetMapping("/")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">index</span><span class="hljs-params">(Model model)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"index"</span>;
    }

    <span class="hljs-meta">@GetMapping("/reservations")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">reservations</span><span class="hljs-params">(Model model)</span> </span>{
        User user = userService.get(<span class="hljs-number">10000L</span>);
        model.addAttribute(<span class="hljs-string">"user"</span>, user);

        <span class="hljs-keyword">return</span> <span class="hljs-string">"reservations"</span>;
    }
}
</code></pre>
<p>If a request is received at "/reservations", this code will call our userService and ask for the user with id 10000L. Then it will add this user to the <strong>Model</strong>. </p>
<p>View will access this model and present the information about this user's reservations. We have also autowired the user service to use it.</p>
<p>Navigate to the templates folder if you are not already there and create another file called "reservations.html":</p>
<pre><code>touch reservations.html
</code></pre><p>Copy and paste the following code:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">HTML</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">"http://www.thymeleaf.org"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>/&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Reservations<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">th:rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css} "</span>/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</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">th:insert</span>=<span class="hljs-string">"fragments/nav :: nav"</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">class</span>=<span class="hljs-string">"container"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-top: 10vh; display: flex; flex-direction: column; align-items: center;"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Welcome <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">" ${user.getFullName()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Amenity<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Date<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Start Time<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>End Time<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">th:each</span>=<span class="hljs-string">"reservation : ${user.getReservations()}"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getAmenityType()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getReservationDate()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getStartTime()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getEndTime()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">table</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">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/jquery/3.0.0/jquery.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/popper.js/1.12.9-1/umd/popper.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>In this <strong>Thymeleaf</strong> template, we import <strong>Bootstrap</strong> and <strong>Thymeleaf</strong> as before and we access the user variable that was added to the model in our controller by using the ${} syntax. </p>
<p>To access data, Thymeleaf uses the getter methods of the object and we can print that information by using the <code>th:text</code> attribute. Thymeleaf also supports loops. In the <code>tbody</code> we have a <code>th:each</code> loop, which we can think of as a foreach loop over a user's reservations. So we loop over the reservations and display them in a table.</p>
<p>You may have an error that says something like "Could not initialize proxy, ... lazy loading". This is caused by the view trying to access the reservations object while it does not yet exist. To get rid of that we can modify the following lines in <strong>User.java</strong>:</p>
<pre><code class="lang-java">    <span class="hljs-meta">@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)</span>
    <span class="hljs-keyword">private</span> Set&lt;Reservation&gt; reservations = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();
</code></pre>
<p>We add a statement to tell Java to fetch this object eagerly.</p>
<p>Now you should be able to view the reservations page:</p>
<p><img src="https://erinc.io/wp-content/uploads/2021/05/image-1-1024x488.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-create-a-reservation">How to Create a Reservation</h3>
<p>We also need a way to create new reservations, so let's build that mechanism for our pre-created user like we did with showing the reservations. Then we can alter it to show the reservations of the currently logged-in user.</p>
<p>Before going forward, we need to update the date formats in our <strong>Reservation.java</strong> file to avoid any format mismatch problems. Make sure your formats for these variables are the same:</p>
<pre><code class="lang-java">    <span class="hljs-meta">@DateTimeFormat(pattern = "yyyy-MM-dd")</span>
    <span class="hljs-meta">@Column(nullable = false)</span>
    <span class="hljs-keyword">private</span> LocalDate reservationDate;

    <span class="hljs-meta">@DateTimeFormat(pattern = "HH:mm")</span>
    <span class="hljs-meta">@Column</span>
    <span class="hljs-keyword">private</span> LocalTime startTime;

    <span class="hljs-meta">@DateTimeFormat(pattern = "HH:mm")</span>
    <span class="hljs-meta">@Column</span>
    <span class="hljs-keyword">private</span> LocalTime endTime;
</code></pre>
<p>In the previous section, we created our <strong>reservations</strong> controller. Now we need to modify it a little bit to add another attribute to the model. </p>
<p>We learned how we can access the objects that are added to the model by using the ${} syntax. Now we are going to do something similar:</p>
<pre><code class="lang-java"><span class="hljs-meta">@GetMapping("/reservations")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">reservations</span><span class="hljs-params">(Model model, HttpSession session)</span> </span>{
        User user = userService.get(<span class="hljs-number">10000L</span>);
        session.setAttribute(<span class="hljs-string">"user"</span>, user);
        Reservation reservation = <span class="hljs-keyword">new</span> Reservation();
        model.addAttribute(<span class="hljs-string">"reservation"</span>, reservation);

        <span class="hljs-keyword">return</span> <span class="hljs-string">"reservations"</span>;
    }
</code></pre>
<p>We are updating our reservations controller to move the user object to the session because we want that to be accessible from another controller method and not only from a template. </p>
<p>Think of it like this: once a user is logged in, this user's account will be responsible for every action that's taken after that point. You can think of Session as a global variable that is accessible from everywhere. </p>
<p>We also create a <strong>Reservation</strong> object and add it to the model. <strong>Thymeleaf</strong> will access this newly created object in our view template using this model and it will call the setters to set its fields.</p>
<p>Now let's create the view for creating the reservation. We are going to use <a target="_blank" href="https://getbootstrap.com/docs/4.0/components/modal/">Bootstrap Modal</a> to display a form modal after a button is clicked.</p>
<p>We can first handle the code to call the modal we are going to create in the next step, move to the reservations.html file, and add this snippet after the table tag we added before:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>
  <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>
  <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span>
  <span class="hljs-attr">data-toggle</span>=<span class="hljs-string">"modal"</span>
  <span class="hljs-attr">data-target</span>=<span class="hljs-string">"#createReservationModal"</span>
&gt;</span>
  Create Reservation
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

<span class="hljs-comment">&lt;!-- Modal --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span>
  <span class="hljs-attr">th:insert</span>=<span class="hljs-string">"fragments/modal :: modal"</span>
  <span class="hljs-attr">th:with</span>=<span class="hljs-string">"reservation=${reservation}"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>This button will trigger our modal. In the div, we insert this modal that we are going to create and we use the <code>th:with</code> tag to pass the reservation object that was put in the model in our controller. If we do not do this, the fragment will not know about the reservation object.</p>
<p>We also need to change how we access the user to print their name because we no longer store it in the modal but in session:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Welcome <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">" ${session.user.getFullName()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
</code></pre>
<p>So your final <strong>reservations.html</strong> file should be looking like this:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">"http://www.thymeleaf.org"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Reservations<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span>
      <span class="hljs-attr">th:rel</span>=<span class="hljs-string">"stylesheet"</span>
      <span class="hljs-attr">th:href</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css} "</span>
    /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</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">th:insert</span>=<span class="hljs-string">"fragments/nav :: nav"</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">class</span>=<span class="hljs-string">"container"</span>
        <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-top: 10vh; display: flex; flex-direction: column; align-items: center;"</span>
      &gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Welcome <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">" ${session.user.getFullName()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Amenity<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Date<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>Start Time<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"col"</span>&gt;</span>End Time<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">th:each</span>=<span class="hljs-string">"reservation : ${session.user.getReservations()}"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getAmenityType()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getReservationDate()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getStartTime()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string">"${reservation.getEndTime()}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
          <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>
          <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span>
          <span class="hljs-attr">data-toggle</span>=<span class="hljs-string">"modal"</span>
          <span class="hljs-attr">data-target</span>=<span class="hljs-string">"#createReservationModal"</span>
        &gt;</span>
          Create Reservation
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

        <span class="hljs-comment">&lt;!-- Modal --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
          <span class="hljs-attr">th:insert</span>=<span class="hljs-string">"fragments/modal :: modal"</span>
          <span class="hljs-attr">th:with</span>=<span class="hljs-string">"reservation=${reservation}"</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">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/jquery/3.0.0/jquery.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/popper.js/1.12.9-1/umd/popper.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">th:src</span>=<span class="hljs-string">"@{/webjars/bootstrap/4.0.0-2/js/bootstrap.min.js}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>We are now ready to create the modal fragment. We can create a fragment for the modal just like we did with the nav:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">pwd</span>
/src/main/resources
<span class="hljs-built_in">cd</span> templates/fragments
touch modal.html
</code></pre>
<p>And paste in the following template code:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">"http://www.thymeleaf.org"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"modal fade"</span>
      <span class="hljs-attr">th:fragment</span>=<span class="hljs-string">"modal"</span>
      <span class="hljs-attr">id</span>=<span class="hljs-string">"createReservationModal"</span>
      <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"-1"</span>
      <span class="hljs-attr">role</span>=<span class="hljs-string">"dialog"</span>
      <span class="hljs-attr">aria-labelledby</span>=<span class="hljs-string">"createReservationModalTitle"</span>
      <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal-dialog"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"document"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal-content"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal-header"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h5</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal-title"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"createReservationModalTitle"</span>&gt;</span>
              Create Reservation
            <span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
              <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>
              <span class="hljs-attr">class</span>=<span class="hljs-string">"close"</span>
              <span class="hljs-attr">data-dismiss</span>=<span class="hljs-string">"modal"</span>
              <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Close"</span>
            &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-symbol">&amp;times;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</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> <span class="hljs-attr">class</span>=<span class="hljs-string">"modal-body"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">form</span>
              <span class="hljs-attr">action</span>=<span class="hljs-string">"#"</span>
              <span class="hljs-attr">th:action</span>=<span class="hljs-string">"@{/reservations-submit}"</span>
              <span class="hljs-attr">th:object</span>=<span class="hljs-string">"${reservation}"</span>
              <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>
            &gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group row"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"type-select"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-2 col-form-label"</span>
                  &gt;</span>Amenity<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>
                &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-10"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">select</span>
                    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
                    <span class="hljs-attr">id</span>=<span class="hljs-string">"type-select"</span>
                    <span class="hljs-attr">th:field</span>=<span class="hljs-string">"*{amenityType}"</span>
                  &gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"POOL"</span>&gt;</span>POOL<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"SAUNA"</span>&gt;</span>SAUNA<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"GYM"</span>&gt;</span>GYM<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">select</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">class</span>=<span class="hljs-string">"form-group row"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"start-date"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-2 col-form-label"</span>
                  &gt;</span>Date<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>
                &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-10"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
                    <span class="hljs-attr">type</span>=<span class="hljs-string">"date"</span>
                    <span class="hljs-attr">id</span>=<span class="hljs-string">"start-date"</span>
                    <span class="hljs-attr">name</span>=<span class="hljs-string">"trip-start"</span>
                    <span class="hljs-attr">th:field</span>=<span class="hljs-string">"*{reservationDate}"</span>
                    <span class="hljs-attr">value</span>=<span class="hljs-string">"2018-07-22"</span>
                    <span class="hljs-attr">min</span>=<span class="hljs-string">"2021-05-01"</span>
                    <span class="hljs-attr">max</span>=<span class="hljs-string">"2021-12-31"</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">class</span>=<span class="hljs-string">"form-group row"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"start-time"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-2 col-form-label"</span>
                  &gt;</span>From<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>
                &gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-10"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
                    <span class="hljs-attr">type</span>=<span class="hljs-string">"time"</span>
                    <span class="hljs-attr">id</span>=<span class="hljs-string">"start-time"</span>
                    <span class="hljs-attr">name</span>=<span class="hljs-string">"time"</span>
                    <span class="hljs-attr">th:field</span>=<span class="hljs-string">"*{startTime}"</span>
                    <span class="hljs-attr">min</span>=<span class="hljs-string">"08:00"</span>
                    <span class="hljs-attr">max</span>=<span class="hljs-string">"19:30"</span>
                    <span class="hljs-attr">required</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">class</span>=<span class="hljs-string">"form-group row"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"end-time"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-2 col-form-label"</span>&gt;</span>To<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-10"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">input</span>
                    <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>
                    <span class="hljs-attr">type</span>=<span class="hljs-string">"time"</span>
                    <span class="hljs-attr">id</span>=<span class="hljs-string">"end-time"</span>
                    <span class="hljs-attr">name</span>=<span class="hljs-string">"time"</span>
                    <span class="hljs-attr">th:field</span>=<span class="hljs-string">"*{endTime}"</span>
                    <span class="hljs-attr">min</span>=<span class="hljs-string">"08:30"</span>
                    <span class="hljs-attr">max</span>=<span class="hljs-string">"20:00"</span>
                    <span class="hljs-attr">required</span>
                  /&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">small</span>&gt;</span>Amenities are available from 8 am to 8 pm<span class="hljs-tag">&lt;/<span class="hljs-name">small</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">class</span>=<span class="hljs-string">"modal-footer"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                  <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span>
                  <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-secondary"</span>
                  <span class="hljs-attr">data-dismiss</span>=<span class="hljs-string">"modal"</span>
                &gt;</span>
                  Close
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Submit"</span>&gt;</span>
                  Save changes
                <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">form</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>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>There are a few important points that you need to take note of here.</p>
<p>Notice how we access the reservation object in the form tag:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">form</span>
  <span class="hljs-attr">action</span>=<span class="hljs-string">"#"</span>
  <span class="hljs-attr">th:action</span>=<span class="hljs-string">"@{/reservations-submit}"</span>
  <span class="hljs-attr">th:object</span>=<span class="hljs-string">"${reservation}"</span>
  <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>
&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
</code></pre>
<p>The <strong><code>th:object</code></strong> tag associates this form with the reservation object that we have created before. <strong><code>th:action</code></strong> determines where this object will be sent when the form is submitted, and our submission method will be <strong>POST</strong>. We will create this controller with the mapping to <strong>/reservations-submit</strong> after this step.</p>
<p>We use the <strong><code>th:field</code></strong> tag to bind the inputs to our reservation object's fields. Thymeleaf calls the setters of the reservation object whenever that input field's value changes.</p>
<p>Now let's create the controller that will receive this form. Go to <strong>HomeController</strong> and add the following method:</p>
<pre><code class="lang-java"><span class="hljs-meta">@PostMapping("/reservations-submit")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">reservationsSubmit</span><span class="hljs-params">(<span class="hljs-meta">@ModelAttribute</span> Reservation reservation,
                                     <span class="hljs-meta">@SessionAttribute("user")</span> User user)</span> </span>{

        <span class="hljs-comment">// Save to DB after updating</span>
        <span class="hljs-keyword">assert</span> user != <span class="hljs-keyword">null</span>;
        reservation.setUser(user);
        reservationService.create(reservation);
        Set&lt;Reservation&gt; userReservations = user.getReservations();
        userReservations.add(reservation);
        user.setReservations(userReservations);
        userService.update(user.getId(), user);
        <span class="hljs-keyword">return</span> <span class="hljs-string">"redirect:/reservations"</span>;
    }
</code></pre>
<p>And also add the <strong>ReservationService</strong> to our dependencies:</p>
<pre><code class="lang-java">    <span class="hljs-keyword">final</span> UserService userService;
    <span class="hljs-keyword">final</span> ReservationService reservationService;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">HomeController</span><span class="hljs-params">(UserService userService, ReservationService reservationService)</span> </span>{
        <span class="hljs-keyword">this</span>.userService = userService;
        <span class="hljs-keyword">this</span>.reservationService = reservationService;
    }
</code></pre>
<p>After our modal fragment posts the reservation object to this controller, that object will be bound with the <strong>@ModelAttribute</strong> annotation. We also need the user so we use <strong>@SessionAttribute</strong> to get a reference to it.</p>
<p>The fields of the reservation object should be all set by the form. Now we just need to save it to the database. </p>
<p>We do that by calling the <strong>create</strong> method. Then we add the new Reservation to the user's list of reservations and update the user to reflect these changes. We then redirect the user to the reservations page to show the updated reservations list.</p>
<p>Your reservations page should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/LFJE0Ad---Imgur.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And when you click the button, the create reservation modal should pop up.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/image-42.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-add-authentication-and-authorization-to-the-app">How to Add Authentication and Authorization to the App</h2>
<p>We will use <strong>Spring Security</strong> to add authentication and authorization to our application. We want to make sure that nobody can see each other's reservations and that the users must be logged in to create reservations. </p>
<p>If you want to learn more about it, I wrote an article that provides an overview of <a target="_blank" href="https://auth0.com/blog/spring-security-overview/">Spring Security</a>. </p>
<p>We will keep it simple and mostly use the defaults because this is a difficult topic on its own. If you want to learn how to properly set up Spring Security Auth, you can check out my <a target="_blank" href="https://www.freecodecamp.org/news/how-to-setup-jwt-authorization-and-authentication-in-spring/">article</a> on that. </p>
<p>We need to add "Spring Security" and "Thymeleaf Spring Security" to our dependencies, so open your pom.xml and add the following to your list of dependencies:</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-security<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>

<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.thymeleaf.extras<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>thymeleaf-extras-springsecurity5<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.0.4.RELEASE<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>
</code></pre>
<p>Now, by default, Spring Security makes all the endpoints protected, so we need to configure it to allow viewing the home page. </p>
<p>Let's create a config folder to contain our <strong>WebSecurityConfig</strong> file. Assuming you are on the root folder:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> /src/main/java/com/amenity_reservation_system
mkdir config &amp;&amp; <span class="hljs-built_in">cd</span> config
touch WebSecurityConfig.java
</code></pre>
<p>This should be the content of your config file:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.config;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.service.UserDetailsServiceImpl;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Configuration;
<span class="hljs-keyword">import</span> org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
<span class="hljs-keyword">import</span> org.springframework.security.config.annotation.web.builders.HttpSecurity;
<span class="hljs-keyword">import</span> org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
<span class="hljs-keyword">import</span> org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
<span class="hljs-keyword">import</span> org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

<span class="hljs-meta">@Configuration</span>
<span class="hljs-meta">@EnableWebSecurity</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WebSecurityConfig</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">WebSecurityConfigurerAdapter</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> UserDetailsServiceImpl userDetailsService;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> BCryptPasswordEncoder bCryptPasswordEncoder;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">WebSecurityConfig</span><span class="hljs-params">(UserDetailsServiceImpl userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder)</span> </span>{
        <span class="hljs-keyword">this</span>.userDetailsService = userDetailsService;
        <span class="hljs-keyword">this</span>.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configure</span><span class="hljs-params">(HttpSecurity http)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        http
                .authorizeRequests()
                .antMatchers(<span class="hljs-string">"/"</span>, <span class="hljs-string">"/webjars/**"</span>).permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .logoutSuccessUrl(<span class="hljs-string">"/"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">configure</span><span class="hljs-params">(AuthenticationManagerBuilder auth)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
    }

}
</code></pre>
<p>I will not go into the details, but here's a summary of what happened here: </p>
<ul>
<li>we configured Spring Security to permit all requests made to the home page ("/")</li>
<li>we configured our styles ("/webjars/**")</li>
<li>we asked it to provide us with login and logout forms </li>
<li>and we asked it to permit the requests to them as well and redirect to the home page after logout is successful</li>
</ul>
<p>Isn't it amazing what you can achieve with just a few statements?</p>
<p>We also configured our <strong>AuthenticationManagerBuilder</strong> to use bCryptPasswordEncoder and userDetailsService. But wait, we don't have neither of them yet, and your IDE may already be complaining about that. So let's create them.</p>
<p>Before we go on, it may be a good idea to add <strong>username</strong> and passwordHash fields to our <strong>User</strong> class. We'll use them to authenticate the user instead of using their full name. Then we'll add it to the constructor.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.model;

<span class="hljs-keyword">import</span> java.time.OffsetDateTime;
<span class="hljs-keyword">import</span> java.util.HashSet;
<span class="hljs-keyword">import</span> java.util.Set;
<span class="hljs-keyword">import</span> javax.persistence.*;

<span class="hljs-keyword">import</span> lombok.AllArgsConstructor;
<span class="hljs-keyword">import</span> lombok.Getter;
<span class="hljs-keyword">import</span> lombok.NoArgsConstructor;
<span class="hljs-keyword">import</span> lombok.Setter;


<span class="hljs-meta">@Entity</span>
<span class="hljs-meta">@Getter</span>
<span class="hljs-meta">@Setter</span>
<span class="hljs-meta">@AllArgsConstructor</span>
<span class="hljs-meta">@NoArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{

    <span class="hljs-meta">@Id</span>
    <span class="hljs-meta">@Column(nullable = false, updatable = false)</span>
    <span class="hljs-meta">@SequenceGenerator(
            name = "primary_sequence",
            sequenceName = "primary_sequence",
            allocationSize = 1,
            initialValue = 10000
    )</span>
    <span class="hljs-meta">@GeneratedValue(
            strategy = GenerationType.SEQUENCE,
            generator = "primary_sequence"
    )</span>
    <span class="hljs-keyword">private</span> Long id;

    <span class="hljs-meta">@Column(nullable = false, unique = true)</span>
    <span class="hljs-keyword">private</span> String fullName;

    <span class="hljs-meta">@Column(nullable = false, unique = true)</span>
    <span class="hljs-keyword">private</span> String username;

    <span class="hljs-meta">@Column</span>
    <span class="hljs-keyword">private</span> String passwordHash;

    <span class="hljs-meta">@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)</span>
    <span class="hljs-keyword">private</span> Set&lt;Reservation&gt; reservations = <span class="hljs-keyword">new</span> HashSet&lt;&gt;();

    <span class="hljs-meta">@Column(nullable = false, updatable = false)</span>
    <span class="hljs-keyword">private</span> OffsetDateTime dateCreated;

    <span class="hljs-meta">@Column(nullable = false)</span>
    <span class="hljs-keyword">private</span> OffsetDateTime lastUpdated;

    <span class="hljs-meta">@PrePersist</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">prePersist</span><span class="hljs-params">()</span> </span>{
        dateCreated = OffsetDateTime.now();
        lastUpdated = dateCreated;
    }

    <span class="hljs-meta">@PreUpdate</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">preUpdate</span><span class="hljs-params">()</span> </span>{
        lastUpdated = OffsetDateTime.now();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">(String fullName, String username, String passwordHash)</span> </span>{
        <span class="hljs-keyword">this</span>.fullName = fullName;
        <span class="hljs-keyword">this</span>.username = username;
        <span class="hljs-keyword">this</span>.passwordHash = passwordHash;
    }
}
</code></pre>
<p>Create a file called <strong>UserDetailsServiceImpl</strong> under the services folder:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> service
touch UserDetailsServiceImpl.java
</code></pre>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.service;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.User;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.UserRepository;
<span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetails;
<span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UserDetailsService;
<span class="hljs-keyword">import</span> org.springframework.security.core.userdetails.UsernameNotFoundException;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Service;

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

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

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserDetailsServiceImpl</span><span class="hljs-params">(UserRepository userRepository)</span> </span>{
        <span class="hljs-keyword">this</span>.userRepository = userRepository;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> UserDetails <span class="hljs-title">loadUserByUsername</span><span class="hljs-params">(String username)</span> <span class="hljs-keyword">throws</span> UsernameNotFoundException </span>{
        <span class="hljs-keyword">final</span> User user = userRepository.findUserByUsername(username);

        <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> UsernameNotFoundException(username);
        }

        UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(
                user.getUsername()).password(user.getPwHash()).roles(<span class="hljs-string">"USER"</span>).build();

        <span class="hljs-keyword">return</span> userDetails;
    }
}
</code></pre>
<p>This basically tells Spring Security that we want to use the <strong>User</strong> entity we created earlier by getting the <strong>User</strong> object from our database and using the JPA method on our repository. But again, we do not have the <strong>findUserByUsername</strong> method on our <strong>UserRepository</strong>. You can try fixing this on your own as a challenge, it is really simple.</p>
<p>Remember, we do not need to write queries. It is sufficient to provide the signature and let JPA do the work.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.repos;

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


<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">UserRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">User</span>, <span class="hljs-title">Long</span>&gt; </span>{

    <span class="hljs-function">User <span class="hljs-title">findUserByUsername</span><span class="hljs-params">(String username)</span></span>;
}
</code></pre>
<p>We also need a <strong>BCryptPasswordEncoder</strong> bean to satisfy that dependency in <strong>WebSecurityConfig</strong> and to make it work. Let's modify our main class to add a bean and change the constructor parameters to give our predefined <strong>User</strong> a username.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.AmenityType;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.Reservation;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.User;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.ReservationRepository;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.UserRepository;
<span class="hljs-keyword">import</span> org.springframework.boot.CommandLineRunner;
<span class="hljs-keyword">import</span> org.springframework.boot.SpringApplication;
<span class="hljs-keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;
<span class="hljs-keyword">import</span> org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

<span class="hljs-keyword">import</span> java.text.DateFormat;
<span class="hljs-keyword">import</span> java.text.SimpleDateFormat;
<span class="hljs-keyword">import</span> java.time.LocalDate;
<span class="hljs-keyword">import</span> java.time.LocalTime;
<span class="hljs-keyword">import</span> java.time.ZoneId;
<span class="hljs-keyword">import</span> java.util.Date;


<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">AmenityReservationSystemApplication</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(AmenityReservationSystemApplication.class, args);
    }


    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> CommandLineRunner <span class="hljs-title">loadData</span><span class="hljs-params">(UserRepository userRepository,
                                      ReservationRepository reservationRepository)</span> </span>{
    <span class="hljs-keyword">return</span> (args) -&gt; {
      User user =
          userRepository.save(
              <span class="hljs-keyword">new</span> User(<span class="hljs-string">"Yigit Kemal Erinc"</span>,
                      <span class="hljs-string">"yigiterinc"</span>,
                      bCryptPasswordEncoder().encode(<span class="hljs-string">"12345"</span>)));
      DateFormat dateFormat = <span class="hljs-keyword">new</span> SimpleDateFormat(<span class="hljs-string">"dd/MM/yyyy HH:mm:ss"</span>);
      Date date = <span class="hljs-keyword">new</span> Date();
      LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
      Reservation reservation =
          Reservation.builder()
              .reservationDate(localDate)
              .startTime(LocalTime.of(<span class="hljs-number">12</span>, <span class="hljs-number">00</span>))
              .endTime(LocalTime.of(<span class="hljs-number">13</span>, <span class="hljs-number">00</span>))
              .user(user)
              .amenityType(AmenityType.POOL)
              .build();

      reservationRepository.save(reservation);
    };
    }

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> BCryptPasswordEncoder <span class="hljs-title">bCryptPasswordEncoder</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> BCryptPasswordEncoder();
    }
}
</code></pre>
<p>Your application should be ready to compile now and it should already be redirecting you to the login page if you send a request to "/reservations". </p>
<p>It would be nice to have buttons for log-in and log-out on the navbar, and we want to show login if user is not authenticated and logout otherwise. We can do it this way in <strong>nav.html</strong>:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span> <span class="hljs-attr">xmlns:th</span>=<span class="hljs-string">"http://www.thymeleaf.org"</span> <span class="hljs-attr">xmlns:sec</span>=<span class="hljs-string">"http://www.w3.org/1999/xhtml"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">th:fragment</span>=<span class="hljs-string">"nav"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar navbar-expand navbar-dark bg-primary"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-nav w-100"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand text-color"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Amenities Reservation System<span class="hljs-tag">&lt;/<span class="hljs-name">a</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">a</span> <span class="hljs-attr">sec:authorize</span>=<span class="hljs-string">"isAnonymous()"</span>
           <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand text-color"</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">"@{/login}"</span>&gt;</span>Log in<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">sec:authorize</span>=<span class="hljs-string">"isAuthenticated()"</span>
               <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand text-color"</span> <span class="hljs-attr">th:href</span>=<span class="hljs-string">"@{/logout}"</span>&gt;</span>Log out<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The log in link should now be visible on the navbar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-10-at-02.19.09.png" alt="Image" width="600" height="400" loading="lazy">
<em>Home page when you are not logged in</em></p>
<h2 id="heading-how-to-show-a-logged-in-users-reservations">How to Show a Logged-in User's Reservations</h2>
<p>Our Reservations page is currently displaying the reservations of one hard-coded user and not the reservations of the logged-in user. </p>
<pre><code class="lang-java">    <span class="hljs-meta">@GetMapping("/reservations")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">reservations</span><span class="hljs-params">(Model model, HttpSession session)</span> </span>{
        User user = userService.get(<span class="hljs-number">10000L</span>);
        session.setAttribute(<span class="hljs-string">"user"</span>, user);
        Reservation reservation = <span class="hljs-keyword">new</span> Reservation();
        model.addAttribute(<span class="hljs-string">"reservation"</span>, reservation);

        <span class="hljs-keyword">return</span> <span class="hljs-string">"reservations"</span>;
    }
</code></pre>
<p>We need to show the reservations of the currently logged-in user. To achieve that, we should use some Spring Security.</p>
<p>Go to the <strong>HomeController</strong> (I know, that name is a bit problematic right now) class and change it with the following code:</p>
<pre><code class="lang-java"><span class="hljs-meta">@GetMapping("/reservations")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">reservations</span><span class="hljs-params">(Model model, HttpSession session)</span> </span>{
        UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String name = principal.getUsername();
        User user = userService.getUserByUsername(name);

        <span class="hljs-comment">// This should always be the case </span>
        <span class="hljs-keyword">if</span> (user != <span class="hljs-keyword">null</span>) {
            session.setAttribute(<span class="hljs-string">"user"</span>, user);

            <span class="hljs-comment">// Empty reservation object in case the user creates a new reservation</span>
            Reservation reservation = <span class="hljs-keyword">new</span> Reservation();
            model.addAttribute(<span class="hljs-string">"reservation"</span>, reservation);

            <span class="hljs-keyword">return</span> <span class="hljs-string">"reservations"</span>;
        }

        <span class="hljs-keyword">return</span> <span class="hljs-string">"index"</span>;    
        }
</code></pre>
<p>Since we have added Spring Security to the project, it automatically creates the <strong>Authentication</strong> object behind the scenes – we are getting that from <strong>SecurityContextHolder</strong>. </p>
<p>We are grabbing the <strong><a target="_blank" href="https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/userdetails/UserDetails.html#:~:text=Interface%20UserDetails&amp;text=Provides%20core%20user%20information.,later%20encapsulated%20into%20Authentication%20objects.">UserDetails</a></strong> object which stores the info related to user. Then we check if the user object is null. This should always be the case since <em>reservations</em> is a protected endpoint and the user must be logged in to see that page – but it is always good to make sure everything is as expected.</p>
<p>Then we call the <strong>UserService</strong> class to get the <strong>User</strong> object which has this username – but we have not added the <strong>getUserByUsername</strong> method yet. So let's move to the <strong>UserService</strong> and add this simple method.</p>
<pre><code class="lang-java">    <span class="hljs-function"><span class="hljs-keyword">public</span> User <span class="hljs-title">getUserByUsername</span><span class="hljs-params">(String username)</span> </span>{
        <span class="hljs-keyword">return</span> userRepository.findUserByUsername(username);
    }
</code></pre>
<p>Now you should be able to see the logged-in user's reservations. You can try that by adding another user and creating reservations for that user as well. </p>
<h3 id="heading-how-to-check-the-capacity">How to Check the Capacity</h3>
<p>We currently don't have a mechanism to store the Capacity of each amenity type. We need to store those somehow and also check that there is enough capacity before we approve a reservation. </p>
<p>For that purpose, let's create a class called <strong>Capacity</strong> under our model folder.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.model;

<span class="hljs-keyword">import</span> lombok.AllArgsConstructor;
<span class="hljs-keyword">import</span> lombok.Getter;
<span class="hljs-keyword">import</span> lombok.NoArgsConstructor;
<span class="hljs-keyword">import</span> lombok.Setter;

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

<span class="hljs-meta">@Entity</span>
<span class="hljs-meta">@Getter</span>
<span class="hljs-meta">@Setter</span>
<span class="hljs-meta">@AllArgsConstructor</span>
<span class="hljs-meta">@NoArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Capacity</span> </span>{

    <span class="hljs-meta">@Id</span>
    <span class="hljs-meta">@Column(nullable = false, updatable = false)</span>
    <span class="hljs-meta">@SequenceGenerator(
            name = "primary_sequence",
            sequenceName = "primary_sequence",
            allocationSize = 1,
            initialValue = 10000
    )</span>
    <span class="hljs-meta">@GeneratedValue(
            strategy = GenerationType.SEQUENCE,
            generator = "primary_sequence"
    )</span>
    <span class="hljs-keyword">private</span> Long id;

    <span class="hljs-meta">@Column(nullable = false, unique = true)</span>
    <span class="hljs-meta">@Enumerated(EnumType.STRING)</span>
    <span class="hljs-keyword">private</span> AmenityType amenityType;

    <span class="hljs-meta">@Column(nullable = false)</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> capacity;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Capacity</span><span class="hljs-params">(AmenityType amenityType, <span class="hljs-keyword">int</span> capacity)</span> </span>{
        <span class="hljs-keyword">this</span>.amenityType = amenityType;
        <span class="hljs-keyword">this</span>.capacity = capacity;
    }
}
</code></pre>
<p>This is the entity that will represent our logical construct to be stored in our database. It is basically a map entry with an AmenityType and its corresponding capacity.</p>
<p>We also need a repository to store the <strong>Capacity</strong> entries, so let's create the CapacityRepository under the <strong>repos</strong> folder.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.repos;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.Capacity;
<span class="hljs-keyword">import</span> org.springframework.data.jpa.repository.JpaRepository;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">CapacityRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">Capacity</span>, <span class="hljs-title">Long</span>&gt; </span>{
}
</code></pre>
<p>We need to populate this new table with the initial capacities. We could read the initial capacities from a config file or something, but let's keep it simple and hardcode it using loadData in our main method.</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system;

<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.AmenityType;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.Capacity;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.Reservation;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.model.User;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.CapacityRepository;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.ReservationRepository;
<span class="hljs-keyword">import</span> com.amenity_reservation_system.repos.UserRepository;
<span class="hljs-keyword">import</span> org.springframework.boot.CommandLineRunner;
<span class="hljs-keyword">import</span> org.springframework.boot.SpringApplication;
<span class="hljs-keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;
<span class="hljs-keyword">import</span> org.springframework.context.annotation.Bean;
<span class="hljs-keyword">import</span> org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

<span class="hljs-keyword">import</span> java.text.DateFormat;
<span class="hljs-keyword">import</span> java.text.SimpleDateFormat;
<span class="hljs-keyword">import</span> java.time.LocalDate;
<span class="hljs-keyword">import</span> java.time.LocalTime;
<span class="hljs-keyword">import</span> java.time.ZoneId;
<span class="hljs-keyword">import</span> java.util.Date;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Map;

<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">AmenityReservationSystemApplication</span> </span>{

  <span class="hljs-keyword">private</span> Map&lt;AmenityType, Integer&gt; initialCapacities =
      <span class="hljs-keyword">new</span> HashMap&lt;&gt;() {
        {
          put(AmenityType.GYM, <span class="hljs-number">20</span>);
          put(AmenityType.POOL, <span class="hljs-number">4</span>);
          put(AmenityType.SAUNA, <span class="hljs-number">1</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(AmenityReservationSystemApplication.class, args);
  }

  <span class="hljs-meta">@Bean</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> CommandLineRunner <span class="hljs-title">loadData</span><span class="hljs-params">(
      UserRepository userRepository,
      CapacityRepository capacityRepository)</span> </span>{
    <span class="hljs-keyword">return</span> (args) -&gt; {
      userRepository.save(
          <span class="hljs-keyword">new</span> User(<span class="hljs-string">"Yigit Kemal Erinc"</span>, <span class="hljs-string">"yigiterinc"</span>, bCryptPasswordEncoder().encode(<span class="hljs-string">"12345"</span>)));

      <span class="hljs-keyword">for</span> (AmenityType amenityType : initialCapacities.keySet()) {
        capacityRepository.save(<span class="hljs-keyword">new</span> Capacity(amenityType, initialCapacities.get(amenityType)));
      }
    };
  }

  <span class="hljs-meta">@Bean</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> BCryptPasswordEncoder <span class="hljs-title">bCryptPasswordEncoder</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> BCryptPasswordEncoder();
  }
}
</code></pre>
<p>I just added the capacities inside the <strong>initialCapacities</strong> map then saved those to the <strong>CapacityRepository</strong> inside the <strong>loadData</strong> method.</p>
<p>We can now check if the number of reservations in the requested time exceeds the capacity and reject the reservation request if it does.</p>
<p>So here is the logic: We need to fetch the number of reservations that are on the same day and overlap with this current request. Then we need to fetch the capacity for this amenity type, and if the capacity is exceeded we can throw an exception. </p>
<p>Therefore we need a query to get the number of potentially overlapping reservations. It is not the easiest query to write, but JPA is very convenient and we can access that query inside our <strong>ReservationRepository</strong> without needing to write any SQL or HQL (Hibernate Query Language). </p>
<p>I encourage you to try it yourself before moving forward, because this is like the sole reason why I have included this concept of capacity in this tutorial (to show an example of a more advanced JPA query).</p>
<p>So this is how the <strong>ReservationService</strong>'s create method looks. You need to replace the 0 with a call to reservationRepository to get the number of overlapping reservations. </p>
<p>If the current number of overlapping reservations is equal to the capacity, it means that the next one will exceed it so we throw the exception.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> Long <span class="hljs-title">create</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Reservation reservation)</span> </span>{
        <span class="hljs-keyword">int</span> capacity = capacityRepository.findByAmenityType(reservation.getAmenityType()).getCapacity();
        <span class="hljs-keyword">int</span> overlappingReservations = <span class="hljs-number">0</span>; <span class="hljs-comment">// TODO</span>

        <span class="hljs-keyword">if</span> (overlappingReservations &gt;= capacity) {
            <span class="hljs-comment">// Throw a custom exception</span>
        }

        <span class="hljs-keyword">return</span> reservationRepository.save(reservation).getId();
    }
</code></pre>
<p>To find the overlapping reservations there are a few conditions we need to check:</p>
<p>First of all, the reservation date should be the same as the date in the request.</p>
<ol>
<li>Start time can be before the startTime of a new request. In that case, the end time should be later than our request, in order to overlap. (startTimeBeforeAndEndTimeAfter)</li>
<li>Or, endTime can be after but the startTime can actually be between the startTime and endTime of the request. (endTimeAfterOrStartTimeBetween)</li>
</ol>
<p>So our final query should return all reservations which match any of these 2 possibilities.</p>
<p>We can express it like this: </p>
<pre><code class="lang-java"><span class="hljs-function">List&lt;Reservation&gt; <span class="hljs-title">findReservationsByReservationDateAndStartTimeBeforeAndEndTimeAfterOrStartTimeBetween</span>
            <span class="hljs-params">(LocalDate reservationDate, LocalTime startTime, LocalTime endTime, LocalTime betweenStart, LocalTime betweenEnd)</span></span>;
</code></pre>
<p>And the final create method looks like this:</p>
<pre><code class="lang-java"> <span class="hljs-function"><span class="hljs-keyword">public</span> Long <span class="hljs-title">create</span><span class="hljs-params">(<span class="hljs-keyword">final</span> Reservation reservation)</span> </span>{
        <span class="hljs-keyword">int</span> capacity = capacityRepository.findByAmenityType(reservation.getAmenityType()).getCapacity();
        <span class="hljs-keyword">int</span> overlappingReservations = reservationRepository
                .findReservationsByReservationDateAndStartTimeBeforeAndEndTimeAfterOrStartTimeBetween(
                        reservation.getReservationDate(),
                        reservation.getStartTime(), reservation.getEndTime(),
                        reservation.getStartTime(), reservation.getEndTime()).size();

        <span class="hljs-keyword">if</span> (overlappingReservations &gt;= capacity) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> CapacityFullException(<span class="hljs-string">"This amenity's capacity is full at desired time"</span>);
        }

        <span class="hljs-keyword">return</span> reservationRepository.save(reservation).getId();
    }
</code></pre>
<p>You don't need to worry about the custom exception, but if you are interested in that, here is the code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">package</span> com.amenity_reservation_system.exception;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CapacityFullException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">RuntimeException</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CapacityFullException</span><span class="hljs-params">(String message)</span> </span>{
        <span class="hljs-keyword">super</span>(message);
    }
}
</code></pre>
<p>We should normally show an error modal if the capacity is exceeded but I will skip that to avoid repetitive UI stuff. You can try that as a challenge if you wish.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, we have learned about so many technologies that make development with Spring Boot easier and faster. </p>
<p>I believe many people underestimate the framework in terms of development speed and the quality of the resulting work. </p>
<p>Assuming you are fluent with the technology, I would argue that Spring Boot is not any slower (in development) than any other backend framework if you do everything in the modern fashion. </p>
<p>You can find the whole code in this repository:</p>
<p><a target="_blank" href="https://github.com/yigiterinc/amenity-reservation-system.git">https://github.com/yigiterinc/amenity-reservation-system.git</a></p>
<p>If you are interested in reading more content like this, feel free to subscribe to my blog at <a target="_blank" href="https://erinc.io/">https://erinc.io</a> to get notified about my new posts.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Generate an Excel Report in a Spring Boot REST API with Apache POI and Kotlin ]]>
                </title>
                <description>
                    <![CDATA[ By Piotr Wolak In this article, I would like to show you how to generate Excel reports in the .xls and .xlsx formats (also known as Open XML) in a Spring Boot REST API with Apache POI and Kotlin. After finishing this guide, you will have a fundamenta... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/generate-excel-report-in-spring-rest-api/</link>
                <guid isPermaLink="false">66d46089677cb8c6c15f3167</guid>
                
                    <category>
                        <![CDATA[ excel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 08 Dec 2020 01:54:41 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/12/share-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Piotr Wolak</p>
<p>In this article, I would like to show you how to generate Excel reports in the <strong>.xls</strong> and <strong>.xlsx</strong> formats (also known as Open XML) in a <strong>Spring Boot REST API</strong> with <strong>Apache POI and Kotlin</strong>.</p>
<p>After finishing this guide, you will have a fundamental understanding of how to create custom cells formats, styles, and fonts. In the end, I will show you how to create Spring Boot REST endpoints so you can easily download generated files.</p>
<p>To better visualize what we'll learn, check out the preview of the resulting file:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/result_file_preview.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-step-1-add-the-necessary-imports">Step 1: Add the Necessary Imports</h2>
<p>As the first step, let's create a Spring Boot project (I highly recommend using the <a target="_blank" href="https://start.spring.io/">Spring Initializr</a> page) and add the following imports:</p>
<pre><code class="lang-groovy">implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.apache.poi:poi:4.1.2")
implementation("org.apache.poi:poi-ooxml:4.1.2")
</code></pre>
<p>Let me explain the purpose of each library: </p>
<ul>
<li>The <strong>Spring Boot Starter Web</strong> is necessary to create the REST API in our application.</li>
<li>The <strong>Apache POI</strong> is a complex Java library for working with Excel files. If we would like to work only with the .xls format, then the <em>poi</em> import would be enough. In our case, we would like to add the support for the <strong>.xlsx</strong> format, so the <em>poi-ooxml</em> component is necessary as well.</li>
</ul>
<h2 id="heading-step-2-create-the-models">Step 2: Create the Models</h2>
<p>As the next step, let's create an enum class called <strong>CustomCellStyle</strong> with 4 constants: </p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">enum</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomCellStyle</span> </span>{
    GREY_CENTERED_BOLD_ARIAL_WITH_BORDER,
    RIGHT_ALIGNED,
    RED_BOLD_ARIAL_WITH_BORDER,
    RIGHT_ALIGNED_DATE_FORMAT
}
</code></pre>
<p>Although the purpose of this enum class might seem a bit enigmatic at the moment, it will all become clear in the next sections.</p>
<h2 id="heading-step-3-prepare-cells-styles">Step 3: Prepare Cells Styles</h2>
<p>The Apache POI library comes with the <strong>CellStyle</strong> interface, which we can use to define custom styling and formatting within rows, columns, and cells.</p>
<p>Let's create a <strong>StylesGenerator</strong> component, which will be responsible for preparing a map containing our custom styles:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Component</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StylesGenerator</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">prepareStyles</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>)</span></span>: Map&lt;CustomCellStyle, CellStyle&gt; {
        <span class="hljs-keyword">val</span> boldArial = createBoldArialFont(wb)
        <span class="hljs-keyword">val</span> redBoldArial = createRedBoldArialFont(wb)

        <span class="hljs-keyword">val</span> rightAlignedStyle = createRightAlignedStyle(wb)
        <span class="hljs-keyword">val</span> greyCenteredBoldArialWithBorderStyle =
            createGreyCenteredBoldArialWithBorderStyle(wb, boldArial)
        <span class="hljs-keyword">val</span> redBoldArialWithBorderStyle =
            createRedBoldArialWithBorderStyle(wb, redBoldArial)
        <span class="hljs-keyword">val</span> rightAlignedDateFormatStyle =
            createRightAlignedDateFormatStyle(wb)

        <span class="hljs-keyword">return</span> mapOf(
            CustomCellStyle.RIGHT_ALIGNED to rightAlignedStyle,
            CustomCellStyle.GREY_CENTERED_BOLD_ARIAL_WITH_BORDER to greyCenteredBoldArialWithBorderStyle,
            CustomCellStyle.RED_BOLD_ARIAL_WITH_BORDER to redBoldArialWithBorderStyle,
            CustomCellStyle.RIGHT_ALIGNED_DATE_FORMAT to rightAlignedDateFormatStyle
        )
    }
}
</code></pre>
<p>As you can see, with this approach, we create each style once and put it inside a map so that we will be able to refer to it later. </p>
<p>There are plenty of design techniques which we could use here, but I believe using a map and enum constants is one of the best ways to keep the code cleaner and easier to modify.</p>
<p>With that being said, let's add some missing functions inside the generator class. Let's start with custom fonts first:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createBoldArialFont</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>)</span></span>: Font {
    <span class="hljs-keyword">val</span> font = wb.createFont()
    font.fontName = <span class="hljs-string">"Arial"</span>
    font.bold = <span class="hljs-literal">true</span>
    <span class="hljs-keyword">return</span> font
}
</code></pre>
<p>The <strong>createBoldArialFont</strong> function creates a new bold Arial Font instance, which we will use later. </p>
<p>Similarly, let's implement a <strong>createRedBoldArialFont</strong> function and set the font color to red: </p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createRedBoldArialFont</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>)</span></span>: Font {
    <span class="hljs-keyword">val</span> font = wb.createFont()
    font.fontName = <span class="hljs-string">"Arial"</span>
    font.bold = <span class="hljs-literal">true</span>
    font.color = IndexedColors.RED.index
    <span class="hljs-keyword">return</span> font
}
</code></pre>
<p>After that, we can add other functions responsible for creating individual <strong>CellStyle</strong> instances: </p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createRightAlignedStyle</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>)</span></span>: CellStyle {
    <span class="hljs-keyword">val</span> style: CellStyle = wb.createCellStyle()
    style.alignment = HorizontalAlignment.RIGHT
    <span class="hljs-keyword">return</span> style
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createBorderedStyle</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>)</span></span>: CellStyle {
    <span class="hljs-keyword">val</span> thin = BorderStyle.THIN
    <span class="hljs-keyword">val</span> black = IndexedColors.BLACK.getIndex()
    <span class="hljs-keyword">val</span> style = wb.createCellStyle()
    style.borderRight = thin
    style.rightBorderColor = black
    style.borderBottom = thin
    style.bottomBorderColor = black
    style.borderLeft = thin
    style.leftBorderColor = black
    style.borderTop = thin
    style.topBorderColor = black
    <span class="hljs-keyword">return</span> style
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createGreyCenteredBoldArialWithBorderStyle</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>, boldArial: <span class="hljs-type">Font</span>)</span></span>: CellStyle {
    <span class="hljs-keyword">val</span> style = createBorderedStyle(wb)
    style.alignment = HorizontalAlignment.CENTER
    style.setFont(boldArial)
    style.fillForegroundColor = IndexedColors.GREY_25_PERCENT.getIndex();
    style.fillPattern = FillPatternType.SOLID_FOREGROUND;
    <span class="hljs-keyword">return</span> style
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createRedBoldArialWithBorderStyle</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>, redBoldArial: <span class="hljs-type">Font</span>)</span></span>: CellStyle {
    <span class="hljs-keyword">val</span> style = createBorderedStyle(wb)
    style.setFont(redBoldArial)
    <span class="hljs-keyword">return</span> style
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createRightAlignedDateFormatStyle</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>)</span></span>: CellStyle {
    <span class="hljs-keyword">val</span> style = wb.createCellStyle()
    style.alignment = HorizontalAlignment.RIGHT
    style.dataFormat = <span class="hljs-number">14</span>
    <span class="hljs-keyword">return</span> style
}
</code></pre>
<p>Please keep in mind that the above examples represent only a small part of <strong>CellStyle's</strong> possibilities. If you would like to see the full list, please refer to the official documentation <a target="_blank" href="https://poi.apache.org/apidocs/dev/org/apache/poi/ss/usermodel/CellStyle.html">here</a>.</p>
<h2 id="heading-step-4-create-the-reportservice-class"><strong>Step 4: Create the ReportService Class</strong></h2>
<p>As the next step, let's implement a <strong>ReportService</strong> class responsible for creating .xlsx and <strong>.xls</strong> files and returning them as ByteArray instances:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ReportService</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> stylesGenerator: StylesGenerator
) {
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateXlsxReport</span><span class="hljs-params">()</span></span>: ByteArray {
        <span class="hljs-keyword">val</span> wb = XSSFWorkbook()

        <span class="hljs-keyword">return</span> generateReport(wb)
    }

    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateXlsReport</span><span class="hljs-params">()</span></span>: ByteArray {
        <span class="hljs-keyword">val</span> wb = HSSFWorkbook()

        <span class="hljs-keyword">return</span> generateReport(wb)
    }
 }
</code></pre>
<p>As you can see, the only difference between these two formats' generation is the type of <strong>Workbook</strong> implementation we've. used. For the .xlsx format we will use the <strong>XSSFWorkbook</strong> class, and for the .xls we will use <strong>HSSFWorkbook</strong><em>.</em></p>
<p>Let's add the rest of the code to the <strong>ReportService</strong>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateReport</span><span class="hljs-params">(wb: <span class="hljs-type">Workbook</span>)</span></span>: ByteArray {
    <span class="hljs-keyword">val</span> styles = stylesGenerator.prepareStyles(wb)
    <span class="hljs-keyword">val</span> sheet: Sheet = wb.createSheet(<span class="hljs-string">"Example sheet name"</span>)

    setColumnsWidth(sheet)

    createHeaderRow(sheet, styles)
    createStringsRow(sheet, styles)
    createDoublesRow(sheet, styles)
    createDatesRow(sheet, styles)

    <span class="hljs-keyword">val</span> <span class="hljs-keyword">out</span> = ByteArrayOutputStream()
    wb.write(<span class="hljs-keyword">out</span>)

    <span class="hljs-keyword">out</span>.close()
    wb.close()

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">out</span>.toByteArray()
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setColumnsWidth</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>)</span></span> {
    sheet.setColumnWidth(<span class="hljs-number">0</span>, <span class="hljs-number">256</span> * <span class="hljs-number">20</span>)

    <span class="hljs-keyword">for</span> (columnIndex <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        sheet.setColumnWidth(columnIndex, <span class="hljs-number">256</span> * <span class="hljs-number">15</span>)
    }
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createHeaderRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">0</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue(<span class="hljs-string">"Column <span class="hljs-variable">$columnNumber</span>"</span>)
        cell.cellStyle = styles[CustomCellStyle.GREY_CENTERED_BOLD_ARIAL_WITH_BORDER]
    }
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createRowLabelCell</span><span class="hljs-params">(row: <span class="hljs-type">Row</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;, label: <span class="hljs-type">String</span>)</span></span> {
    <span class="hljs-keyword">val</span> rowLabel = row.createCell(<span class="hljs-number">0</span>)
    rowLabel.setCellValue(label)
    rowLabel.cellStyle = styles[CustomCellStyle.RED_BOLD_ARIAL_WITH_BORDER]
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createStringsRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">1</span>)
    createRowLabelCell(row, styles, <span class="hljs-string">"Strings row"</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue(<span class="hljs-string">"String <span class="hljs-variable">$columnNumber</span>"</span>)
        cell.cellStyle = styles[CustomCellStyle.RIGHT_ALIGNED]
    }
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createDoublesRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">2</span>)
    createRowLabelCell(row, styles, <span class="hljs-string">"Doubles row"</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue(BigDecimal(<span class="hljs-string">"<span class="hljs-subst">${columnNumber}</span>.99"</span>).toDouble())
        cell.cellStyle = styles[CustomCellStyle.RIGHT_ALIGNED]
    }
}

<span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createDatesRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">3</span>)
    createRowLabelCell(row, styles, <span class="hljs-string">"Dates row"</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue((LocalDate.now()))
        cell.cellStyle = styles[CustomCellStyle.RIGHT_ALIGNED_DATE_FORMAT]
    }
}
</code></pre>
<p>As you can see, the first thing the <strong>generateReport</strong> function does is that it styles the initialization. We pass the <strong>Workbook</strong> instance to the <strong>StylesGenerator</strong> and in return, we get a map, which we will use later to obtain appropriate CellStyles. </p>
<p>After that, it creates a new sheet within our workbook and passes a name for it. </p>
<p>Then, it invokes functions responsible for setting the columns' widths and operating on our sheet row by row. </p>
<p>Finally, it writes out our workbook to a ByteArrayOutputStream.</p>
<p>Let's take a minute and analyze what exactly each function does:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">setColumnsWidth</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>)</span></span> {
    sheet.setColumnWidth(<span class="hljs-number">0</span>, <span class="hljs-number">256</span> * <span class="hljs-number">20</span>)

    <span class="hljs-keyword">for</span> (columnIndex <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        sheet.setColumnWidth(columnIndex, <span class="hljs-number">256</span> * <span class="hljs-number">15</span>)
    }
}
</code></pre>
<p>As the name suggests, <strong>setColumnsWidth</strong> is responsible for setting widths of columns in our sheet. The first parameter passed to the <strong>setColumnWidth</strong> indicates the columnIndex, whereas the second one sets the width (in units of 1/256th of a character width). </p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createRowLabelCell</span><span class="hljs-params">(row: <span class="hljs-type">Row</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;, label: <span class="hljs-type">String</span>)</span></span> {
    <span class="hljs-keyword">val</span> rowLabel = row.createCell(<span class="hljs-number">0</span>)
    rowLabel.setCellValue(label)
    rowLabel.cellStyle = styles[CustomCellStyle.RED_BOLD_ARIAL_WITH_BORDER]
}
</code></pre>
<p>The <strong>createRowLabelCell</strong> function is responsible for adding a cell in the first column of the passed row, alongside setting its value to the specified label and setting the style. I've decided to add this function to slightly reduce the code's redundancy.</p>
<p>All of the below functions are pretty similar. Their purpose is to create a new row, invoking the <strong>createRowLabelCell</strong> function (except for <strong>createHeaderRow</strong>) and adding five columns with data to our sheet.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createHeaderRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">0</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue(<span class="hljs-string">"Column <span class="hljs-variable">$columnNumber</span>"</span>)
        cell.cellStyle = styles[CustomCellStyle.GREY_CENTERED_BOLD_ARIAL_WITH_BORDER]
    }
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createStringsRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">1</span>)
    createRowLabelCell(row, styles, <span class="hljs-string">"Strings row"</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue(<span class="hljs-string">"String <span class="hljs-variable">$columnNumber</span>"</span>)
        cell.cellStyle = styles[CustomCellStyle.RIGHT_ALIGNED]
    }
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createDoublesRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">2</span>)
    createRowLabelCell(row, styles, <span class="hljs-string">"Doubles row"</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue(BigDecimal(<span class="hljs-string">"<span class="hljs-subst">${columnNumber}</span>.99"</span>).toDouble())
        cell.cellStyle = styles[CustomCellStyle.RIGHT_ALIGNED]
    }
}
</code></pre>
<pre><code class="lang-kotlin"><span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createDatesRow</span><span class="hljs-params">(sheet: <span class="hljs-type">Sheet</span>, styles: <span class="hljs-type">Map</span>&lt;<span class="hljs-type">CustomCellStyle</span>, CellStyle&gt;)</span></span> {
    <span class="hljs-keyword">val</span> row = sheet.createRow(<span class="hljs-number">3</span>)
    createRowLabelCell(row, styles, <span class="hljs-string">"Dates row"</span>)

    <span class="hljs-keyword">for</span> (columnNumber <span class="hljs-keyword">in</span> <span class="hljs-number">1</span> until <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">val</span> cell = row.createCell(columnNumber)

        cell.setCellValue((LocalDate.now()))
        cell.cellStyle = styles[CustomCellStyle.RIGHT_ALIGNED_DATE_FORMAT]
    }
}
</code></pre>
<h2 id="heading-step-5-implement-the-rest-reportcontroller"><strong>Step 5: Implement the REST ReportController</strong></h2>
<p>As the last step, we will implement a class named <strong>ReportController</strong>. It will be responsible for handling POST requests coming to our two REST endpoints:</p>
<ul>
<li><em>/api/report/xlsx -</em> creating a report in a <em>.xlsx</em> format </li>
<li><em>/api/report/xls</em> - same as above, but in a .xls format</li>
</ul>
<pre><code class="lang-kotlin"><span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping(<span class="hljs-meta-string">"/api/report"</span>)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ReportController</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> reportService: ReportService
) {

    <span class="hljs-meta">@PostMapping(<span class="hljs-meta-string">"/xlsx"</span>)</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateXlsxReport</span><span class="hljs-params">()</span></span>: ResponseEntity&lt;ByteArray&gt; {
        <span class="hljs-keyword">val</span> report = reportService.generateXlsxReport()

        <span class="hljs-keyword">return</span> createResponseEntity(report, <span class="hljs-string">"report.xlsx"</span>)
    }

    <span class="hljs-meta">@PostMapping(<span class="hljs-meta-string">"/xls"</span>)</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateXlsReport</span><span class="hljs-params">()</span></span>: ResponseEntity&lt;ByteArray&gt; {
        <span class="hljs-keyword">val</span> report = reportService.generateXlsReport()

        <span class="hljs-keyword">return</span> createResponseEntity(report, <span class="hljs-string">"report.xls"</span>)
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">createResponseEntity</span><span class="hljs-params">(
        report: <span class="hljs-type">ByteArray</span>,
        fileName: <span class="hljs-type">String</span>
    )</span></span>: ResponseEntity&lt;ByteArray&gt; =
        ResponseEntity.ok()
            .contentType(MediaType.APPLICATION_OCTET_STREAM)
            .header(HttpHeaders.CONTENT_DISPOSITION, <span class="hljs-string">"attachment; filename=\"<span class="hljs-variable">$fileName</span>\""</span>)
            .body(report)

}
</code></pre>
<p>The most interesting part of the above code is the <strong>createResponseEntity</strong> function, which sets the passed ByteArray with its generated report as a response body. </p>
<p>Additionally, we set the <strong>Content-Type</strong> header of the response as the <strong>application/octet-stream</strong>, and the Content-Disposition as the <strong>attachment; filename=</strong>.</p>
<h2 id="heading-step-6-test-everything-with-postman"><strong>Step 6: Test Everything With Postman</strong></h2>
<p>Finally, we can run and test our Spring Boot application, for instance with the <code>gradlew</code> command:</p>
<pre><code>./gradlew bootRun
</code></pre><p>By default, the Spring Boot application will be running on port 8080, so let's open up <a target="_blank" href="https://www.postman.com/">Postman</a> (or any other tool), specify the <strong>POST</strong> request to <strong>localhost:8080/api/report/xls</strong> and hit <strong>Send and Download</strong> button: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/POST_xls.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>If everything went well, we should see a window allowing us to save the <strong>.xls</strong> file. </p>
<p>Similarly, let's test the second endpoint:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/12/POST_xlsx.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This time, the file extension should be .xlsx.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>That's all for this article! We've covered the process of generating Excel reports in a Spring Boot REST API with Apache POI and Kotlin.</p>
<p>If you enjoyed it and would like to learn other topics through similar articles, please visit my blog, <a target="_blank" href="https://codersee.com/"><strong>Codersee</strong></a>.</p>
<p>And the last thing: for the source code of a fully working project, please refer to <a target="_blank" href="https://github.com/codersee-blog/freecodecamp-spring-boot-kotlin-excel">this GitHub repository</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ COM Interface API Tutorial: Java Spring Boot + JACOB Library ]]>
                </title>
                <description>
                    <![CDATA[ By Serhii Povisenko In this article, I will show you how to embed the JACOB library into your Spring Boot application. This will help you call a COM interface API via the DLL library in your web application. Also, for illustrative purposes, I will pr... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/interface-in-java-tutorial-how-to-call-the-com-interface-spring-boot-jacob-library/</link>
                <guid isPermaLink="false">66d4608bd1ffc3d3eb89de36</guid>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Libraries ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 30 Sep 2020 05:07:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/Screenshot-2020-09-29-at-15.49.33.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Serhii Povisenko</p>
<p>In this article, I will show you how to embed the <a target="_blank" href="https://sourceforge.net/projects/jacob-project/">JACOB library</a> into your <a target="_blank" href="https://spring.io/projects/spring-boot">Spring Boot</a> application. This will help you call a <a target="_blank" href="https://en.wikipedia.org/wiki/Component_Object_Model">COM interface API</a> via the <a target="_blank" href="https://en.wikipedia.org/wiki/Dynamic-link_library">DLL</a> library in your web application.</p>
<p>Also, for illustrative purposes, I will provide a description of a COM API so you can build your application on top of it. You can find all the code snippets in this <a target="_blank" href="https://github.com/povisenko/jacob-within-spring-boot-2">GitHub repo</a>.</p>
<p>But first, a quick note: at <a target="_blank" href="https://cthesigns.co.uk">C the Signs</a> we deployed this solution that allowed us to integrate with <a target="_blank" href="https://www.emishealth.com">EMIS Health</a>. It is an electronic patient record system used in primary care in the United Kingdom. For integration we used their provided DLL library.</p>
<p>The approach that I'll show you here (sanitised to avoid leaking any sensitive information) rolled out to production more than two years ago, and has since proven its durability.</p>
<p>Since we recently employed a brand new approach to integrating with EMIS, the old system is going to be shut down in a month or two. So this tutorial is its swan song. Sleep, my little prince.</p>
<h2 id="heading-what-is-the-dll-api">What is the DLL API?</h2>
<p>First, let's start with a clear description of the DLL library. To do this, I prepared a short mock-up of the original technical documentation.</p>
<p>Let's take a look through it to see what the three methods of a COM interface are.</p>
<h3 id="heading-initialisewithid-method">InitialiseWithID Method</h3>
<p>This method is a security feature required on-site that lets us obtain a connection to an API server that we want to integrate with the library.</p>
<p>It requires the <code>AccountID</code> (GUID) of the current API user (to access the server) and some other initialization arguments that are listed below.</p>
<p>This function also supports an auto-login feature. If a client has a logged-in version of the running system (the library is a part of that system) and calls the method on the same host, the API will automatically complete the login under that user's account. Then it'll return the <code>SessionID</code> for subsequent API calls. </p>
<p>Otherwise, the client needs to continue with the <code>Logon</code> function (see the next part) using the returned <code>LoginID</code>.</p>
<p>To call the function, use the name <code>InitialiseWithID</code> with the following arguments:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>In/out</td><td>Type</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>address</td><td>In</td><td>String</td><td>provided integration server IP</td></tr>
<tr>
<td>AccountID</td><td>In</td><td>String</td><td>provided unique GUID string</td></tr>
<tr>
<td>LoginID</td><td>Out</td><td>String</td><td>GUID string used for Logon API call</td></tr>
<tr>
<td>Error</td><td>Out</td><td>String</td><td>Error description</td></tr>
<tr>
<td>Outcome</td><td>Out</td><td>Integer</td><td>-1 = Refer to error<br>1 = Successful initialise awaiting logon<br>2 = Unable to connect to server due to absent server, or incorrect details<br>3 = Unmatched AccountID<br>4 = Autologon successful</td></tr>
<tr>
<td>SessionID</td><td>Out</td><td>String</td><td>GUID used for subsequent interactions (if auto log in successful)</td></tr>
</tbody>
</table>
</div><h3 id="heading-logon-method">Logon Method</h3>
<p>This method determines the authority of the user. The username here is the ID used to log in to the system. The password is the API password set for that username. </p>
<p>In the success scenario, the call returns a <code>SessionID</code> string (GUID) that must be passed into other subsequent calls to authenticate them.</p>
<p>To call the function, use the name <code>Logon</code> with the following arguments:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>In/out</td><td>Type</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>LoginID</td><td>In</td><td>String</td><td>The login id returned by the initialization method Initialise with ID</td></tr>
<tr>
<td>username</td><td>In</td><td>String</td><td>provided API username</td></tr>
<tr>
<td>password</td><td>In</td><td>String</td><td>provided API password</td></tr>
<tr>
<td>SessionID</td><td>Out</td><td>String</td><td>GUID used for subsequent interactions (if logon successful)</td></tr>
<tr>
<td>Error</td><td>Out</td><td>String</td><td>Error description</td></tr>
<tr>
<td>Outcome</td><td>Out</td><td>Integer</td><td>-1 = Technical error<br>1 = Successful<br>2 = Expired<br>3 = Unsuccessful<br>4 = Invalid login ID or login ID does not have access to this product</td></tr>
</tbody>
</table>
</div><h3 id="heading-getmatchedusers-method">getMatchedUsers Method</h3>
<p>This call lets you find user data records that match specific criteria. The search term can only refer to one field at a time such as last name, first name, or date of birth. </p>
<p>A successful call returns an XML string with the data in it.</p>
<p>To call the function, use the name <code>getMatchedUsers</code> with the following arguments:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>In/out</td><td>Type</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td>SessionID</td><td>In</td><td>String</td><td>The session id returned by the logon  method</td></tr>
<tr>
<td>MatchTerm</td><td>In</td><td>String</td><td>Search term</td></tr>
<tr>
<td>MatchedList</td><td>Out</td><td>String</td><td>XML conforming to provided corresponding XSD scheme</td></tr>
<tr>
<td>SessionID</td><td>Out</td><td>String</td><td>GUID used for subsequent interactions (if logon successful)</td></tr>
<tr>
<td>Error</td><td>Out</td><td>String</td><td>Error description</td></tr>
<tr>
<td>Outcome</td><td>Out</td><td>Integer</td><td>-1 = Technical error<br>1 =  Users found<br>2 = Access denied<br>3 = No users</td></tr>
</tbody>
</table>
</div><h2 id="heading-dll-library-application-flow">DLL Library Application Flow</h2>
<p>To make it easier to grasp what we want to implement, I decided to create a simple flow diagram. </p>
<p>It describes a step-by-step scenario of how a web client can interact with our server-based application using its API. It encapsulates interaction with the DLL Library and allows us to get hypothetical users with the provided match term (search criteria):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/09/JACOB_DLL_FLOW-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Application Flow Diagram</em></p>
<h2 id="heading-registering-com">Registering COM</h2>
<p>Now let's learn how we can access the DLL library. To be able to interact with a 3rd party COM interface, it <a target="_blank" href="https://docs.microsoft.com/en-us/windows/win32/com/registering-com-applications">needs to be added to the registry</a>. </p>
<p>Here's what the docs say:</p>
<blockquote>
<p>The registry is a system database that contains information about the configuration of system hardware and software as well as about users of the system. Any Windows-based program can add information to the registry and read information back from the registry. Clients search the registry for interesting components to use.  </p>
<p>The registry maintains information about all the COM objects installed in the system. Whenever an application creates an instance of a COM component, the registry is consulted to resolve either the CLSID or ProgID of the component into the pathname of the server DLL or EXE that contains it.  </p>
<p>After determining the component's server, Windows either loads the server into the process space of the client application (in-process components) or starts the server in its own process space (local and remote servers).  </p>
<p>The server creates an instance of the component and returns to the client a reference to one of the component's interfaces.</p>
</blockquote>
<p>To learn how to do that, the official Microsoft documentation <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/framework/interop/registering-assemblies-with-com">says</a>:</p>
<blockquote>
<p>You can run a command-line tool called the <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/framework/tools/regasm-exe-assembly-registration-tool">Assembly Registration Tool (Regasm.exe)</a> to register or unregister an assembly for use with COM.  </p>
<p>Regasm.exe adds information about the class to the system registry so COM clients can use the .NET Framework class transparently.  </p>
<p>The <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.registrationservices">RegistrationServices</a> class provides the equivalent functionality. A managed component must be registered in the Windows registry before it can be activated from a COM client</p>
</blockquote>
<p>Make sure that your host machine has installed the required <code>.NET Framework</code> components. After that, you can execute the following CLI command:</p>
<pre><code class="lang-shell">C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe {PATH_TO_YOUR_DLL_FILE} /codebase
</code></pre>
<p>A message will display indicating whether the file was successfully registered. Now we're ready for the next step.</p>
<h2 id="heading-defining-the-backbone-of-the-application">Defining the Backbone of the Application</h2>
<h3 id="heading-dllapiservice">DllApiService</h3>
<p>First of all, let's define the interface that describes our DLL library as it is:</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">DllApiService</span> </span>{

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> accountId identifier for which we trigger initialisation
     * <span class="hljs-doctag">@return</span> Tuple3 from values of Outcome, SessionID/LoginID, error
     * where by the first argument you can understand what is the result of the API call
     */</span>
    Mono&lt;Tuple3&lt;Integer, String, String&gt;&gt; initialiseWithID(String accountId);

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> loginId  is retrieved before using {<span class="hljs-doctag">@link</span> DllApiService#initialiseWithID(String)} call
     * <span class="hljs-doctag">@param</span> username
     * <span class="hljs-doctag">@param</span> password
     * <span class="hljs-doctag">@return</span> Tuple3 from values of Outcome, SessionID, Error
     * where by the first argument you can understand what is the result of the API call
     */</span>
    Mono&lt;Tuple3&lt;Integer, String, String&gt;&gt; logon(String loginId, String username, String password);

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> sessionId is retrieved before using either
     *                  {<span class="hljs-doctag">@link</span> DllApiService#initialiseWithID(String)} or
     *                  {<span class="hljs-doctag">@link</span> DllApiService#logon(String, String, String)} calls
     * <span class="hljs-doctag">@param</span> matchTerm
     * <span class="hljs-doctag">@return</span> Tuple3 from values of Outcome, MatchedList, Error
     * where by the first argument you can understand what is the result of the API call
     */</span>
    Mono&lt;Tuple3&lt;Integer, String, String&gt;&gt; getMatchedUsers(String sessionId, String matchTerm);

    <span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">COM_API_Method</span> </span>{
        InitialiseWithID, Logon, getMatchedUsers
    }
}
</code></pre>
<p>As you might have noticed, all the methods map with the definition of the COM Interface described above, except for the <code>initialiseWithID</code> function.</p>
<p>I decided to omit the <code>address</code> variable in the signature (the IP of the integration server) and inject it as an environment variable which we will be implementing.</p>
<h3 id="heading-sessionidservice-explained">SessionIDService Explained</h3>
<p>To be able to retrieve any data using the library, first we need to get the <code>SessionID</code>. </p>
<p>According to the flow diagram above, this involves calling the <code>initialiseWithID</code> method first. After that, depending on the result, we will get either the SessionID or <code>LoginID</code> to use in subsequent <code>Logon</code> calls. </p>
<p>So basically this is a two-step process behind the scenes. Now, let's create the interface, and after that, the implementation:</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">SessionIDService</span> </span>{

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> accountId identifier for which we retrieve SessionID
     * <span class="hljs-doctag">@param</span> username
     * <span class="hljs-doctag">@param</span> password
     * <span class="hljs-doctag">@return</span> Tuple3 containing the following values:
     * result ( Boolean), sessionId (String) and status (HTTP Status depending on the result)
     */</span>
    Mono&lt;Tuple3&lt;Boolean, String, HttpStatus&gt;&gt; getSessionId(String accountId, String username, String password);
}
</code></pre>
<pre><code class="lang-java"><span class="hljs-meta">@Service</span>
<span class="hljs-meta">@RequiredArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SessionIDServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">SessionIDService</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> DllApiService dll;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> Mono&lt;Tuple3&lt;Boolean, String, HttpStatus&gt;&gt; getSessionId(String accountId, String username, String password) {
        <span class="hljs-keyword">return</span> dll.initialiseWithID(accountId)
                  .flatMap(t4 -&gt; {
                      <span class="hljs-keyword">switch</span> (t4.getT1()) {
                          <span class="hljs-keyword">case</span> -<span class="hljs-number">1</span>:
                              <span class="hljs-keyword">return</span> just(of(<span class="hljs-keyword">false</span>, t4.getT3(), SERVICE_UNAVAILABLE));

                          <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>: {

                              <span class="hljs-keyword">return</span> dll.logon(t4.getT2(), username, password)
                                        .map(t3 -&gt; {
                                            <span class="hljs-keyword">switch</span> (t3.getT1()) {
                                                <span class="hljs-keyword">case</span> -<span class="hljs-number">1</span>:
                                                    <span class="hljs-keyword">return</span> of(<span class="hljs-keyword">false</span>, t3.getT3(), SERVICE_UNAVAILABLE);
                                                <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
                                                    <span class="hljs-keyword">return</span> of(<span class="hljs-keyword">true</span>, t3.getT2(), OK);
                                                <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
                                                <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:
                                                    <span class="hljs-keyword">return</span> of(<span class="hljs-keyword">false</span>, t3.getT3(), FORBIDDEN);
                                                <span class="hljs-keyword">default</span>:
                                                    <span class="hljs-keyword">return</span> of(<span class="hljs-keyword">false</span>, t3.getT3(), BAD_REQUEST);

                                            }
                                        });

                          }

                          <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:
                              <span class="hljs-keyword">return</span> just(of(<span class="hljs-keyword">true</span>, t4.getT2(), OK));

                          <span class="hljs-keyword">default</span>:
                              <span class="hljs-keyword">return</span> just(of(<span class="hljs-keyword">false</span>, t4.getT3(), BAD_REQUEST));
                      }
                  });

    }
}
</code></pre>
<h3 id="heading-api-facade">API Facade</h3>
<p>The next step is to design our web application API. It should represent and encapsulate our interaction with the COM Interface API:</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">DllApiRouter</span> </span>{

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> RouterFunction&lt;ServerResponse&gt; <span class="hljs-title">dllApiRoute</span><span class="hljs-params">(DllApiRouterHandler handler)</span> </span>{
        <span class="hljs-keyword">return</span> RouterFunctions.route(GET(<span class="hljs-string">"/api/sessions/{accountId}"</span>), handler::sessionId)
                              .andRoute(GET(<span class="hljs-string">"/api/users/{matchTerm}"</span>), handler::matchedUsers);
    }
}
</code></pre>
<p>Besides the <code>Router</code> class, let's define an implementation of its handler with logic for retrieving the SessionID and the user records data. </p>
<p>For the second scenario, to be able to make a DLL <code>getMatchedUsers</code> API call according to the design, let's use the mandatory header <code>X-SESSION-ID</code>:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Slf4j</span>
<span class="hljs-meta">@Component</span>
<span class="hljs-meta">@RequiredArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DllApiRouterHandler</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String SESSION_ID_HDR = <span class="hljs-string">"X-SESSION-ID"</span>;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> DllApiService service;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> AccountRepo accountRepo;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> SessionIDService sessionService;

    <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;ServerResponse&gt; <span class="hljs-title">sessionId</span><span class="hljs-params">(ServerRequest request)</span> </span>{
        <span class="hljs-keyword">final</span> String accountId = request.pathVariable(<span class="hljs-string">"accountId"</span>);

        <span class="hljs-keyword">return</span> accountRepo.findById(accountId)
                          .flatMap(acc -&gt; sessionService.getSessionId(accountId, acc.getApiUsername(), acc.getApiPassword()))
                          .doOnEach(logNext(t3 -&gt; {
                              <span class="hljs-keyword">if</span> (t3.getT1()) {
                                  log.info(format(<span class="hljs-string">"SessionId to return %s"</span>, t3.getT2()));
                              } <span class="hljs-keyword">else</span> {
                                  log.warn(format(<span class="hljs-string">"Session Id could not be retrieved. Cause: %s"</span>, t3.getT2()));
                              }
                          }))
                          .flatMap(t3 -&gt; status(t3.getT3()).contentType(APPLICATION_JSON)
                                                           .bodyValue(t3.getT1() ? t3.getT2() : Response.error(t3.getT2())))

                          .switchIfEmpty(Mono.just(<span class="hljs-string">"Account could not be found with provided ID "</span> + accountId)
                                             .doOnEach(logNext(log::info))
                                             .flatMap(msg -&gt; badRequest().bodyValue(Response.error(msg))));
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> Mono&lt;ServerResponse&gt; <span class="hljs-title">matchedUsers</span><span class="hljs-params">(ServerRequest request)</span> </span>{

        <span class="hljs-keyword">return</span> sessionIdHeader(request).map(sId -&gt; Tuples.of(sId, request.queryParam(<span class="hljs-string">"matchTerm"</span>)
                                                                         .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> IllegalArgumentException(
                                                                                 <span class="hljs-string">"matchTerm query param should be specified"</span>))))
                                       .flatMap(t2 -&gt; service.getMatchedUsers(t2.getT1(), t2.getT2()))
                                       .flatMap(<span class="hljs-keyword">this</span>::handleT3)
                                       .onErrorResume(IllegalArgumentException.class, <span class="hljs-keyword">this</span>::handleIllegalArgumentException);

    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Mono&lt;String&gt; <span class="hljs-title">sessionIdHeader</span><span class="hljs-params">(ServerRequest request)</span> </span>{
        <span class="hljs-keyword">return</span> Mono.justOrEmpty(request.headers()
                                       .header(SESSION_ID_HDR)
                                       .stream()
                                       .findFirst()
                                       .orElseThrow(() -&gt; <span class="hljs-keyword">new</span> IllegalArgumentException(SESSION_ID_HDR + <span class="hljs-string">" header is mandatory"</span>)));
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Mono&lt;ServerResponse&gt; <span class="hljs-title">handleT3</span><span class="hljs-params">(Tuple3&lt;Integer, String, String&gt; t3)</span> </span>{
        <span class="hljs-keyword">switch</span> (t3.getT1()) {
            <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
                <span class="hljs-keyword">return</span> ok().contentType(APPLICATION_JSON)
                           .bodyValue(t3.getT2());
            <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
                <span class="hljs-keyword">return</span> status(FORBIDDEN).contentType(APPLICATION_JSON)
                                        .bodyValue(Response.error(t3.getT3()));
            <span class="hljs-keyword">default</span>:
                <span class="hljs-keyword">return</span> badRequest().contentType(APPLICATION_JSON)
                                   .bodyValue(Response.error(t3.getT3()));
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> Mono&lt;ServerResponse&gt; <span class="hljs-title">handleIllegalArgumentException</span><span class="hljs-params">(IllegalArgumentException e)</span> </span>{
        <span class="hljs-keyword">return</span> Mono.just(Response.error(e.getMessage()))
                   .doOnEach(logNext(res -&gt; log.info(String.join(<span class="hljs-string">","</span>, res.getErrors()))))
                   .flatMap(res -&gt; badRequest().contentType(MediaType.APPLICATION_JSON)
                                               .bodyValue(res));
    }

    <span class="hljs-meta">@Getter</span>
    <span class="hljs-meta">@Setter</span>
    <span class="hljs-meta">@NoArgsConstructor</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Response</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Serializable</span> </span>{

        <span class="hljs-keyword">private</span> String message;

        <span class="hljs-keyword">private</span> Set&lt;String&gt; errors;

        <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Response</span><span class="hljs-params">(Set&lt;String&gt; errors)</span> </span>{
            <span class="hljs-keyword">this</span>.errors = errors;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Response <span class="hljs-title">error</span><span class="hljs-params">(String error)</span> </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(singleton(error));
        }
    }
}
</code></pre>
<h3 id="heading-account-entity">Account Entity</h3>
<p>As you might have noticed, we've imported <code>AccountRepo</code> in the router's handler to find the entity in a database by the provided <code>accountId</code>. This lets us get the corresponding API user credentials and use all three in the DLL <code>Logon</code> API call. </p>
<p>To get a clearer picture, let's define the managed <code>Account</code> entity as well:</p>
<pre><code class="lang-java"><span class="hljs-meta">@TypeAlias("Account")</span>
<span class="hljs-meta">@Document(collection = "accounts")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Account</span> </span>{

    <span class="hljs-meta">@Version</span>
    <span class="hljs-keyword">private</span> Long version;

    <span class="hljs-comment">/**
     * unique account ID for API, provided by supplier
     * defines restriction for data domain visibility
     * i.e. data from one account is not visible for another
     */</span>
    <span class="hljs-meta">@Id</span>
    <span class="hljs-keyword">private</span> String accountId;

    <span class="hljs-comment">/**
     * COM API username, provided by supplier
     */</span>
    <span class="hljs-keyword">private</span> String apiUsername;

    <span class="hljs-comment">/**
     * COM API password, provided by supplier
     */</span>
    <span class="hljs-keyword">private</span> String apiPassword;


    <span class="hljs-meta">@CreatedDate</span>
    <span class="hljs-keyword">private</span> Date createdAt;

    <span class="hljs-meta">@LastModifiedDate</span>
    <span class="hljs-keyword">private</span> Date updatedOn;
}
</code></pre>
<h2 id="heading-the-jacob-library-setup">The JACOB Library Setup</h2>
<p>All parts of our application are ready now except the core – the configuration and use of the JACOB library. Let's start with setting up the library.</p>
<p>The library is distributed via <a target="_blank" href="https://sourceforge.net/projects/jacob-project/">sourceforge.net</a>. I did not find it available anywhere on either the Central Maven Repo or any other repositories online. So I decided to import it manually into our project as a local package. </p>
<p>To do that, I downloaded it and put it in the root folder under <code>/libs/jacob-1.19</code>. </p>
<p>After that, put the following <a target="_blank" href="https://maven.apache.org/plugins/maven-install-plugin/">maven-install-plugin</a> configuration into <code>pom.xml</code>. This will add the library to the local repository during Maven's <code>install</code> build phase:</p>
<pre><code class="lang-xml"><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-install-plugin<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">executions</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">execution</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">id</span>&gt;</span>install-jacob<span class="hljs-tag">&lt;/<span class="hljs-name">id</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">phase</span>&gt;</span>validate<span class="hljs-tag">&lt;/<span class="hljs-name">phase</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">file</span>&gt;</span>${basedir}/libs/jacob-1.19/jacob.jar<span class="hljs-tag">&lt;/<span class="hljs-name">file</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">repositoryLayout</span>&gt;</span>default<span class="hljs-tag">&lt;/<span class="hljs-name">repositoryLayout</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>net.sf.jacob-project<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>jacob<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.19<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">packaging</span>&gt;</span>jar<span class="hljs-tag">&lt;/<span class="hljs-name">packaging</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">generatePom</span>&gt;</span>true<span class="hljs-tag">&lt;/<span class="hljs-name">generatePom</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">goals</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">goal</span>&gt;</span>install-file<span class="hljs-tag">&lt;/<span class="hljs-name">goal</span>&gt;</span>
         <span class="hljs-tag">&lt;/<span class="hljs-name">goals</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">execution</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">executions</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">plugin</span>&gt;</span>
</code></pre>
<p>That will let you easily add the dependency as usual:</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>net.sf.jacob-project<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>jacob<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.19<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>
</code></pre>
<p>The library import is finished. Now let's get it ready to use it.</p>
<p>To interact with the COM component, JACOB provides a wrapper called an <code>ActiveXComponent</code> class (as I mentioned before). </p>
<p>It has a method called <code>invoke(String function, Variant... args)</code> that lets us make exactly what we want. </p>
<p>Generally speaking, our library is set up to create the <code>ActiveXComponent</code> bean so we can use it anywhere we want in the app (and we want it in the implementation of <code>DllApiService</code>). </p>
<p>So let's define a separate Spring <code>@Configuration</code> with all the essential preparations:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Slf4j</span>
<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">JacobCOMConfiguration</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String COM_INTERFACE_NAME = <span class="hljs-string">"NAME_OF_COM_INTERFACE_AS_IN_REGISTRY"</span>;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String JACOB_LIB_PATH = System.getProperty(<span class="hljs-string">"user.dir"</span>) + <span class="hljs-string">"\\libs\\jacob-1.19"</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String LIB_FILE = System.getProperty(<span class="hljs-string">"os.arch"</span>)
                                                 .equals(<span class="hljs-string">"amd64"</span>) ? <span class="hljs-string">"\\jacob-1.19-x64.dll"</span> : <span class="hljs-string">"\\jacob-1.19-x86.dll"</span>;

    <span class="hljs-keyword">private</span> File temporaryDll;

    <span class="hljs-keyword">static</span> {
        log.info(<span class="hljs-string">"JACOB lib path: {}"</span>, JACOB_LIB_PATH);
        log.info(<span class="hljs-string">"JACOB file lib path: {}"</span>, JACOB_LIB_PATH + LIB_FILE);
        System.setProperty(<span class="hljs-string">"java.library.path"</span>, JACOB_LIB_PATH);
        System.setProperty(<span class="hljs-string">"com.jacob.debug"</span>, <span class="hljs-string">"true"</span>);
    }

    <span class="hljs-meta">@PostConstruct</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException </span>{
        InputStream inputStream = <span class="hljs-keyword">new</span> FileInputStream(JACOB_LIB_PATH + LIB_FILE);

        temporaryDll = File.createTempFile(<span class="hljs-string">"jacob"</span>, <span class="hljs-string">".dll"</span>);
        FileOutputStream outputStream = <span class="hljs-keyword">new</span> FileOutputStream(temporaryDll);
        <span class="hljs-keyword">byte</span>[] array = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">8192</span>];
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = inputStream.read(array); i != -<span class="hljs-number">1</span>; i = inputStream.read(array)) {
            outputStream.write(array, <span class="hljs-number">0</span>, i);
        }
        outputStream.close();

        System.setProperty(LibraryLoader.JACOB_DLL_PATH, temporaryDll.getAbsolutePath());
        LibraryLoader.loadJacobLibrary();
        log.info(<span class="hljs-string">"JACOB library is loaded and ready to use"</span>);
    }

    <span class="hljs-meta">@Bean</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ActiveXComponent <span class="hljs-title">dllAPI</span><span class="hljs-params">()</span> </span>{
        ActiveXComponent activeXComponent = <span class="hljs-keyword">new</span> ActiveXComponent(COM_INTERFACE_NAME);
        log.info(<span class="hljs-string">"API COM interface {} wrapped into ActiveXComponent is created and ready to use"</span>, COM_INTERFACE_NAME);
        <span class="hljs-keyword">return</span> activeXComponent;
    }

    <span class="hljs-meta">@PreDestroy</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">clean</span><span class="hljs-params">()</span> </span>{
        temporaryDll.deleteOnExit();
        log.info(<span class="hljs-string">"Temporary DLL API library is cleaned on exit"</span>);
    }
}
</code></pre>
<p>It's worth mentioning that, besides defining the bean, we initialize the library components based on the host machine's ISA (instruction set architecture).</p>
<p>Also, we follow some common recommendations to make a copy of the corresponding library's file. This avoids any potential corruption of the original file during runtime. We also need to cleanup all allocated resources when the applications terminates.</p>
<p>Now the library is set up and ready to use. Finally, we can implement our last main component that helps us interact with the DLL API:  <code>DllApiServiceImpl</code>.</p>
<h2 id="heading-how-to-implement-a-dll-library-api-service">How to Implement a DLL Library API Service</h2>
<p>As all COM API calls are going to be cooked using a common approach, let's implement <code>InitialiseWithID</code> first. After that, all other methods can be implemented easily in a similar way.</p>
<p>As I mentioned before, to interact with the COM interface, JACOB provides us with the <code>ActiveXComponent</code> class that has the <code>invoke(String function, Variant... args)</code> method. </p>
<p>If you want to know more about the <code>Variant</code> class, the JACOB documentation says the following (you can find it in the <a target="_blank" href="https://sourceforge.net/projects/jacob-project/">archive</a> or under <code>/libs/jacob-1.19</code> in the <a target="_blank" href="https://github.com/povisenko/jacob-within-spring-boot-2">project</a>):</p>
<blockquote>
<p>The multi-format data type used for all call backs and most communications between Java and COM. It provides a single class that can handle all data types.</p>
</blockquote>
<p>This means that all arguments defined in the <code>InitialiseWithID</code> signature should be wrapped with <code>new Variant(java.lang.Object in)</code> and passed to the <code>invoke</code> method. Use the same order as specified in the interface description at the beginning of this article.</p>
<p>The only other important thing we haven't touched on yet is how to distinguish <code>in</code> and <code>out</code> type arguments. </p>
<p>For that purpose, <code>Variant</code> provides a constructor that accepts the data object and information about whether this is by reference or not. This means that after <code>invoke</code> is called, all variants that were initialized as references can be accessed after the call. So we can extract the results from <code>out</code> arguments. </p>
<p>To do that, just pass an extra boolean variable to the constructor as the second parameter: <code>new Variant(java.lang.Object pValueObject, boolean fByRef)</code>. </p>
<p>Initializing the <code>Variant</code> object as reference puts an additional requirement on the client to decide when to release the value (so it can be scrapped by the garbage collector). </p>
<p>For that purpose, you have the <code>safeRelease()</code> method that is supposed to be called when the value is taken from the corresponding <code>Variant</code> object.  </p>
<p>Putting all the pieces together gives us the following service's implementation:</p>
<pre><code class="lang-java"><span class="hljs-meta">@RequiredArgsConstructor</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DllApiServiceImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DllApiService</span> </span>{

    <span class="hljs-meta">@Value("${DLL_API_ADDRESS}")</span>
    <span class="hljs-keyword">private</span> String address;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ActiveXComponent dll;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> Mono&lt;Tuple3&lt;Integer, String, String&gt;&gt; initialiseWithID(<span class="hljs-keyword">final</span> String accountId) {

        <span class="hljs-keyword">return</span> Mono.just(format(<span class="hljs-string">"Calling %s(%s, %s, %s, %s, %s, %s)"</span>,<span class="hljs-comment">//</span>
                                InitialiseWithID, address, accountId, <span class="hljs-string">"loginId/out"</span>, <span class="hljs-string">"error/out"</span>, <span class="hljs-string">"outcome/out"</span>, <span class="hljs-string">"sessionId/out"</span>))
                   .doOnEach(logNext(log::info))
                   <span class="hljs-comment">//invoke COM interface method and extract the result mapping it onto corresponding *Out inner class</span>
                   .map(msg -&gt; invoke(InitialiseWithID, vars -&gt; InitialiseWithIDOut.builder()
                                                                                   .loginId(vars[<span class="hljs-number">3</span>].toString())
                                                                                   .error(vars[<span class="hljs-number">4</span>].toString())
                                                                                   .outcome(valueOf(vars[<span class="hljs-number">5</span>].toString()))
                                                                                   .sessionId(vars[<span class="hljs-number">6</span>].toString())
                                                                                   .build(), <span class="hljs-comment">//</span>
                                      <span class="hljs-keyword">new</span> Variant(address), <span class="hljs-keyword">new</span> Variant(accountId), initRef(), initRef(), initRef(), initRef()))
                   <span class="hljs-comment">//Handle the response according to the documentation</span>
                   .map(out -&gt; {

                       <span class="hljs-keyword">final</span> String errorVal;

                       <span class="hljs-keyword">switch</span> (out.outcome) {
                           <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
                               errorVal = <span class="hljs-string">"InitialiseWithID method call failed. DLL API request outcome (response code from server via DLL) = 2 "</span> +<span class="hljs-comment">//</span>
                                       <span class="hljs-string">"(Unable to connect to server due to absent server, or incorrect details)"</span>;
                               <span class="hljs-keyword">break</span>;
                           <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
                               errorVal = <span class="hljs-string">"InitialiseWithID method call failed. DLL API request outcome (response code from server via DLLe) = 3 (Unmatched AccountID)"</span>;
                               <span class="hljs-keyword">break</span>;
                           <span class="hljs-keyword">default</span>:
                               errorVal = handleOutcome(out.outcome, out.error, InitialiseWithID);
                       }

                       <span class="hljs-keyword">return</span> of(out, errorVal);
                   })
                   .doOnEach(logNext(t2 -&gt; {
                       InitialiseWithIDOut out = t2.getT1();
                       log.info(<span class="hljs-string">"{} API call result:\noutcome: {}\nsessionId: {}\nerror: {}\nloginId: {}"</span>,<span class="hljs-comment">//</span>
                                InitialiseWithID, out.outcome, out.sessionId, t2.getT2(), out.loginId);
                   }))
                   .map(t2 -&gt; {
                       InitialiseWithIDOut out = t2.getT1();
                       <span class="hljs-comment">//out.outcome == 4 auto-login successful, SessionID is retrieved</span>
                       <span class="hljs-keyword">return</span> of(out.outcome, out.outcome == <span class="hljs-number">4</span> ? out.sessionId : out.loginId, t2.getT2());
                   });
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Variant <span class="hljs-title">initRef</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Variant(<span class="hljs-string">""</span>, <span class="hljs-keyword">true</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">handleOutcome</span><span class="hljs-params">(Integer outcome, String error, COM_API_Method method)</span> </span>{
        <span class="hljs-keyword">switch</span> (outcome) {
            <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
                <span class="hljs-keyword">return</span> <span class="hljs-string">"no error"</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
                <span class="hljs-keyword">return</span> format(<span class="hljs-string">"%s method call failed. DLL API request outcome (response code from server via DLL) = 2 (Access denied)"</span>, method);
            <span class="hljs-keyword">default</span>:
                <span class="hljs-keyword">return</span> format(<span class="hljs-string">"%s method call failed. DLL API request outcome (response code from server via DLL) = %s (server technical error). "</span> + <span class="hljs-comment">//</span>
                                      <span class="hljs-string">"DLL API is temporary unavailable (server behind is down), %s"</span>, method, outcome, error);
        }

    }

    <span class="hljs-comment">/**
     * <span class="hljs-doctag">@param</span> method     to be called in COM interface
     * <span class="hljs-doctag">@param</span> returnFunc maps Variants (references) array onto result object that is to be returned by the method
     * <span class="hljs-doctag">@param</span> vars       arguments required for calling COM interface method
     * <span class="hljs-doctag">@param</span> &lt;T&gt;        type of the result object that is to be returned by the method
     * <span class="hljs-doctag">@return</span> result of the COM API method invocation in defined format
     */</span>
    <span class="hljs-keyword">private</span> &lt;T extends Out&gt; <span class="hljs-function">T <span class="hljs-title">invoke</span><span class="hljs-params">(COM_API_Method method, Function&lt;Variant[], T&gt; returnFunc, Variant... vars)</span> </span>{
        dll.invoke(method.name(), vars);
        T res = returnFunc.apply(vars);
        asList(vars).forEach(Variant::safeRelease);
        <span class="hljs-keyword">return</span> res;
    }

    <span class="hljs-meta">@SuperBuilder</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Out</span> </span>{
        <span class="hljs-keyword">final</span> Integer outcome;
        <span class="hljs-keyword">final</span> String error;
    }

    <span class="hljs-meta">@SuperBuilder</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InitialiseWithIDOut</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Out</span> </span>{
        <span class="hljs-keyword">final</span> String loginId;
        <span class="hljs-keyword">final</span> String sessionId;
}
</code></pre>
<p>Two other methods, <code>Logon</code> and <code>getMatchedUsers</code>, are implemented accordingly. You can refer to my <a target="_blank" href="https://github.com/povisenko/jacob-within-spring-boot-2/blob/master/src/main/java/me/povisenko/jacob_within_spring_boot_2/services/impl/DllApiServiceImpl.java">GitHub</a> repo for a complete version of the service if you want to check it out.</p>
<h2 id="heading-congratulations-youve-learned-a-few-things">Congratulations – You've Learned a Few Things</h2>
<p>We've gone through a step by step scenario that showed us how a hypothetical COM API could be distributed and called in Java. </p>
<p>We also learned how the JACOB library can be configured and effectively used to interact with a DDL library within your Spring Boot 2 application.</p>
<p>A small improvement would be to cache the retrieved SessionID which could improve the general flow. But that's a bit outside the scope of this article. </p>
<p>If you want to investigate further, you can find that on GitHub where it's implemented using Spring's caching mechanism.</p>
<p>Hope you enjoyed going through everything with me and found this tutorial helpful!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Set Up Java Spring Boot JWT Authorization and Authentication ]]>
                </title>
                <description>
                    <![CDATA[ By Yiğit Kemal Erinç In the past month, I had a chance to implement JWT auth for a side project. I have previously worked with JWT in Ruby on Rails, but this was my first time in Spring.  In this post, I will try to explain what I have ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-setup-jwt-authorization-and-authentication-in-spring/</link>
                <guid isPermaLink="false">66d45e44182810487e0ce155</guid>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authorization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JSON Web Tokens ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JWT ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 12 Aug 2020 20:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/08/jwt.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Yiğit Kemal Erinç</p>
<p>In the past month, I had a chance to implement JWT auth for a side project. I have previously worked with JWT in Ruby on Rails, but this was my first time in Spring. </p>
<p>In this post, I will try to explain what I have learned and applied in my project to share my experience and hopefully help some people. </p>
<p>We will start by taking a quick look at the theory behind JWT and how it works. Then we will look at how to implement it in a Spring Boot application.</p>
<h2 id="heading-jwt-basics">JWT Basics</h2>
<p>JWT, or JSON Web Tokens (<a target="_blank" href="https://tools.ietf.org/html/rfc7519">RFC 7519</a>), is a standard that is mostly used for securing REST APIs. Despite being a relatively new technology, it is gaining rapid popularity.</p>
<p>In the JWT auth process, the front end (client) firstly sends some credentials to authenticate itself (username and password in our case, since we're working on a web application). </p>
<p>The server (the Spring app in our case) then checks those credentials, and if they are valid, it generates a JWT and returns it. </p>
<p>After this step client has to provide this token in the request’s <strong>Authorization</strong> header in the “Bearer TOKEN” form. The back end will check the validity of this token and authorize or reject requests. The token may also store user roles and authorize the requests based on the given authorities.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/1.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-implementation">Implementation</h2>
<p>Now let’s see how we can implement the JWT login and save mechanism in a real Spring application.</p>
<h3 id="heading-dependencies">Dependencies</h3>
<p>You can see the list of Maven dependencies that our example code uses below. Note that the core dependencies like Spring Boot and Hibernate are not included in this screenshot.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/2-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-saving-users">Saving Users</h3>
<p>We will start by creating controllers to save users securely and authenticate them based on username and password.</p>
<p>We have a model entity called User. It is a simple entity class that maps to the <strong>USER</strong> table. You can use whatever properties you need depending on your application.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/3-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We also have a simple <strong>UserRepository</strong> class to save users. We need to override the <strong>findByUsername</strong> method since we will use it in authentication.</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">UserRepository</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">JpaRepository</span>&lt;<span class="hljs-title">User</span>, <span class="hljs-title">String</span>&gt;</span>{ 
    <span class="hljs-function">User <span class="hljs-title">findByUsername</span><span class="hljs-params">(String username)</span></span>; 
}
</code></pre>
<p>We should never store plaintext passwords in the database because many users tend to use the same password for multiple sites. </p>
<p>There are many different hashing algorithms, but the most commonly used one is <strong>BCrypt</strong> and it is a recommended method of secure hashing. You can check out <a target="_blank" href="https://security.blogoverflow.com/2013/09/about-secure-password-hashing/#:~:text=Passwords%20should%20be%20hashed%20with,providing%20most%20security%20is%20bcrypt.">this</a> article for more information on the topic.</p>
<p>To hash the password, we will define a <strong>BCrypt</strong> bean in <strong>@SpringBootApplication</strong> and annotate the main class as follows:</p>
<pre><code class="lang-java"><span class="hljs-meta">@Bean</span> <span class="hljs-function"><span class="hljs-keyword">public</span> BCryptPasswordEncoder <span class="hljs-title">bCryptPasswordEncoder</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> BCryptPasswordEncoder(); 
}
</code></pre>
<p>We will call the methods on this bean when we need to hash a password.</p>
<p>We also need a UserController to save users. We create the controller, annotate it with <strong>@RestController,</strong> and define the corresponding mapping. </p>
<p>In our application, we save the user based on a DTO object that is passed from the front end. You can also pass a User object in <strong>@RequestBody</strong>.</p>
<p>After we pass the DTO object, we encrypt the password field using the <strong>BCrypt</strong> bean we created earlier. You could also do this in the controller, but it is a better practice to put this logic in the service class.</p>
<pre><code class="lang-java"><span class="hljs-meta">@Transactional(rollbackFor = Exception.class)</span> 
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">saveDto</span><span class="hljs-params">(UserDto userDto)</span> </span>{ 
    userDto.setPassword(bCryptPasswordEncoder
           .encode(userDto.getPassword())); 
    <span class="hljs-keyword">return</span> save(<span class="hljs-keyword">new</span> User(userDto)).getId(); 
}
</code></pre>
<h3 id="heading-authentication-filter">Authentication Filter</h3>
<p>We need authentication to make sure that the user is really who they claim to be. We will be using the classic username/password pair to accomplish this.</p>
<p>Here are the steps to implement authentication:</p>
<ol>
<li>Create our Authentication Filter that extends <strong>UsernamePasswordAuthenticationFilter</strong></li>
<li>Create a security configuration class that extends <strong>WebSecurityConfigurerAdapter</strong> and apply the filter</li>
</ol>
<p>Here is the code for our Authentication Filter – as you might know, filters are the backbone of Spring Security.</p>


<p>Let’s go over this code step by step.</p>
<p>This class extends <strong>UsernamePasswordAuthenticationFilter</strong> which is the default class for password authentication in Spring Security. We extend it to define our custom authentication logic.</p>
<p>We make a call to the <strong>setFilterProcessesUrl</strong> method in our constructor. This method sets the default login URL to the provided parameter. </p>
<p>If you remove this line, Spring Security creates the <strong>“/login”</strong> endpoint by default. It defines the login endpoint for us, which is why we will not define a login endpoint in our controller explicitly. </p>
<p>After this line our login endpoint will be <strong>/api/services/controller/user/login</strong>. You can use this function to stay consistent with your endpoints.</p>
<p>We override the <strong>attemptAuthentication</strong> and <strong>successfulAuthentication</strong> methods of the <strong>UsernameAuthenticationFilter</strong> class.</p>
<p>The <strong>attemptAuthentication</strong> function runs when the user tries to log in to our application. It reads the credentials, creates a user POJO from them, and then checks the credentials to authenticate. </p>
<p>We pass the username, password, and an empty list. The empty list represents the authorities (roles), and we leave it as is since we do not have any roles in our application yet.</p>
<p>If the authentication is successful, the <strong>successfulAuthentication</strong> method runs. The parameters of this method are passed by Spring Security behind the scenes. </p>
<p>The <strong>attemptAuthentication</strong> method returns an <strong>Authentication</strong> object that contains the authorities we passed while attempting. </p>
<p>We want to return a token to user after authentication is successful, so we create the token using username, secret, and expiration date. We need to define the <strong>SECRET</strong> and <strong>EXPIRATION_DATE</strong> now.</p>


<p>We create a class to be a container for our constants. You can set the secret to whatever you want, but the best practice is making the secret key as long as your hash. We use the <strong>HS256</strong> algorithm in this example, so our secret key is 256 bits/32 chars.</p>
<p>The expiration time is set to 15 minutes, because it is the best practice against secret key brute-forcing attacks. The time is in milliseconds.</p>
<p>We have prepared our Authentication filter, but it is not active yet. We also need an Authorization filter, and then we will apply them both through a configuration class. </p>
<p>This filter will check the existence and validity of the access token on the Authorization header. We will specify which endpoints will be subject to this filter in our configuration class.</p>
<h3 id="heading-authorization-filter">Authorization Filter</h3>


<p>The <strong>doFilterInternal</strong> method intercepts the requests then checks the Authorization header. If the header is not present or doesn’t start with “BEARER”, it proceeds to the filter chain. </p>
<p>If the header is present, the <strong>getAuthentication</strong> method is invoked. <strong>getAuthentication</strong> verifies the JWT, and if the token is valid, it returns an access token which Spring will use internally. </p>
<p>This new token is then saved to SecurityContext. You can also pass in Authorities to this token if you need for role-based authorization.</p>
<p>Our filters are ready, and now we need to put them into action with the help of a configuration class.</p>
<h3 id="heading-configuration">Configuration</h3>


<p>We annotate this class with <strong>@EnableWebSecurity</strong> and extend <strong>WebSecurityConfigureAdapter</strong> to implement our custom security logic. </p>
<p>We autowire the BCrypt bean that we defined earlier. We also autowire the <strong>UserDetailsService</strong> to find the user’s account. </p>
<p>The most important method is the one which accepts an <strong>HttpSecurity</strong> object. Here we specify the secure endpoints and filters that we want to apply. We configure CORS, and then we permit all post requests to our sign up URL that we defined in the constants class. </p>
<p>You can add other ant matchers to filter based on URL patterns and roles, and you can <a target="_blank" href="https://stackoverflow.com/questions/44067650/spring-security-role-based-access">check</a> this StackOverflow question for examples regarding that. The other method configures the <strong>AuthenticationManager</strong> to use our encoder object as its password encoder while checking the credentials.</p>
<h3 id="heading-testing">Testing</h3>
<p>Let’s send a few requests to test if it works properly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here we send a GET request to access a protected resource. Our server responds with a 403 code. This is the expected behavior because we haven’t provided a token in the header. Now let’s create a user:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To create a user, we send a post request with our User DTO data. We will use this user to login and get an access token.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Great! We got the token. After this point, we will use this token to access protected resources.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/08/7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We provide the token in the Authorization header and we are now allowed access to our protected endpoint.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial I have walked you through the steps I took when implementing JWT authorization and password authentication in Spring. We also learned how to save a user securely. </p>
<p>Thank you for reading – I hope it was helpful to you. If you are interested in reading more content like this, feel free to subscribe to my blog at <a target="_blank" href="https://erinc.io">https://erinc.io</a>. :)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Use Spring Boot and Java to create a Rest API (Tutorial) ]]>
                </title>
                <description>
                    <![CDATA[ Rest APIs are used all over the place. If you are learning the Spring Boot Java-based framework, you will need to know how to create one. We've released a full video course that will teach you how to create a Rest API using Spring Boot. This course f... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/use-spring-boot-and-java-to-create-a-rest-api-tutorial/</link>
                <guid isPermaLink="false">66b206e6a2135cc2539a21f6</guid>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 15 Jul 2020 15:07:17 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/springapi.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Rest APIs are used all over the place. If you are learning the Spring Boot Java-based framework, you will need to know how to create one. We've released a full video course that will teach you how to create a Rest API using Spring Boot.</p>
<p>This course from Pair Learning will also demonstrate how to use PostgreSQL as the relational database and Spring JdbcTemplate for interacting with that. You will learn how to add authentication using JWT (JSON Web Tokens).</p>
<p>Here are the sections in this course:</p>
<ul>
<li>Project Setup &amp; Creating Database Objects</li>
<li>Persisting User Information on Register</li>
<li>Login and Hashing Password</li>
<li>JWT Authentication</li>
<li>Adding New Categories</li>
<li>Category - Find &amp; Update Functionality</li>
<li>Adding Category Transactions</li>
<li>Transaction - Find and Update</li>
<li>Deleting - Category &amp; Transactions</li>
<li>CORS &amp; Testing from Web Client</li>
<li>Summary and Code</li>
</ul>
<p>You can watch the full course on <a target="_blank" href="https://youtu.be/5VUjP1wMqoE">the freeCodeCamp.org YouTube channel</a> (2 hour watch).</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Spring Boot Tutorial - Learn the popular Java framework ]]>
                </title>
                <description>
                    <![CDATA[ Learn Spring Boot in this full course for beginners from Amigoscode. Spring Boot is an amazing framework for building Java applications. It makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run". This ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/spring-boot-tutorial/</link>
                <guid isPermaLink="false">66b2067639b555ffda8bfeb6</guid>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Fri, 06 Sep 2019 14:53:10 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/09/springboot.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Learn Spring Boot in this full course for beginners from Amigoscode. Spring Boot is an amazing framework for building Java applications. It makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".</p>
<p>This course covers:</p>
<ul>
<li>HTTP: GET, POST, PUT &amp; DELETE</li>
<li>Build an in-memory database</li>
<li>How to structure applications using N Tier Architecture</li>
<li>Auto wire beans with dependency injections</li>
<li>Program to interfaces</li>
<li>Run .jar file so that you can deploy to any server</li>
<li>Use Postman REST Client</li>
<li>and more!</li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/vtPkZShrvXQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>You can watch the <a target="_blank" href="https://www.youtube.com/watch?v=vtPkZShrvXQ">full video on the freeCodeCamp.org YouTube channel</a> (2 hour watch).</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement a Hexagonal Architecture ]]>
                </title>
                <description>
                    <![CDATA[ By Bertil Muth A hexagonal  architecture simplifies deferring or changing technology decisions. You  want to change to a different framework? Write a new adapter. You want  to use a database, instead of storing data in files? Again, write an  adapter... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/implementing-a-hexagonal-architecture/</link>
                <guid isPermaLink="false">66d45dde55db48792eed3f43</guid>
                
                    <category>
                        <![CDATA[ Clean Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Hexagonal Architecture ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ spring-boot ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 19 Jun 2019 21:54:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/06/aluminum-architecture-art-1492232.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Bertil Muth</p>
<p>A hexagonal  architecture simplifies deferring or changing technology decisions. You  want to change to a different framework? Write a new adapter. You want  to use a database, instead of storing data in files? Again, write an  adapter for it.</p>
<p>Draw a boundary around the business logic. The hexagon. Anything inside the hexagon must be free from technology concerns.<br> The  outside of the hexagon talks with the inside only by using interfaces,  called ports. Same the other way around. By changing the implementation  of a port, you change the technology.</p>
<p>Isolating  business logic inside the hexagon has another benefit. It enables  writing fast, stable tests for the business logic. They do not depend on  web technology to drive them, for example.</p>
<p>Here’s  an example diagram. It shows Spring MVC technology as boxes with dotted  lines, ports and adapters as solid boxes, and the hexagon without its  internals:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/grafik.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>An adapter translates between a specific technology and a technology free port. The <code>PoemController</code> adapter on the left receives requests and sends commands to the <code>IReactToCommands</code> port. The <code>PoemController</code> is a regular Spring MVC Controller. Because it actively uses the port, it's called a driver adapter.</p>
<p><code>IReactToCommands</code> is called a driver port. Its implementation is inside the hexagon. It's not shown on the diagram.</p>
<p>On the right side, the <code>SpringMvcPublisher</code> adapter implements the <code>IWriteLines</code> port. This time, the <em>hexagon</em> calls the adapter through the port. That's why <code>SpringMvcPublisher</code> is called a driven adapter. And <code>IWriteLines</code> is called a driven port.</p>
<p>I show you how to implement that application. We go all the way from a  user story to a domain model inside the hexagon. We start with a simple  version of the application that prints to the console. Then we switch  to Spring Boot and Spring MVC.</p>
<h2 id="heading-from-a-user-story-to-ports-amp-adapters">From a user story to ports &amp; adapters</h2>
<p>The company FooBars.io decides to build a Poetry App. The product owner and the developers agree on the following user story:</p>
<p>As a reader<br>I want to read at least one poem each day<br>So that I thrive as a human being</p>
<p>As acceptance criteria, the team agrees on:</p>
<ul>
<li>When the user asks for a poem in a specific language, the system displays a random poem in that language in the console</li>
<li>It's ok to "simulate" the user at first, i.e. no real user interaction. (This will change in future versions.)</li>
<li>Supported languages: English, German</li>
</ul>
<p>The developers meet and draw the following diagram:</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4a_F9pCz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/02hr6f652yran0dz38h1.PNG" alt="poem-hexagon" width="600" height="400" loading="lazy"></p>
<p>So the <code>SimulatedUser</code> sends commands to the <code>IReactToCommands</code> port. It asks for poems in English and German. Here's the code, it's available on <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon">Github</a>.</p>
<p>_poem/simple/driver_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/driver_adapter/SimulatedUser.java">SimulatedUser.java</a>_</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">SimulatedUser</span> </span>{
    <span class="hljs-keyword">private</span> IReactToCommands driverPort;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SimulatedUser</span><span class="hljs-params">(IReactToCommands driverPort)</span> </span>{
        <span class="hljs-keyword">this</span>.driverPort = driverPort;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{
        driverPort.reactTo(<span class="hljs-keyword">new</span> AskForPoem(<span class="hljs-string">"en"</span>));
        driverPort.reactTo(<span class="hljs-keyword">new</span> AskForPoem(<span class="hljs-string">"de"</span>));
    }
}
</code></pre>
<p>The <code>IReactToCommands</code> port has only one method to receive any kind of command.</p>
<p>_poem/boundary/driver_port/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/driver_port/IReactToCommands.java">IReactToCommands.java</a>_</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">IReactToCommands</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">reactTo</span><span class="hljs-params">(Object command)</span></span>;
}
</code></pre>
<p><code>AskForPoem</code> is the command. Instances are simple, immutable POJOs. They carry the language of the requested poem.</p>
<p><em>poem/command/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/command/AskForPoem.java">AskForPoem.java</a></em></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">AskForPoem</span> </span>{
    <span class="hljs-keyword">private</span> String language;

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

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getLanguage</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> language;
    }
}
</code></pre>
<p>And that's it for the left, driver side of the hexagon. On to the right, driven side.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cMUjGG4H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8vsbpug5fjfjzs8sfs2y.PNG" alt="poem-hexagon: driven side up next" width="600" height="400" loading="lazy"></p>
<p>When the <code>SimulatedUser</code> asks the <code>IReactToCommands</code> port for a poem, the hexagon:</p>
<ol>
<li>Contacts the <code>IObtainPoems</code> port for a collection of poems</li>
<li>Picks a random poem from the collection</li>
<li>Tells the <code>IWriteLines</code> port to write the poem to the output device</li>
</ol>
<p>You can't see Step 2 yet. It happens inside the hexagon, in the  domain model. That's the business logic of the example. So we focus on  Step 1 and Step 3 first.</p>
<p>In Step 1, the collection of poems is a language dependent, hard coded array. It's provided by the <code>HardcodedPoemLibrary</code> adapter that implements the <code>IObtainPoems</code> port.</p>
<p>_poem/boundary/driven_port/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/driven_port/IObtainPoems.java">IObtainPoems.java</a>_</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">IObtainPoems</span> </span>{
    String[] getMePoems(String language);
}
</code></pre>
<p>_poem/simple/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/driven_adapter/HardcodedPoemLibrary.java">HardcodedPoemLibrary.java</a>_</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">HardcodedPoemLibrary</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IObtainPoems</span> </span>{
    <span class="hljs-keyword">public</span> String[] getMePoems(String language) {
        <span class="hljs-keyword">if</span> (<span class="hljs-string">"de"</span>.equals(language)) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> String[] { <span class="hljs-comment">/* Omitted for brevity */</span> };
        } <span class="hljs-keyword">else</span> { 
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> String[] { <span class="hljs-comment">/* Omitted for brevity */</span> };
        }
    }
}
</code></pre>
<p>In Step 3, the <code>ConsoleWriter</code> adapter writes the lines of the poems to the output device, i.e. the console.</p>
<p>_poem/boundary/driven_port/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/driven_port/IWriteLines.java">IWriteLines.java</a>_</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">IWriteLines</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">writeLines</span><span class="hljs-params">(String[] strings)</span></span>;
}
</code></pre>
<p>_poem/simple/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/driven_adapter/ConsoleWriter.java">ConsoleWriter.java</a>_</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">ConsoleWriter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IWriteLines</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">writeLines</span><span class="hljs-params">(String[] lines)</span> </span>{
        Objects.requireNonNull(lines);
        <span class="hljs-keyword">for</span> (String line : lines) {
            System.out.println(line);
        }
        System.out.println(<span class="hljs-string">""</span>);
    }
}
</code></pre>
<p>We have created all the ports, and a simple implementation of all the  adapters. So far, the inside of the hexagon remained a mystery. It's up  next.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s---tA0dZqp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/efcfrsrwb9jei5uik63k.PNG" alt="poem-hexagon: inside up next" width="600" height="400" loading="lazy"></p>
<h1 id="heading-command-handlers-inside-the-hexagon">Command handlers (inside the hexagon)</h1>
<p>When a user asks for a poem, the system displays a random poem.<br>Similar in the code: when the <code>IReactToCommands</code> port receives an <code>AskForPoem</code>command, the hexagon calls a <code>DisplayRandomPoem</code> command handler.</p>
<p>The <code>DisplayRandomPoem</code> command handler obtains a list of  poems, picks a random one and writes it to the output device. This is  exactly the list of steps we talked about in the last clause.</p>
<p>_poem/boundary/internal/command_handler/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/internal/command_handler/DisplayRandomPoem.java">DisplayRandomPoem.java</a>_</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">DisplayRandomPoem</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Consumer</span>&lt;<span class="hljs-title">AskForPoem</span>&gt; </span>{
        <span class="hljs-comment">/* Omitted for brevity */</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">accept</span><span class="hljs-params">(AskForPoem askForPoem)</span> </span>{
        List&lt;Poem&gt; poems = obtainPoems(askForPoem);
        Optional&lt;Poem&gt; poem = pickRandomPoem(poems);
        writeLines(poem);   
    }

        <span class="hljs-comment">/* Rest of class omitted for brevity */</span>
}
</code></pre>
<p>It's also the job of the command handler to translate between the domain model data and the data used in the port interfaces.</p>
<h1 id="heading-tying-commands-to-command-handlers">Tying commands to command handlers</h1>
<p>In my implementation of a hexagonal architecture, there is only a single driver port, <code>IReactToCommands</code>. It reacts to all types of commands.</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">IReactToCommands</span></span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">reactTo</span><span class="hljs-params">(Object command)</span></span>;
}
</code></pre>
<p>The <code>Boundary</code> class is the implementation of the <code>IReactToCommands</code> port. It creates a behavior model using a <a target="_blank" href="https://github.com/bertilmuth/requirementsascode">library</a>. The behavior model maps each command type to a command handler. Then, a behavior dispatches the commands based on the behavior model.</p>
<p><em>poem/boundary/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/Boundary.java">Boundary.java</a></em></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">Boundary</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IReactToCommands</span>, <span class="hljs-title">BehaviorModel</span> </span>{
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> IObtainPoems poemObtainer;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> IWriteLines lineWriter;
  <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> StatelessBehavior behavior;

  <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Class&lt;AskForPoem&gt; asksForPoem = AskForPoem.class;

  <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Boundary</span><span class="hljs-params">(IObtainPoems poemObtainer, IWriteLines lineWriter)</span> </span>{
    <span class="hljs-keyword">this</span>.poemObtainer = poemObtainer;
    <span class="hljs-keyword">this</span>.lineWriter = lineWriter;
    <span class="hljs-keyword">this</span>.behavior = StatelessBehavior.of(<span class="hljs-keyword">this</span>);
  }

  <span class="hljs-meta">@Override</span>
  <span class="hljs-function"><span class="hljs-keyword">public</span> Model <span class="hljs-title">model</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> Model.builder()
        .user(asksForPoem).system(displaysRandomPoem())
        .build();
  }

  <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">reactTo</span><span class="hljs-params">(Object commandObject)</span> </span>{
    behavior.reactTo(commandObject);
  }

  <span class="hljs-function"><span class="hljs-keyword">private</span> Consumer&lt;AskForPoem&gt; <span class="hljs-title">displaysRandomPoem</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> DisplayRandomPoem(poemObtainer, lineWriter);
  }
}
</code></pre>
<h1 id="heading-the-domain-model">The domain model</h1>
<p>The domain model of the example doesn’t have very interesting functionality. The <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/internal/domain/RandomPoemPicker.java">RandomPoemPicker</a> picks a random poem from a list.</p>
<p>A <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/boundary/internal/domain/Poem.java">Poem</a> has a constructor that takes a String containing line separators, and splits it into verses.</p>
<p>The really interesting bit about the example domain model: it doesn’t  refer to a database or any other technology, not even by interface!</p>
<p>That means that you can test the domain model with <a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/test/java/poem/boundary/internal/domain/RandomPoemPickerTest.java">plain unit tests</a>. You don’t need to mock anything.</p>
<p>Such a pure domain model is not a necessary property of an  application implementing a hexagonal architecture. But I like the  decoupling and testability it provides.</p>
<h1 id="heading-plug-adapters-into-ports-and-thats-it">Plug adapters into ports, and that's it</h1>
<p>A final step remains to make the application work. The application  needs a main class that creates the driven adapters. It injects them  into the boundary.<br>It then creates the driver adapter,  for the boundary, and runs it.</p>
<p><em>poem/simple/<a target="_blank" href="https://github.com/bertilmuth/poem-hexagon/blob/master/src/main/java/poem/simple/Main.java">Main.java</a></em></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">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">new</span> Main().startApplication();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startApplication</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Instantiate driven, right-side adapters</span>
        HardcodedPoemLibrary poemLibrary = <span class="hljs-keyword">new</span> HardcodedPoemLibrary();
        ConsoleWriter consoleWriter = <span class="hljs-keyword">new</span> ConsoleWriter();

        <span class="hljs-comment">// Inject driven adapters into boundary</span>
        Boundary boundary = <span class="hljs-keyword">new</span> Boundary(poemLibrary, consoleWriter);

        <span class="hljs-comment">// Start the driver adapter for the application</span>
        <span class="hljs-keyword">new</span> SimulatedUser(boundary).run();
    }
}
</code></pre>
<p>And that's it! The team shows the result to the product owner. And  she's happy with the progress. Time for a little celebration.</p>
<p><img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PDHorQ0r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6pe5yam3xe68m11bojff.PNG" alt="hexagon-poem the completed application" width="600" height="400" loading="lazy"></p>
<h1 id="heading-switching-to-spring">Switching to Spring</h1>
<p>The team decides to turn the poem app into a web application. And to  store poems in a real database. They agree to use the Spring framework  to implement it.<br>Before they start coding, the team meets and draws the following diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/04/grafik-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Instead of a <code>SimulatedUser</code>, there is a <code>PoemController</code> now, that sends commands to the hexagon.</p>
<p>_poem/springboot/driver_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/driver_adapter/PoemController.java">PoemController.java</a>_</p>
<pre><code class="lang-java"><span class="hljs-meta">@Controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PoemController</span> </span>{
    <span class="hljs-keyword">private</span> SpringMvcBoundary springMvcBoundary;

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

    <span class="hljs-meta">@GetMapping("/askForPoem")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">askForPoem</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(name = "lang", required = false, defaultValue = "en")</span> String language,
            Model webModel)</span> </span>{
        springMvcBoundary.basedOn(webModel).reactTo(<span class="hljs-keyword">new</span> AskForPoem(language));

        <span class="hljs-keyword">return</span> <span class="hljs-string">"poemView"</span>;
    }
}
</code></pre>
<p>When receiving a command, the <code>PoemController</code> calls <code>springMvcBoundary.basedOn(webModel)</code>. This creates a new <code>Boundary</code> instance, based on the <code>webModel</code> of the request:</p>
<p><em>poem/springboot/boundary/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/boundary/SpringMvcBoundary.java">SpringMvcBoundary.java</a></em></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">SpringMvcBoundary</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> IObtainPoems poemObtainer;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SpringMvcBoundary</span><span class="hljs-params">(IObtainPoems poemObtainer)</span> </span>{
        <span class="hljs-keyword">this</span>.poemObtainer = poemObtainer;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> IReactToCommands <span class="hljs-title">basedOn</span><span class="hljs-params">(Model webModel)</span> </span>{
        SpringMvcPublisher webPublisher = <span class="hljs-keyword">new</span> SpringMvcPublisher(webModel);
        IReactToCommands boundary = <span class="hljs-keyword">new</span> Boundary(poemObtainer, webPublisher);
        <span class="hljs-keyword">return</span> boundary;
    }
}
</code></pre>
<p>The call to <code>reactTo()</code> sends the command to the boundary, as before. On the right side of the hexagon, the <code>SpringMvcPublisher</code> adds an attribute <code>lines</code> to the Spring MVC model. That's the value Thymeleaf uses to insert the lines into the web page.</p>
<p>_poem/springboot/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/driven_adapter/SpringMvcPublisher.java">SpringMvcPublisher.java</a>_</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">SpringMvcPublisher</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IWriteLines</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String LINES_ATTRIBUTE = <span class="hljs-string">"lines"</span>;

    <span class="hljs-keyword">private</span> Model webModel;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SpringMvcPublisher</span><span class="hljs-params">(Model webModel)</span> </span>{
        <span class="hljs-keyword">this</span>.webModel = webModel;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">writeLines</span><span class="hljs-params">(String[] lines)</span> </span>{
        Objects.requireNonNull(lines);
        webModel.addAttribute(LINES_ATTRIBUTE, lines);
    }
}
</code></pre>
<p>The team also implements a <code>PoemRepositoryAdapter</code> to access the <code>PoemRepository</code>. The adapter gets the <code>Poem</code> objects from the database. It returns the texts of all poems as a String array.</p>
<p>_poem/springboot/driven_adapter/<a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/driven_adapter/PoemRepositoryAdapter.java">PoemRepositoryAdapter.java</a>_</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">PoemRepositoryAdapter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">IObtainPoems</span> </span>{
    <span class="hljs-keyword">private</span> PoemRepository poemRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PoemRepositoryAdapter</span><span class="hljs-params">(PoemRepository poemRepository)</span> </span>{
        <span class="hljs-keyword">this</span>.poemRepository = poemRepository;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> String[] getMePoems(String language) {
        Collection&lt;Poem&gt; poems = poemRepository.findByLanguage(language);
        <span class="hljs-keyword">final</span> String[] poemsArray = poems.stream()
            .map(p -&gt; p.getText())
            .collect(Collectors.toList())
            .toArray(<span class="hljs-keyword">new</span> String[<span class="hljs-number">0</span>]);
        <span class="hljs-keyword">return</span> poemsArray;
    }
}
</code></pre>
<p>Finally, the team implements the <a target="_blank" href="https://github.com/bertilmuth/poem-springboot/blob/master/src/main/java/poem/springboot/Application.java">Application</a> class that sets up an example repository and plugs the adapters into the ports.</p>
<p>And that's it. The switch to Spring is complete.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>There are many ways to implement a hexagonal architecture. I showed  you a straightforward approach that provides an easy to use, command  driven API for the hexagon. It reduces the number of interfaces you need  to implement. And it leads to a pure domain model.</p>
<p>If you want to get more information on the topic, read <a target="_blank" href="http://archive.is/5j2NI">Alistair Cockburn’s original article on the subject</a>.</p>
<p>The example in this article is inspired by a three part series of <a target="_blank" href="https://www.youtube.com/playlist?list=PLGl1Jc8ErU1w27y8-7Gdcloy1tHO7NriL">talks</a> by Alistair Cockburn on the subject.</p>
<p><em>Last updated on 30 July 2021.__. If you want to keep up with what I’m doing or drop me a note, follow me on</em> <a target="_blank" href="https://dev.to/bertilmuth"><em>dev.to</em></a><em>,</em> <a target="_blank" href="https://www.linkedin.com/in/bertilmuth/"><em>LinkedIn</em></a> <em>or</em> <a target="_blank" href="https://twitter.com/BertilMuth"><em>Twitter</em></a><em>. Or visit my</em> <a target="_blank" href="https://github.com/bertilmuth/requirementsascode"><em>GitHub project</em></a><em>. To learn about agile software development,</em> <a target="_blank" href="https://skl.sh/2Cq497P"><em>visit my online course</em></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
