Featured resource
pluralsight tech forecast
2025 Tech Forecast

Which technologies will dominate in 2025? And what skills do you need to keep up?

Check it out
Hamburger Icon
  • Labs icon Lab
  • Core Tech
Labs

Guided: Building an Auction Application with Spring Framework 6

This lab is designed to be a step-by-step guide, starting with the basics of Spring Framework and gradually moving to more complex concepts. By the end of this lab, you'll will have a solid understanding of how to build an application using Spring Framework 6. You will also have a working auction application that you can use as a reference for future projects. If you are looking to deepen your understanding of the Spring Framework and gain practical experience in building web applications in Spring this lab is a great resource.

Labs

Path Info

Level
Clock icon Intermediate
Duration
Clock icon 45m
Published
Clock icon Nov 01, 2023

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    In this Lab, you'll build a comprehensive Spring Boot application for an auction system. Starting with the AuctionApplication class as your foundation, you'll define the Item entity class that represents an auction item in a Java Persistence API (JPA) repository. You'll also create a CrudRepository interface to handle CRUD operations for your Item entity.

    Next, you'll construct two Spring MVC Controllers: ItemController for fetching items and populating the model, and AdminController for managing administrative tasks for items.

    Finally, you'll create Thymeleaf templates to dynamically render your list of auction items (index.html), present an admin view with functionalities (admin.html), and provide a form for creating or editing items (form.html). This Lab will give you a thorough understanding of building a functional Spring Boot application, combining Spring MVC, Spring Data, and Thymeleaf templates.

    Running the Application: This project uses gradle so to run the application use the command gradle bootrun in the Terminal. There may be some points where you run into compiler errors that will prevent the application from starting. If that happens check the solutions. Once the application is running it can be view in the Web Browser tab.

  2. Challenge

    Application Class

    The AuctionApplication class lies at the heart of your Spring Boot application. Annoted with @SpringBootApplication, this class seamlessly configures Spring for you while enabling component scanning. The SpringApplication class from the Spring Boot framework is your key to bootstrapping a Spring application from a Java main method. To run your application, simply call the run() method from the SpringApplication class. This nifty method returns a ConfigurableApplicationContext that you can tuck away for later use.

    Relevant File: /src/main/java/com/pluralsight/auction/AuctionApplication.java

    Instructions

    1. Import the SpringApplication Class: Import the SpringApplication class from the Spring Boot framework. This class is used to bootstrap and launch a Spring application from a Java main method.
    2. Run the Application: Start the Spring application. This is done by calling the static method run() from the SpringApplication class. This method returns a ConfigurableApplicationContext that you can use later if needed. But for now, just start the application by passing two arguments to the run() method.
    📝 Notes The `SpringBootApplication` annotation is a convenience annotation that adds all of the following: - `@Configuration`: Tags the class as a source of bean definitions for the application context. - `@EnableAutoConfiguration`: Tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings. - `@ComponentScan`: Tells Spring to look for other components, configurations, and services in the `com.pluralsight.auction` package.

    The `main()` method uses Spring Boot’s `SpringApplication.run()` method to launch an application. This is the entry point of our Spring Boot application.

    There is no web server configuration required, no XML configuration, and no need to even unpack a WAR file. Spring Boot takes an opinionated view of the Spring platform and third-party libraries, letting you get started with minimum fuss.
    🔑 Solution
    
    package com.pluralsight.auction;
    

    import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

    @SpringBootApplication public class AuctionApplication {

    public static void main(String[] args) {
        SpringApplication.run(AuctionApplication.class, args);
    }
    

    }



  3. Challenge

    Item Entity Class

    The Item entity class is a crucial part of your auction setup, serving as an Entity class for a JPA (Java Persistence API) repository. This class represents an auction item, complete with properties like name, description, seller, price, and reserve. To access these properties, you'll equip your class with getters and setters. Plus, you'll design a constructor that accepts parameters for each property, making it a breeze to create new Item instances.

    Relevant File: /src/main/java/com/pluralsight/auction/Item.java

    Instructions

    1. Define Properties: Define the properties for the Item entity. These properties should include name, description, seller, price, and reserve. Remember to specify the correct data types for each property.
    2. Create Getters and Setters: After defining the properties, your next task is to create getters and setters for each property. These methods will allow other parts of your code to read (get) or modify (set) the values of your properties.
    3. Define a Parameterized Constructor: Finally, you should define a constructor that accepts parameters for each property (except the id, which is automatically generated). This constructor will make it easy to create new Item instances with specific values.
    📝 Notes The `@Entity` annotation indicates that this class is an entity. This is a JPA-specific annotation which denotes the whole class for storage in a relational table.

    The `@Id` annotation is JPA's way of indicating the primary key of the entity.

    The `@GeneratedValue` annotation is used to specify how the primary key should be generated. The `GenerationType.IDENTITY` strategy means that the persistence provider must assign primary keys for the entity using a database identity column.

    Getters and setters are used in Java to provide encapsulation. They are used to set and get the values of private fields.

    A parameterized constructor allows you to initialize an object with specific values at the time of its creation. If you don't provide any constructor, Java compiler provides a default one for you, but it does not allow you to set initial values. Therefore, it's often helpful to create a parameterized constructor when you need more control over your object's initialization.
    🔑 Solution
    
    package com.pluralsight.auction;
    

    import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id;

    @Entity public class Item { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String description; private String seller; private double price; private double reserve;

    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    public String getSeller() {
        return seller;
    }
    
    public void setSeller(String seller) {
        this.seller = seller;
    }
    
    public double getPrice() {
        return price;
    }
    
    public void setPrice(double price) {
        this.price = price;
    }
    
    public double getReserve() {
        return reserve;
    }
    
    public void setReserve(double reserve) {
        this.reserve = reserve;
    }
    
    public Item(String name, String description, String seller, double price, double reserve) {
        this.name = name;
        this.description = description;
        this.seller = seller;
        this.price = price;
        this.reserve = reserve;
    }
    
    public Item() {
    }
    

    }

  4. Challenge

    Spring Data CrudRepository Interface

    In this step, you'll be crafting a Spring Data repository interface that can handle the CRUD operations for your Item entity. The CrudRepository interface from Spring Data is your ticket to these operations, and your ItemRepository interface will extend this, specifying Item and Long as the type parameters.

    Relevant File: /src/main/java/com/pluralsight/auction/ItemRepository.java

    Instructions

    1. Import the CrudRepository Interface: Import the CrudRepository interface from Spring Data. This interface provides several methods for common CRUD operations. You can do this by typing import org.springframework.data.repository.CrudRepository; at the top of your file.
    2. Define the ItemRepository Interface: Define an interface named ItemRepository. This interface should extend CrudRepository, which requires two type parameters: the entity class and the type of the entity ID. In this case, you'll use Item and Long.
    📝 Notes The `CrudRepository` interface provides sophisticated CRUD functionality for the entity class that is being managed. This interface is a part of Spring Data repository abstraction that makes it easy to connect your application to a relational database.

    The methods provided by `CrudRepository` include: - `save(…)`: Save an entity. - `findOne(…)`: Find an entity by its primary key. - `findAll(…)`: Find all entities. - `count(…)`: Return the number of entities. - `delete(…)`: Delete an entity.

    By creating a repository interface that extends `CrudRepository`, Spring is able to automatically create a concrete class that implements those methods. This process is called "auto implementation". The details of how this works are hidden away, so you can focus on writing the rest of your application.
    🔑 Solution
    
    package com.pluralsight.auction;
    

    import org.springframework.data.repository.CrudRepository;

    public interface ItemRepository extends CrudRepository<Item, Long> { }

  5. Challenge

    Item Controller

    Next, you'll build a Spring MVC Controller that utilizes the ItemRepository to fetch items. It then populates the model with these items for rendering in the view. To achieve this, you'll rely on the Autowired, Model, GetMapping, and the ItemRepository classes and interfaces.

    Relevant File: /src/main/java/com/pluralsight/auction/ItemController.java

    Instructions

    1. Import Required Classes: Import all the required classes and interfaces. These include Autowired, Model, GetMapping, and the ItemRepository interface that you created in the previous module.
    2. Inject the ItemRepository: Use dependency injection to get an instance of ItemRepository. You can use the @Autowired annotation to do this. Also, create a constructor to set the ItemRepository instance to a class level variable.
    3. Define the listItems Method: Define a method named listItems that will handle GET requests at the root URL ("/"). This method should use the ItemRepository to fetch all items, add them to the model, and then return the name of the view that should be rendered ("index").
    📝Notes The `@Controller` annotation indicates that this class is a Spring MVC controller. Spring MVC controllers handle incoming HTTP requests.

    The `@Autowired` annotation is used for dependency injection. In this case, it's injecting an instance of `ItemRepository` into the `ItemController`.

    The `@GetMapping` annotation is a composed annotation that acts as a shortcut for `@RequestMapping(method = RequestMethod.GET)`. In this case, it's mapping HTTP GET requests for the root URL ("/") to the `listItems` method.

    The `Model` is essentially a map that holds data that should be displayed in the view. In this case, you're adding all items from the `ItemRepository` to the model, under the attribute name "items". This attribute can then be used in the view to display the items.

    Finally, the `listItems` method returns the name of the view that should be rendered. In this case, it's returning "index", which means that Spring MVC will look for a view named "index" (e.g., "`index.html`" or "`index.jsp`").
    🔑 Solution
    
    package com.pluralsight.auction;
    

    import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping;

    @Controller public class ItemController { @Autowired private final ItemRepository itemRepository;

    public ItemController(ItemRepository itemRepository) {
        this.itemRepository = itemRepository;
    }
    
    @GetMapping("/")
    public String listItems(Model model) {
        model.addAttribute("items", itemRepository.findAll());
        return "index";
    }
    

    }

  6. Challenge

    Thymeleaf template: `index.html`

    In this step, you'll create a Thymeleaf template named index.html that will serve as the canvas for rendering our list of auction items. The body of this page will house a <main> element, within which you'll nest a <section>. This section will then generate an <article> for each item in the items attribute of the model.

    Relevant File: /src/main/resources/templates/index.html

    Instructions

    1. Create the Main Content Area: In the body of the page, create a <main> element. Inside this element, create a <section>.
    2. Display the Auction Items: In the section, create an <article> for each item in the items attribute of the model (which was set in the ItemController). For each article:
      • Display the item's name in a <h3>.
      • Display the item's description in a <p>.
      • Display the item's price and seller in a <footer>. Use the th:utext attribute to generate the content.
    📝 Notes Thymeleaf is a Java-based templating engine used in web development. It provides a way to dynamically generate HTML content based on data from your application.

    The `th:each` attribute is used to loop over a collection of objects. In this case, it's looping over the `items` attribute of the model.

    The `th:text` and `th:utext` attributes are used to add dynamic content to an element. `th:text` escapes HTML special characters, while `th:utext` does not. In this case, they're used to display the name, description, price, and seller of each item.

    The `th:href` attribute is used to generate URLs. In this case, it's used to link to the CSS file.

    The `${...}` syntax is used to evaluate expressions. In this case, it's used to access the properties of each item.

    The `@{...}` syntax is used to generate URLs. In this case, it's used to generate the URL for the CSS file.

    This task helps learners understand how Thymeleaf can be used to generate dynamic HTML content based on data from a Spring MVC controller.
    🔑 Solution

    ```html Auction Items

    Auction Items

    ```

  7. Challenge

    Admin Controller

    Now, you'll put together a Spring MVC Controller named AdminController. This controller will oversee administrative tasks for items, including listing all items, creating a new item, saving an item, editing an item, and deleting an item.

    Relevant File: /src/main/java/com/pluralsight/auction/AdminController.java

    Instructions

    1. Import Required Classes: Import all the required classes and interfaces. These include Autowired, Model, ModelAttribute, PathVariable, GetMapping, PostMapping, and the ItemRepository interface that you created in the previous step.
    2. Inject the ItemRepository: Use the @Autowired annotation to get an instance of ItemRepository. Also, create a constructor to set the ItemRepository instance to a class level variable.
    3. Define Controller Methods: Define the following methods:
      • listItems: Handles GET requests at the "/admin" URL, fetches all items, and adds them to the model.
      • newItem: Handles GET requests at the "/admin/new" URL, creates a new Item instance, adds it to the model and renders the form.html template.
      • saveItem: Handles POST requests at the "/admin/save" URL, saves an item to the repository, and redirects to the "/admin" URL.
      • editItem: Handles GET requests at the "/admin/edit/{id}" URL, fetches an item by its ID, adds it to the model and renders the form.html template.
      • deleteItem: Handles GET requests at the "/admin/delete/{id}" URL, deletes an item by its ID, and redirects to the "/admin" URL.
    📝 Notes The `@Controller` annotation indicates that this class is a Spring MVC controller. Spring MVC controllers handle incoming HTTP requests.

    The `@Autowired` annotation is used for dependency injection. In this case, it's injecting an instance of `ItemRepository` into the `AdminController`.

    The `@GetMapping` and `@PostMapping` annotations are used to map HTTP GET and POST requests to specific methods.

    The `@ModelAttribute` annotation binds a method parameter to a model attribute. In this case, it's binding the `item` parameter to an attribute in the model.

    The `@PathVariable` annotation indicates that a method parameter should be bound to a URI template variable. In this case, it's binding the `id` parameter to the `{id}` variable in the URL.

    The `Model` is essentially a map that holds data that should be displayed in the view. It's being used here to hold the items that should be displayed, as well as the item that should be edited or saved.

    The methods in this controller return the name of the view that should be rendered, or they redirect to a specific URL. For example, the `listItems` method returns "admin", which means that Spring MVC will look for a view template named `admin.html`. The `saveItem` and `deleteItem` methods return "redirect:/admin", which makes the browser send a new GET request to the "/admin" URL. The `newItem` and `editItem` methods return `“form”` which will look for a view template called `form.html`.
    🔑 Solution
    
    package com.pluralsight.auction;
    

    import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping;

    @Controller public class AdminController { @Autowired private final ItemRepository itemRepository;

    public AdminController(ItemRepository itemRepository) {
        this.itemRepository = itemRepository;
    }
    
    @GetMapping({
        "/admin",
        "/admin/"
    })
    public String listItems(Model model) {
        model.addAttribute("items", itemRepository.findAll());
        return "admin";
    }
    
    @GetMapping({
        "/admin/new",
        "/admin/new/"
    })
    public String newItem(Model model) {
        model.addAttribute("item", new Item());
        return "form";
    }
    
    @PostMapping({
        "/admin/save",
        "/admin/save/"
    })
    public String saveItem(@ModelAttribute Item item) {
        itemRepository.save(item);
        return "redirect:/admin";
    }
    
    @GetMapping({
        "/admin/edit/{id}",
        "/admin/edit/{id}/"
    })
    public String editItem(@PathVariable Long id, Model model) {
        model.addAttribute("item", itemRepository.findById(id).orElse(null));
        return "form";
    }
    
    @GetMapping({
        "/admin/delete/{id}",
        "/admin/delete/{id}/"
    })
    public String deleteItem(@PathVariable Long id) {
        itemRepository.deleteById(id);
        return "redirect:/admin";
    }
    

    }

  8. Challenge

    Thymeleaf template: `admin.html`

    Here, you'll construct a Thymeleaf template that presents auction items in a table format for an admin view. This view will provide additional functionalities like creating a new item and editing or deleting existing items.

    Relevant File: /src/main/resources/templates/admin.html

    Instructions

    1. Create a Table to Display the Auction Items: Add a table. The table should have headers for ID, Name, Price, Reserve, Seller, and an empty header for actions.
    2. Add a Link to Create a New Item: Above the table, add a link that navigates to "/admin/new" to create a new auction item.
    3. Display the Auction Items in the Table: In the table body, create a row for each item in the items attribute of the model. For each row:
      • Display the item's ID, name, price, reserve, and seller in separate cells.
      • In the last cell, add links to edit and delete the item. The edit link should navigate to "/admin/edit/{id}", and the delete link should navigate to "/admin/delete/{id}". The {id} in the URLs should be replaced with the item's ID.

    In order for the form to work you will need to click on the icon in the upper right of the web browser to open the page in an external tab.

    📝 Notes The `>table>`, `>thead>`, `>tbody>`, `>tr>`, `>th>`, and `>td>` elements are used to create a table. The table header (`>thead>`) contains the headers (`>th>`), and the table body (`>tbody>`) contains the rows (``) and cells (`>td>`).

    The `>a>` element is used to create hyperlinks. In this case, it's used to create links to create, edit, and delete items.

    The `th:href` attribute is used to generate URLs. In this case, it's used to generate the URLs for the edit and delete links. The `@{/admin/edit/{id}(id=${item.id})}` syntax generates a URL with the item's ID in place of `{id}`.

    The `th:each` attribute is used to loop over a collection of objects. In this case, it's looping over the `items` attribute of the model.

    The `th:text` attribute is used to add dynamic content to an element. In this case, it's used to display the ID, name, price, reserve, and seller of each item.
    🔑 Solution

    ```html Auction Items

    Auction Items

    New
    ID Name Price Reserve Seller
    Edit Delete
    ```

  9. Challenge

    Thymeleaf template: `form.html`

    In your final step, you'll create a Thymeleaf template for an auction item form. This form will give users the ability to create a new item or edit an existing one.

    Relevant File: /src/main/resources/templates/form.html

    Instructions

    1. Create the Form
      • In the body of the page, create a <main> element. Inside this element, create a <section>.
      • In the section, create a <form> with the action set to "/admin/save" and the method set to "post". The form should use the item attribute of the model as the object.
    2. Add Input Fields to the Form
      • In the form, add input fields for the item's ID, name, price, reserve, description, and seller. Use the th:field attribute to bind each input field to a property of the item.
      • The ID field should be a hidden input field.
      • Each input field (except for the ID field) should be wrapped in a <label>.
    3. Add Buttons to the Form
      • At the bottom of the form, add a submit button with the text "Save".
      • Next to the submit button, add a link with the text "Cancel". The link should navigate back to the admin page.

    When submit the form you may receive an error message that says This content is blocked. Contact the site owner to fix the issue.. This is a function of the form being submit in an iframe. If you refresh you should see the changes.

    📝 Notes The `
    ` element is used to create a form. The `th:action` attribute is used to set the URL that the form will be submitted to, and the `th:object` attribute is used to bind the form to an object.

    The `` element is used to create input fields. The `type` attribute is used to set the type of the input field, the `id` and `name` attributes are used to identify the input field, and the `th:field` attribute is used to bind the input field to a property of the object.

    The `
    🔑 Solution

    ```html Auction Items

    Auction Items

    New
    ID Name Price Reserve Seller
    Edit Delete
    ```

  10. Challenge

    Completion

    Congratulations 🎉, on successfully completing this Spring Lab! You've taken important steps in your journey to learn Spring Boot.

    Throughout the lab, you've built a complete auction system, starting from the ground up with the AuctionApplication class, moving to defining the Item entity class, and setting up a CrudRepository interface to handle CRUD operations.

    You've also gotten hands-on experience with building Spring MVC Controllers, specifically the ItemController and AdminController, each with its own responsibilities in managing auction items.

    Moreover, you've learned how to create dynamic Thymeleaf templates for various views, such as listing auction items (index.html), presenting an admin view with functionalities (admin.html), and providing a form for creating or editing items (form.html).

    These skills are not only critical for building Spring applications but also lay a strong foundation for your journey in Java web development. Well done on your achievement and keep up the good work!

Tom is a staff author at Pluralsight helping to develop Hands-On content. Tom's background in software development, UI/UX, and instructional design was developed over the years while working as a faculty member at the School of Computing at Weber State University in Utah, and continues to grow as he develops Projects and Labs for Pluralsight. When he's not creating content to allow learners to gain real-life experience, he enjoys spending time with his family.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.