I am kind of confused about the way I should design repository -> service -> controller communication using Optionals in my RestAPI Spring app. For instance, client wants to find film by id, but film is not present and repository returns empty Optional. I have two ways of dealing with it:
Service method returns Optional value or throws Exception which can be handled in Controller using ControllerAdvice.
Service returns Optional and Controller deals with it (return value if present or handle exception, or maybe just do something else).
I know that using exceptions for such simple situations is not best practice, probably you may suggest other ways of letting client know that id is wrong.
Method in RestController currently:
@GetMapping("/{id}")
public FilmGetDto getFilm(@PathVariable int id) {
return filmService.getFilm(id);
}
Most followed practice I have followed or seen people doing is you should handle it in service and use wrapper class for response. By this way you will achieve two things i.e. you will have a constant Response object that you can use in all of your application and also you can use exceptions etc very easily with that. You should always handle any sought of business logic in service layer as MVC states. I am posting an example here so that you can understand better what I am trying to say here.
Controller:
@GetMapping("/{id}")
public Response getFilm(@PathVariable int id) {
return filmService.getFilm(id);
}
Service:
public Response getFilm(int id){
Optional<Film> film = repo.findById(id);
return film.map(f -> Response.builder().status(200).data(f).message("request successful"))
.orElseGet(() -> Response.builder().status(422).data(null).message("Film with given id not found");
}
and Response class with be like as suggested by @Adrash as well
class Response {
private int status;
private Object data;
private String message;
//you can use lombok or IDE generate getter setters to generate getters setters
}
Note: I have used lombok builder method to create response object in service layer.