Operation System : Windows 10
IDE : IntelliJ
Requirements : Java 8 > , Postman ( For Testing)
Book | Tutorial : youtube tutorial
Java version : 12
Git Project : Here
Parts: Part 1
Goal
Learn how to indicate erroneous actions and objects in the REST Service
Solution
Main Changes
Model
During my research I encountered the use of validation annotations such as @NotNull, @NotEmpty etc, but I could not seem to get them to function as desired. However I will definitely look more into that in the nearer future and update this solution.
With that being said, in this solution the Todo bean/object was extended with a static method which confirms the validity of the provided arguments and returns a boolean value accordingly.
package com.example.demo.model; import java.util.regex.Pattern; import java.util.UUID; public class Todo { private final UUID id; private String title; … public static boolean validateTodo(String title){ if(title == null) { return false; } boolean isValid = true; String pattern = "\\w+"; Pattern p = Pattern.compile(pattern); return p.matcher(title).find(); } }
Service
Since the Todo class has a validateTodo function, the TodoService will use this to check the correctness of the title value before a new Todo object is created. Hence both the addTodo and patchTodo methods are to be modified.
... @Service public class TodoService implements ITodoService { private List<Todo> todos = new ArrayList<>(); @Override public Todo addTodo(@JsonProperty("title") String title, @JsonProperty("isCompleted") boolean isCompleted) { if(Todo.validateTodo(title) == false){ return null; } Todo todo = new Todo(UUID.randomUUID(), title, isCompleted); todos.add(todo); return todo; } @Override public Todo patchTodo(UUID id, Todo patch) { if(Todo.validateTodo(patch.getTitle()) == false){ return null; } Todo update = new Todo(id, patch.getTitle(), patch.getIsComplete()); List<Todo> newtodos = this.todos.stream().map(todo -> todo.getId().equals(id)? update : todo).collect(Collectors.toList()); this.todos = newtodos; return patch; } ...
These functions return either a valid Todo object or a null object depending on the validity of the given title.
Controller
One last modification is the <PATCH> and <POST> APIs. Since the TodoService returns either a valid Todo object or a Null object when creating a todo, the respective controllers should accommodate the changes and react accordingly. This means if the returned value is null, the controllers throw an exception indicating that something went wrong ( “title is invalid”) . Otherwise the todo object is returned along with a status 200.
.... @RestController @RequestMapping("/api/v1/todos") public class TodoController { .... @PostMapping("/") public ResponseEntity<Todo> addTodo(@RequestBody Todo todo){ Todo newtodo = this.todoService.addTodo(todo.getTitle(), todo.getIsComplete()); if(newtodo == null){ throw new TodoInvalidException(); } return new ResponseEntity<Todo>(newtodo, HttpStatus.OK); } @PatchMapping("/{id}") public ResponseEntity<Todo> patchTodo(@PathVariable("id") UUID id, @RequestBody Todo patch ){ Todo updateTodo = this.todoService.patchTodo(id,patch); if(updateTodo == null){ throw new TodoInvalidException(); } return new ResponseEntity<Todo>(updateTodo, HttpStatus.OK); } .... }
Author Notes
This is most likely not the cleanest implementation, just a heads up.
Links
- Validating Form Input
- Validation in Spring Boot
- Practice RegEXP
- Using Spring ResponseEntity to Manipulate the HTTP Response
- Interface BindingResult
- getAllErrors
- ObjectError
- Regular expressions in Java – Tutorial
- RuntimeException
- Exception Handling in Spring MVC
- How to use Regex in Java to pattern match?