Hello.
This is a series of making TODO applications with Java + Spring, but from this time we will finally implement exception handling.
I want to start from a relatively easy place to get used to exception handling, so let's take a look at exception handling when accessing a non-existent ID!
1: [Understanding super basics] A brief description of MVC 2: [Prepare a template] I want to create a template with Spring Initializr and do Hello world 3: [Connection / Settings / Data display with MySQL] Save temporary data in MySQL-> Get all-> Display on top 4: [POST function] Implementation of posting function 5: [PATCH function] Switch TODO display 6: [Easy to use JpaRepository] Implementation of search function [7: [Common with Thymeleaf template fragment] Create Header] (https://qiita.com/nomad_kartman/items/8c33eca2880c43a06e40) [8: [PUT function] Implementation of editing function] (https://qiita.com/nomad_kartman/items/66578f3f91a422f9207d) [9: [Tweak] Sort TODO display in chronological order + Set due date default to today's date] (https://qiita.com/nomad_kartman/items/5ee2b13a701cf3eaeb15) 10: [Exception handling with spring] A brief summary of exception handling 11: [Exception handling with spring] Exception handling when accessing TODO with non-existent ID (now here)
Now, in the previous article, I briefly explained what exception handling is.
In summary
Security by directing to a specific error page when the user makes an unintended request of the creator (entering more characters than specified when registering TODO, trying to access a non-existent URL ... etc) Improve surface and usability.
It means that.
This time we will implement it when ** requesting access to TODO with non-existent ID ** ...
com/example/todo/TodoController.java
@GetMapping("/edit/{id}")
public String showEdit(Model model, @PathVariable("id") long id ) {
TodoEntity editTarget = todoService.findTodoById(id);
model.addAttribute( "editTarget" , editTarget);
return "edit";
}
Exception handling when calling this showEdit
. todoService.findTodoById (id)
gets TODO via the Service class, but let's take a look at findTodoById ()
.
com/example/todo/TodoService.java
public TodoEntity findTodoById(Long todoId) {
Optional<TodoEntity> todoResult = todoRepository.findById(todoId);
return todoResult.get();
}
ID search is performed from Repository, TODO is acquired and returned as Optional type.
However, if you try to search with an ID that does not exist here, it will fail with an error, so at this timing
** If todoResult is empty, lead to a specific Exception class **
You should do it!
com/example/todo/exception/TodoNotFoundException.java
package com.example.todo.exception;
public class TodoNotFoundException extends RuntimeException{
}
Create a new directory called `ʻexceptionand create a class called
TodoNotFoundException`` in it.
`ʻextendsmeans that this class inherits from
RuntimeException. By inheriting, the method of
RunttimeException`` can be used in this class as well. (I will not use it this time ...)
com/example/todo/TodoService.java
public TodoEntity findTodoById(Long todoId) {
Optional<TodoEntity> todoResult = todoRepository.findById(todoId);
todoResult.orElseThrow(TodoNotFoundException::new);
return todoResult.get();
}
Let's take a look at the line we added before return!
By setting ʻOptional.orElseThrow (Exception name :: new)
`, you can skip the process to the specified class when the Optional type is empty. (This time, the TodoNotFoundException
that I made earlier)
By the way, the part of `ʻException name :: new`` is called a method reference, and it refers to the method as an argument of the method.
This article will be helpful, so please take a look.
The TodoNotFoundException
you created earlier just inherited the RuntimeException
and the contents were empty.
com/example/todo/exception/TodoNotFoundException.java
package com.example.todo.exception;
public class TodoNotFoundException extends RuntimeException{
}
Here, using the annotation @ControllerAdvice, we will implement the processing ** when ** TodoNotFoundException is called (= when thrown) **.
com/example/todo/exception/TodoControllerAdvice.java
package com.example.todo.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
@Slf4j
@ControllerAdvice
public class TodoControllerAdvice {
@ResponseStatus(HttpStatus.NOT_FOUND)
@ExceptionHandler(TodoNotFoundException.class)
public String idNotFound() {
log.warn("The specified TODO cannot be found.");
return "error/404.html";
}
}
Let's create a class like this in the `ʻexception`` directory.
To explain in order from the top ...
templates/error/404.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>404</title>
</head>
<body>
404!
</body>
</html>
Normally, the error content should be displayed, but this time it's simply 404! I just want to display.
It may be confusing because I explained it all at once, but the following is a summary of this process.
-User requests Todo editing (800 / edit / 100)
↓
-The controller sends processing to the service class upon request (findTodoById (100))
↓
-Since there is no TODO with ID = 100, TodoNotFoundException
is called.
↓
- TodoControllerAdvice
with @ControllerAdvice outputs a log saying "The specified TODO cannot be found" and transitions to 404.html.
It is like this!
It may be a little difficult to understand if it is a sentence, so I think you should read the article here.
We will continue to implement exception handling next time!