Reputation: 103
I have a question about spring boot. When I want to get the specific user from my database everything is ok but how can I handle the null response (There is no such a user)? I want to handle the return value of null as ResponseEntity but when there is a user with that id I need to return User details. So I could not set return value as ResponseEntity. Here is the screenshot of the problem:
Here is the code:
@GetMapping("get/{id}")
public User findById(@PathVariable int id) throws Exception {
try {
if(userMapper.findById(id) != null) {
return userMapper.findById(id);
}else {
throw new Exception("YOK ULAN YOK");
}
}catch (Exception e) {
// TODO: Make perfect
return new User(-1);
}
}
and here is the return value:
{
"email": null,
"username": null,
"password": null,
"name": null,
"surname": null,
"age": 0,
"photoLink": null,
"dateOfBirth": null,
"phoneNumber": null,
"city": null,
"country": null,
"friendList": null,
"plan": null,
"id": -1,
"planned": false
}
I don't want to send a -1 user, I want to send a user not found response. How can I handle it?
Thanks,
Upvotes: 4
Views: 5677
Reputation: 51
You could use an exception handler to handle these kind of exceptions. To make this work, you could first return an Optional<User>
instead of a User
. Then you could write your controller as following.
@GetMapping(value = "/get/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> findById(@PathVariable int id) {
return ResponseEntity
.status(HttpStatus.OK)
.body(userMapper.findById(id)
.orElseThrow(UserNotFoundException::new);
}
The UserNotFoundException
is a custom class. You can extend from RuntimeException
so the exception becomes unchecked.
public class UserNotFoundException extends RuntimeException {}
Then you could make an ErrorResponse
class. You're free to add the fields you like, but it could look like this:
@Getter
@Setter
public class ErrorResponse {
private int code;
private String description;
}
You could then handle this UserNotFoundException
in an ExceptionHandler
:
@RestControllerAdvice
@Slf4j
public class ApplicationNameExceptionHandler {
@ExceptionHandler
public ResponseEntity<ErrorResponse> handleException(UserNotFoundException e) {
log.info("User not found");
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(HttpStatus.NOT_FOUND.value());
errorResponse.setDescription("User not found");
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.contentType(MediaType.APPLICATION_PROBLEM_JSON)
.body(errorResponse);
}
The advantage of this approach is that you can keep your controllers concise and tidy and all your controller exceptions can be handled in the same class (ApplicationNameExceptionHandler
).
Upvotes: 2
Reputation: 515
We can try to define a exception with reponse status.
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
}
And then, in your controller, throw this exception
throw new ResourceNotFoundException()
Or, just set the status of Response
directly.
BTW, a better approach is to define our business code to implement it.
Upvotes: 0
Reputation: 6063
the best way is to change method return type from User
to ResponseEntity<?>
, smth. like:
@GetMapping("get/{id}")
public ResponseEntity<?> findById(@PathVariable int id) throws Exception {
User user = userMapper.findById(id);
if (user == null) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user);
}
or using optional:
@GetMapping("get/{id}")
public ResponseEntity<?> findById(@PathVariable int id) throws Exception {
return Optional.ofNullable(userMapper.findById(id))
.map(ResponseEntity::ok)
.orElseGet(ResponseEntity.notFound()::build);
}
Upvotes: 2