Java Spring Boot (Part 4)
Neil Haddley • October 29, 2023
ModelAndView
I used Spring MVC's ModelAndView class to pass model data to a Thymeleaf view template for rendering, adding a CRUD interface for the TodoItem application.

I added thymeleaf, bootstrap and jquery as dependencies

I added a thymeleaf page (as an alternative to JSP)

I updated the controller to populate the fetch the todo items and to pass them and the current day of the week to the thymeleaf view.

The new home page displays the todo items

I updated the controller to handle a delete request

I clicked the Delete button on the second todo item

The second todo item was deleted
pom.xml
XML
1<?xml version="1.0" encoding="UTF-8"?> 2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <parent> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-parent</artifactId> 8 <version>3.1.5</version> 9 <relativePath/> <!-- lookup parent from repository --> 10 </parent> 11 <groupId>com.haddley</groupId> 12 <artifactId>springdatajpa</artifactId> 13 <version>0.0.1-SNAPSHOT</version> 14 <name>springdatajpa</name> 15 <description>Demo project for Spring Boot</description> 16 <properties> 17 <java.version>17</java.version> 18 </properties> 19 <dependencies> 20 <dependency> 21 <groupId>org.springframework.boot</groupId> 22 <artifactId>spring-boot-starter-data-jpa</artifactId> 23 </dependency> 24 <dependency> 25 <groupId>org.springframework.boot</groupId> 26 <artifactId>spring-boot-starter-validation</artifactId> 27 </dependency> 28 <dependency> 29 <groupId>org.springframework.boot</groupId> 30 <artifactId>spring-boot-starter-web</artifactId> 31 </dependency> 32 33 <dependency> 34 <groupId>org.springframework.boot</groupId> 35 <artifactId>spring-boot-devtools</artifactId> 36 <scope>runtime</scope> 37 <optional>true</optional> 38 </dependency> 39 <dependency> 40 <groupId>com.h2database</groupId> 41 <artifactId>h2</artifactId> 42 <scope>runtime</scope> 43 </dependency> 44 <dependency> 45 <groupId>org.projectlombok</groupId> 46 <artifactId>lombok</artifactId> 47 <optional>true</optional> 48 </dependency> 49 <dependency> 50 <groupId>org.springframework.boot</groupId> 51 <artifactId>spring-boot-starter-test</artifactId> 52 <scope>test</scope> 53 </dependency> 54 55 <dependency> 56 <groupId>org.springframework.boot</groupId> 57 <artifactId>spring-boot-starter-thymeleaf</artifactId> 58 </dependency> 59 60 <!-- https://mvnrepository.com/artifact/org.webjars/bootstrap --> 61 <dependency> 62 <groupId>org.webjars</groupId> 63 <artifactId>bootstrap</artifactId> 64 <version>3.4.1</version> 65 </dependency> 66 <!-- https://mvnrepository.com/artifact/org.webjars/jquery --> 67 <dependency> 68 <groupId>org.webjars</groupId> 69 <artifactId>jquery</artifactId> 70 <version>3.6.0</version> 71 </dependency> 72 73 </dependencies> 74 75 <build> 76 <plugins> 77 <plugin> 78 <groupId>org.springframework.boot</groupId> 79 <artifactId>spring-boot-maven-plugin</artifactId> 80 <configuration> 81 <excludes> 82 <exclude> 83 <groupId>org.projectlombok</groupId> 84 <artifactId>lombok</artifactId> 85 </exclude> 86 </excludes> 87 </configuration> 88 </plugin> 89 </plugins> 90 </build> 91 92</project>
SpringdatajpaApplication.java
JAVA
1package com.haddley.springdatajpa; 2 3import org.springframework.boot.SpringApplication; 4import org.springframework.boot.autoconfigure.SpringBootApplication; 5 6import org.springframework.web.bind.annotation.GetMapping; 7import org.springframework.web.bind.annotation.RequestParam; 8import org.springframework.web.bind.annotation.RestController; 9import org.springframework.stereotype.Controller; 10 11import com.haddley.springdatajpa.models.TodoItem; 12import com.haddley.springdatajpa.repositories.TodoItemRepository; 13import org.springframework.beans.factory.annotation.Autowired; 14 15import java.util.stream.StreamSupport; 16import java.util.stream.Collectors; 17 18import org.springframework.web.servlet.ModelAndView; 19import org.springframework.ui.Model; 20import java.time.ZoneId; 21import java.time.Instant; 22 23import org.slf4j.Logger; 24import org.slf4j.LoggerFactory; 25 26import org.springframework.web.bind.annotation.PathVariable; 27 28@SpringBootApplication 29@Controller 30public class SpringdatajpaApplication { 31 32 private final Logger logger = LoggerFactory.getLogger(SpringdatajpaApplication.class); 33 34 public static void main(String[] args) { 35 SpringApplication.run(SpringdatajpaApplication.class, args); 36 } 37 38 @Autowired 39 private TodoItemRepository todoItemRepository; 40 41 @GetMapping("/") 42 public ModelAndView index() { 43 logger.info("request to GET index"); 44 ModelAndView modelAndView = new ModelAndView("index"); 45 modelAndView.addObject("todoItems", todoItemRepository.findAll()); 46 modelAndView.addObject("today", Instant.now().atZone(ZoneId.systemDefault()).toLocalDate().getDayOfWeek()); 47 return modelAndView; 48 } 49 50 @GetMapping("/delete/{id}") 51 public String deleteTodoItem(@PathVariable("id") long id, Model model) { 52 TodoItem todoItem = todoItemRepository 53 .findById(id) 54 .orElseThrow(() -> new IllegalArgumentException("TodoItem id: " + id + " not found")); 55 56 todoItemRepository.delete(todoItem); 57 return "redirect:/"; 58 } 59 60 61}