Exception Handling in Spring Boot Application in a Single Component

curl -i --location --request GET 'localhost:8080/items/1000' \
--header 'Content-Type: application/json' \
--data-raw ''
HTTP/1.1 500 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 21 May 2021 12:19:05 GMT
Connection: close

{
"timestamp":"2021-05-21T12:19:05.553+00:00",
"status":500,
"error":"Internal Server Error",
"message":"",
"path":"/items/1000"
}
curl -i --location --request POST 'localhost:8080/items' \
--header 'Content-Type: application/json' \
--data-raw '{
"title" : ""
}'
HTTP/1.1 500 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 21 May 2021 12:04:41 GMT
Connection: close

{
"timestamp":"2021-05-21T12:04:41.354+00:00",
"status":500,
"error":"Internal Server Error",
"message":"",
"path":"/items"
}
@Slf4j
@RestControllerAdvice
public class ApiExceptionHandler {

@ResponseStatus(NOT_FOUND)
@ExceptionHandler(EntityNotFoundException.class)
public void handleNotFound(EntityNotFoundException e) {
log.debug("Entity not found.", e);
}

@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public ErrorsDto handleConstraintViolations(ConstraintViolationException e) {
final List<ErrorDto> errors = e.getConstraintViolations()
.stream()
.map(v -> ErrorDto.builder()
.message(v.getMessage())
.path(v.getPropertyPath().toString())
.value(v.getInvalidValue())
.build())
.collect(toList());

return new ErrorsDto(errors);
}

}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ErrorsDto {

private List<ErrorDto> errors;

}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ErrorDto {

private String message;

private String path;

private Object value;

}
    @ResponseStatus(NOT_FOUND)
@ExceptionHandler(EntityNotFoundException.class)
public void handleNotFound(EntityNotFoundException e) {
log.debug("Entity not found.", e);
}
@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public ErrorsDto handleConstraintViolations(ConstraintViolationException e) {
final List<ErrorDto> errors = e.getConstraintViolations()
.stream()
.map(v -> ErrorDto.builder()
.message(v.getMessage())
.path(v.getPropertyPath().toString())
.value(v.getInvalidValue())
.build())
.collect(toList());

return new ErrorsDto(errors);
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ErrorsDto {

private List<ErrorDto> errors;

}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ErrorDto {

private String message;

private String path;

private Object value;

}
{
"errors": [
{
"message": "size must be between 1 and 255",
"path": "create.createItemRequest.title",
"value": ""
}
]
}
@Test
public void shouldNotGetItem_NotFound() {
final HttpEntity<Void> entity = new HttpEntity<>(httpHeaders());

ResponseEntity<Item> foundItem = restTemplate.exchange(url("/items/-1"), HttpMethod.GET, entity, Item.class);
assertThat(foundItem.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
}

@Test
public void shouldNotCreateItem_LongTitle() {
final String title = Stream.generate(() -> "a")
.limit(257)
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();

final HttpEntity<CreateItemDto> entity = new HttpEntity<>(
new CreateItemDto(title),
httpHeaders()
);

ResponseEntity<ErrorsDto> error = restTemplate.exchange(
url("/items"),
HttpMethod.POST,
entity,
ErrorsDto.class
);

assertThat(error.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
assertThat(error.getBody()).isNotNull();
assertThat(error.getBody().getErrors()).isNotNull();
assertThat(error.getBody().getErrors()).hasSize(1);
assertThat(error.getBody().getErrors().get(0).getMessage()).isEqualTo("size must be between 1 and 255");
assertThat(error.getBody().getErrors().get(0).getPath()).isEqualTo("create.createItemRequest.title");
assertThat(error.getBody().getErrors().get(0).getValue()).isEqualTo(title);
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store