'Spring boot does not show custom error when exception is thrown
I am fairly new to Java/Spring domain and I am trying to utilize @ControllerAdvice in my Spring Boot application. The ControllerAdvice catches the exception but doesn't show my custom response.
following is the snap shot of RestController which is throwing the exception
ResponseEntity<MyClass> response = new ResponseEntity<MyClass>(HttpStatus.OK);
try {
response = restTemplate.exchange(url, HttpMethod.GET, entity, MyClass.class);
} catch (HttpClientErrorException ex) {
throw ex;
}catch (HttpServerErrorException ex) {
logger.debug(ex.getMessage() + " Server Status Code - " + ex.getStatusCode());
}
catch(Exception ex) {
logger.debug(ex.getMessage() + " Generic Exception ");
}
following is the @ControllerAdvice
@ControllerAdvice
public class GlobalExceptionHandler extends Exception {
@ExceptionHandler(HttpClientErrorException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse errorHandle(HttpClientErrorException ex) {
String responseBody = ex.getResponseBodyAsString();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ErrorResponse errorResponse = new ErrorResponse();
try {
errorResponse = mapper.readValue(responseBody, ErrorResponse.class);
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return errorResponse;
}
}
and other classes
@JsonIgnoreProperties
public class ErrorResponse {
@JsonProperty("error")
public Error error;
@JsonProperty("version")
public String version;
}
public class Error {
@JsonProperty("code")
public String Code;
@JsonProperty("message")
public String Message;
public String getCode() {
return Code;
}
public void setCode(String code) {
Code = code;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
}
the error I am getting when using POSTMAN is
{
"timestamp": "2019-11-20T05:42:24.126+0000",
"status": 404,
"error": "Not Found",
"message": "400 Bad Request",
"path": "myApi/somecontroller"
}
and the error I get on browser is as follows
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Tue Nov 19 23:40:26 CST 2019
There was an unexpected error (type=Not Found, status=404).
400 Bad Request
any idea/suggestion why this behavior? I was expecting an JSON representation of ErrorResponse class.
Update
Solution 1:[1]
This isn't an Exception this is an Error scenario
Try to use following code.
@RestController
public class IndexController implements ErrorController{
private static final String PATH = "/error";
@RequestMapping(value = PATH)
public String error() {
return "Error handling";
}
@Override
public String getErrorPath() {
return PATH;
}
}
Spring Boot default register BasicErrorController which needs to overriden
Solution 2:[2]
In your case, you are having a Controller Advice method that returns a Json response for the particular exception. So, there is no point in checking for the response in the browser ui as you need a proper error page to be configured through another exception handler for that to work as you desire. Otherwise the default spring white label error page will be shown.
For the rest exception handler , i think the JSON structure is not getting properly converted when you use the object mapper to create the instance.Try it like :
@ControllerAdvice
public class GlobalExceptionHandler extends Exception {
@ExceptionHandler(HttpClientErrorException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ErrorResponse errorHandle(HttpClientErrorException ex) {
String responseBody = ex.getResponseBodyAsString(); // The response body structure is different, you should get the message and stacktrace separately and assign it to your own response object
ErrorResponse errorResponse = new ErrorResponse();
Error error = new Error();
error.setMessage(ex.getMessage());
error.setCode(HttpStatus.BAD_REQUEST);
errorResponse.setError(error);
return errorResponse;
}
}
getResponseBodyAsString - Return the response body converted to String. The charset used is that of the response "Content-Type" or otherwise "UTF-8".
Solution 3:[3]
After doing some testing/search, figured this out. Using following Controller will be able to achieve that
@ControllerAdvice
public class GlobalExceptionHandler extends Exception {
@ExceptionHandler(value = { HttpClientErrorException.class })
public ResponseEntity<Object> handleResourceNotFoundException(HttpClientErrorException ex) {
String responseBody = ex.getResponseBodyAsString();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ErrorResponse errorResponse = new ErrorResponse();
try {
errorResponse = mapper.readValue(responseBody, ErrorResponse.class);
} catch (JsonMappingException e) {
e.printStackTrace();
}
catch (JsonProcessingException e) {
e.printStackTrace();
}
ResponseEntity<Object> response = new ResponseEntity<>(errorResponse, headers, HttpStatus.BAD_REQUEST);
return response;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Swarit Agarwal |
| Solution 2 | |
| Solution 3 | Karan |

