<?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 security - 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 security - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 25 Jun 2026 10:02:44 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/spring-security/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <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 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>
        
    </channel>
</rss>
