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);
}
CodePudding user response:
If you want to send a message to the client about the non-existence of such id, you have to handle such edge cases. probably you can use Optional and handle if optional.isPresent() returns false, you can send a customized message and let your client know that no data exist with such id.
You can use a wrapper class to achieve this.
class ErrorResponse {
private String status;
private int statusCode;
private String message;
public ErrorResponse(String status, int statusCode, String message){
this.status = status;
-----
-----
}
}
Set this feilds and return this class object as a response.
CodePudding user response:
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);
if(film.isPresent()){
return Response.builder().status(200).data(fim.get()).message("request successful");
}else{
return 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.