When I write RestController in Spring, all time I check whether object is null or not. How can I escape this check?
In below example, there is null check and later return notFound or Http status 404. So I don't want to check it all time.
@GetMapping(path = "/api/member/{member-id}")
public ResponseEntity<Member> getMemberById(@PathVariable(name="member-id", required=true) final Long memberId) {
final Member member = memberService.findById(memberId);
if (member != null) {
return ResponseEntity.ok(member);
}
return ResponseEntity.notFound().build();
}
Although you cannot avoid the null-check itself, you can move it out of the Controller into the service (also, use Optional
). If you are looking for a general strategy to handle negative response scenarios, I'd suggest using Spring's RestControllerAdvice
annotation that will enable global exception handling for all your APIs:
Let's first move the check to the service and raise a custom exception MemberNotFoundException
in case no record is found.
DefaultMemberService.java
public Member findById(final String memberId) {
Optional<Member> member = memberRepository.findById(memberId);
return member.orElseThrow(() -> new MemberNotFoundException("Invalid member Id"));
}
In the Controller, just make a call to the service method, and return the response.
MemberController.java
@GetMapping(path = "/api/member/{member-id}")
public ResponseEntity<Member> getMemberById(@PathVariable(name="member-id", required=true) final Long memberId) {
return ResponseEntity.ok().body(memberService.findById(memberId));
}
As you can see, we're not handling the exception explicitly. Instead we'll let RestControllerAdvice
do it for us by mapping the exception class to the response (error message, response code):
ExceptionHandlerControllerAdvice.java
@RestControllerAdvice
public final class ExceptionHandlerControllerAdvice {
@ExceptionHandler({ MemberNotFoundException.class })
@ResponseStatus(HttpStatus.NOT_FOUND)
ResponseEntity<ErrorDto> handleRecordNotFound(MemberNotFoundException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorDto(ex.getMessage));
}
}
where, ErrorDto
(simplified) is:
public class ErrorDto {
private String message;
public ErrorDto(String msg) { this.message = msg; }
public String getMessage() { return this.message; }
}