# Chapter 3: Building Interactive Web Applications --- ## 3.1 From Display to Interaction In the first two chapters, we built pages that display information — static content, template-rendered layouts, and data passed from controllers through the model. The user could view content, but could not send anything back. A real web application, however, is a conversation: the user submits data, the server processes it, and the application responds accordingly. This chapter introduces the mechanisms that make that conversation possible. We will learn how to handle form submissions, bind form data to Java objects, validate user input on the server side, display validation errors back to the user, handle file uploads, and prevent the duplicate-submission problem with the Post/Redirect/Get pattern. We will also create custom error pages. All form rendering in this chapter uses **Spring's built-in FreeMarker macros** — the `spring.ftl` library we first encountered in Chapter 1 for URL generation. These macros provide form binding, input generation, and error display that integrates directly with Spring MVC's data binding and validation infrastructure. --- ## 3.2 Handling HTTP GET and POST Requests Every interaction with a web application begins with an HTTP request. Two request methods dominate form-based web applications: **GET** requests retrieve data. When you navigate to a URL, click a link, or type an address in the browser bar, a GET request is sent. GET requests should never modify data — they are safe and idempotent. **POST** requests submit data. When you fill in a form and click "Submit," a POST request is sent with the form data in the request body. POST requests typically create or modify a resource on the server. In Spring MVC, handler methods in a `@Controller` class are mapped to specific HTTP methods using `@GetMapping` and `@PostMapping`: ```java @Controller public class ProductController { private final ProductService productService; public ProductController(ProductService productService) { this.productService = productService; } @GetMapping("/products") public String listProducts(Model model) { model.addAttribute("products", productService.findAll()); return "products/list"; } @PostMapping("/products") public String createProduct(@ModelAttribute Product product) { productService.save(product); return "redirect:/products"; } } ``` The same URL — `/products` — is handled by two different methods. Spring dispatches to the correct one based on the HTTP method. The GET handler retrieves data and renders a template. The POST handler processes the submitted form data and redirects (we will discuss why it redirects rather than rendering directly in Section 3.8). --- ## 3.3 Building Forms with Spring's FreeMarker Macros To build an HTML form that integrates with Spring MVC's data binding, we use the macros defined in `spring.ftl`. These macros generate form input elements that are automatically bound to a form-backing object (also called a "command object") in the model. ### Preparing the Form in the Controller Before the form can be rendered, the GET handler must add an empty object to the model. This object is what Spring will bind the form fields to: ```java @GetMapping("/products/new") public String showCreateForm(Model model) { model.addAttribute("product", new Product()); return "products/create"; } ``` The key `"product"` is the name by which the form-backing object is known. In the template, all form macro paths will start with this name. ### The Form Template Here is a complete form using Spring's FreeMarker macros: ```html <#import "/spring.ftl" as spring> <#import "layout.ftlh" as layout> <@layout.page title="Create Product">

Create a New Product

<@spring.formInput "product.name" 'id="name" class="form-control"'/> <@spring.showErrors "
" "error"/>
<@spring.formInput "product.price" 'id="price" class="form-control"' "number"/> <@spring.showErrors "
" "error"/>
<@spring.formTextarea "product.description" 'id="description" rows="5" class="form-control"'/> <@spring.showErrors "
" "error"/>
``` Let us break down what is happening. `<@spring.formInput "product.name" 'id="name" class="form-control"'/>` generates an `` element. The first argument — `"product.name"` — is the **path**: the name of the form-backing object (`product`) followed by the field name (`name`). The macro binds to this path, meaning it will populate the input's `value` attribute from the object's `name` property, and name the input so that submitted data maps back to that property. The second argument is a string of additional HTML attributes to include in the generated tag. `<@spring.formInput "product.price" '...' "number"/>` demonstrates the optional third argument — the field type. By passing `"number"`, the macro generates `` instead of the default text input. You can also pass `"hidden"` or `"password"` here. `<@spring.formTextarea "product.description" '...'/>` generates a `