- Lab
- Core Tech

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.

Path Info
Table of Contents
-
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 theItem
entity class that represents an auction item in a Java Persistence API (JPA) repository. You'll also create aCrudRepository
interface to handle CRUD operations for yourItem
entity.Next, you'll construct two Spring MVC Controllers:
ItemController
for fetching items and populating the model, andAdminController
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. -
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. TheSpringApplication
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 therun()
method from theSpringApplication
class. This nifty method returns aConfigurableApplicationContext
that you can tuck away for later use.Relevant File: /src/main/java/com/pluralsight/auction/AuctionApplication.java
Instructions
- 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. - Run the Application: Start the Spring application. This is done by calling the static method
run()
from theSpringApplication
class. This method returns aConfigurableApplicationContext
that you can use later if needed. But for now, just start the application by passing two arguments to therun()
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); }
}
- Import the SpringApplication Class: Import the
-
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 likename
,description
,seller
,price
, andreserve
. 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 newItem
instances.Relevant File: /src/main/java/com/pluralsight/auction/Item.java
Instructions
- Define Properties:
Define the properties for the
Item
entity. These properties should includename
,description
,seller
,price
, andreserve
. Remember to specify the correct data types for each property. - 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.
- 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 newItem
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() { }
}
- Define Properties:
Define the properties for the
-
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. TheCrudRepository
interface from Spring Data is your ticket to these operations, and yourItemRepository
interface will extend this, specifyingItem
andLong
as the type parameters.Relevant File: /src/main/java/com/pluralsight/auction/ItemRepository.java
Instructions
- 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 typingimport org.springframework.data.repository.CrudRepository;
at the top of your file. - Define the ItemRepository Interface: Define an interface named
ItemRepository
. This interface should extendCrudRepository
, which requires two type parameters: the entity class and the type of the entity ID. In this case, you'll useItem
andLong
.
📝 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> { }
- Import the CrudRepository Interface: Import the
-
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 theAutowired
,Model
,GetMapping
, and theItemRepository
classes and interfaces.Relevant File: /src/main/java/com/pluralsight/auction/ItemController.java
Instructions
- Import Required Classes: Import all the required classes and interfaces. These include
Autowired
,Model
,GetMapping
, and theItemRepository
interface that you created in the previous module. - 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 theItemRepository
instance to a class level variable. - Define the listItems Method: Define a method named
listItems
that will handleGET
requests at the root URL ("/"). This method should use theItemRepository
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"; }
}
- Import Required Classes: Import all the required classes and interfaces. These include
-
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 theitems
attribute of the model.Relevant File: /src/main/resources/templates/index.html
Instructions
- Create the Main Content Area: In the body of the page, create a
<main>
element. Inside this element, create a<section>
. - Display the Auction Items: In the section, create an
<article>
for each item in theitems
attribute of the model (which was set in theItemController
). 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 theth:utext
attribute to generate the content.
- Display the item's name in a
📝 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
```htmlAuction Items Auction Items
- Create the Main Content Area: In the body of the page, create a
-
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
- Import Required Classes: Import all the required classes and interfaces. These include
Autowired
,Model
,ModelAttribute
,PathVariable
,GetMapping
,PostMapping
, and theItemRepository
interface that you created in the previous step. - Inject the ItemRepository: Use the
@Autowired
annotation to get an instance ofItemRepository
. Also, create a constructor to set theItemRepository
instance to a class level variable. - Define Controller Methods: Define the following methods:
listItems
: HandlesGET
requests at the "/admin" URL, fetches all items, and adds them to the model.newItem
: HandlesGET
requests at the "/admin/new" URL, creates a newItem
instance, adds it to the model and renders theform.html
template.saveItem
: HandlesPOST
requests at the "/admin/save" URL, saves an item to the repository, and redirects to the "/admin" URL.editItem
: HandlesGET
requests at the "/admin/edit/{id}" URL, fetches an item by its ID, adds it to the model and renders theform.html
template.deleteItem
: HandlesGET
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"; }
}
- Import Required Classes: Import all the required classes and interfaces. These include
-
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
- 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.
- 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.
- 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. -
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
- 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 theitem
attribute of the model as the object.
- In the body of the page, create a
- 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>
.
- In the form, add input fields for the item's ID, name, price, reserve, description, and seller. Use the
- 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 ` - Create the Form
-
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!
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.