Spring MVC #ExceptionHandler chaining - spring-mvc

Is there a way to chain #ExceptionHandler with exception throwing?
I'm trying to wrap exceptions throw in request handler methods before sending a response:
#ExceptionHandler(value = JsonParseException.class)
public void handleJsonParseException(JsonParseException e) throws BadRequestException {
throw new BadRequestException(e);
}
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
#ExceptionHandler(value = BadRequestException.class)
public #ResponseBody RestResponse handleBadRequest(BadRequestException e) {
log.info("Bad REST Request", e);
return constructErrorResponse(e);
}
So, I'd like to for the handleBadRequest() to catch BadRequestException re-thrown from handleJsonParseException().
With the code above, handleJsonParseException() causes server to return default error page instead of RestResponse.
Is this possible or will I have to put exception wrapping in request handlers' try - catch?

Is not possible:
Chained Annotated Exception Handling - #ExceptionHandler (SPR-13726)

Related

How to handle Internal server error (500) on spring rest API to custom the message?

I am working on spring rest api and I would like to sure everything is working fine. I would like to log abnormal behaviors database connection error among others, I'm working with couchbase database and I'm getting in the endpoint response for example for this kind of exception: CouchbaseQueryExecutionException the next message: Unable to execute query due to the following n1ql errors: \n{\"msg\":\"No index available on keyspace kids_club that matches your query. Use CREATE INDEX or CREATE PRIMARY INDEX to create an index, or check that your expected index is online.\",\"code\":4000} and a very long trace.
For this i found a solution on internet that is extend ResponseEntityExceptionHandler and override handleExceptionInternal method like this:
#ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
private static String DEFAULT_VALIDATION_ERROR_CODE = "KC-0020";
#ExceptionHandler(MiddlewareException.class)
protected ResponseEntity<ResponseBody> handleKidsClubException(MiddlewareException ex) {
return buildErrorResponse(HttpStatus.valueOf(ex.getHttpStatus()), ex.toError());
}
#ExceptionHandler(ServiceUnavailableException.class)
protected ResponseEntity<ResponseBody> handleServiceUnavailable(ServiceUnavailableException ex) {
return buildErrorResponse(INTERNAL_SERVER_ERROR, ex);
}
#ExceptionHandler(NoSuchElementException.class)
protected ResponseEntity<ResponseBody> handleNoFoundElement(NoSuchElementException ex) {
return buildErrorResponse(NOT_FOUND, ex);
}
#ExceptionHandler(CouchbaseQueryExecutionException.class)
protected ResponseEntity<ResponseBody> handleCouchbaseQueryException(ConstraintViolationException ex) {
return buildErrorResponse(BAD_REQUEST, ex);
}
}
But I'm not able to catch any kind of Internal Server Error in this way.
It seems like spring is handle and building the final message to the user.
Any ideas to resolve this?
Thanks.
#ExceptionHandler(NullPointerException.class)
public final ResponseEntity<Object> handleNullPointerException(NullPointerException ex, WebRequest request) {
LOGGER.info("Entering into the handleAllException method");
System.out.println("Exception is : " + ex.getClass());
ResponseData error = new ResponseData();
error.setRespCode(HttpStatus.NOT_FOUND.toString());
error.setRespMessage(ex.getLocalizedMessage());
error.setTimestamp(LocalDateTime.now());
return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
please try this way below to check whether you are able to catch exception or not.. From the sysout you will get the exact exception. Then you can use that exception to catch any particular exception from that business logic..

How to catch a lot of Jackson Exceptions in Spring?

I have a Spring Boot REST application that uses ControllerAdvice and ExceptionHandlers. I'm using Jackson as my serialization/deserialization. I'm using PostMan as my client and when I send in different errors such as invalid inputs, bad JSON syntax etc... Jackson throws certain exceptions. Currently, I have an (1) ExceptionHandler that explicitly states each type of exception such as MismatchedInputException, InvalidFormatException, InvalidDentinitionException...these are all forms of JsonProcsessingException.
Is there a way to just catch JsonProcessingException and all its children? I return different messages/status codes depending on the types of exceptions. So if exception related to serialization is thrown I want a certain error message sent back.
You should create this method in #ControllerAdvice class and verify what exceptions you want to manage in order to return different messages/status codes .
#ExceptionHandler({InvalidFormatException.class, MismatchedInputException.class})
public void handlerIllegalArgumentException(JsonProcessingException exception,
ServletWebRequest webRequest) throws IOException {
if(exception instanceof InvalidFormatException) {
LOGGER.error(exception.getMessage(), exception);
webRequest.getResponse().sendError(HttpStatus.CONFLICT.value(), exception.getMessage());
} else if (exception instanceof MismatchedInputException) {
LOGGER.error(exception.getMessage(), exception);
webRequest.getResponse().sendError(HttpStatus.BAD_REQUEST.value(), exception.getMessage());
}
}

Can a generic #ExceptionHandler and DefaultHandlerExceptionResolver play nice?

I'd like to implement an #ExceptionHandler that prevents all uncaught exceptions from getting to the client. Something like this...
#ControllerAdvice
public class ExceptionHandlingControllerAdvice {
private static final Logger logger = getLogger(ExceptionHandlingControllerAdvice.class);
#ExceptionHandler(Exception.class)
#ResponseStatus(value = INTERNAL_SERVER_ERROR)
public void handleAnyUncaughtException(Exception e) {
logger.error("This uncaught exception is being blocked from reaching the client.", e);
}
}
But this is getting in the way of the exception handling performed out of the box by DefaultHandlerExceptionResolver, e.g. to throw 4xx errors on failed #RequestBody validations checked with #Valid. It seems like #ExceptionHandler is taking precedence and returning 500 before the DHER can try to return a 4xx.
Is there a way to block uncaught exceptions from getting to the client, but still let the DefaultHandlerExceptionResolver do its job?
I found a solution. I was writing an #ExceptionHandler that explicitly handles all the standard Spring MVC exceptions, checked the manual for the list, and ran across the ResponseEntityExceptionHandler base class.
Extending that base class in the #ControllerAdvice adds an #ExceptionHandler for the standard exceptions with the crucial difference that you don't have to maintain the list should those exceptions change. The #ControllerAdvice now looks like this.
#ControllerAdvice
public class ExceptionHandlingControllerAdvice extends ResponseEntityExceptionHandler {
private static final Logger logger = getLogger(ExceptionHandlingControllerAdvice.class);
#ExceptionHandler(Exception.class)
#ResponseStatus(value = INTERNAL_SERVER_ERROR)
public void handleAnyUncaughtException(Exception e) {
logger.error("This uncaught exception is being blocked from reaching the client.", e);
}
}

Spring MVC exception handling with HandlerExceptionResolver

I am currently trying to use HandlerExceptionResolver for exception handling in a Spring MVC project.
I want to handle normal exceptions via resolveException as well as 404's via
handleNoSuchRequestHandlingMethod.
Depending on the request type JSON or text/html the exception response should be returned appropriately.
resolveException works now.
But handleNoSuchRequestHandlingMethod is giving me a headache. It's never called!
According to the docu the method should be called on 404 errors
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.html
What am I doing wrong...
This is what I have so far.
public class JsonExceptionResolver implements HandlerExceptionResolver {
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView resolveException(HttpServletRequest request,
if (exception instanceof NoSuchRequestHandlingMethodException) {
return handleNoSuchRequestHandlingMethod((NoSuchRequestHandlingMethodException) exception, request, response, handler);
}
...
}
public ModelAndView handleNoSuchRequestHandlingMethod(NoSuchRequestHandlingMethodException ex,
HttpServletRequest request,
HttpServletResponse response,
Object handler){
logger.info("Handle my exception!!!");
ModelAndView mav = new ModelAndView();
boolean isJSON = request.getHeader("Accept").equals("application/json");
if(isJSON){
...
}else{
..
}
return mav;
}
}
EDIT with DefaultHandlerExceptionResolver:
public class MyExceptionResolver extends DefaultHandlerExceptionResolver {
protected final Log logger = LogFactory.getLog(getClass());
#Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
logger.warn("An Exception has occured in the application", exception);
logger.info("exception thrown " + exception.getMessage() );
if (exception instanceof NoSuchRequestHandlingMethodException) {
return handleNoSuchRequestHandlingMethod((NoSuchRequestHandlingMethodException) exception, request, response, handler);
}
...
return mav;
}
public ModelAndView handleNoSuchRequestHandlingMethod(NoSuchRequestHandlingMethodException ex,
HttpServletRequest request,
HttpServletResponse response,
Object handler){
logger.info("Handle my exception!!!");
ModelAndView mav = new ModelAndView();
boolean isJSON = request.getHeader("Accept").equals("application/json");
if(isJSON){
...
}else{
...
}
return mav;
}
}
The above code still has no effect.
Any other ideas?
According to Juergen Hoeller from Spring, it isn't possible with the HandlerExceptionResolver because it only works for sub-mapping e.g.
you have a controller mapped to /account/** and accesss a method from acount where no mapping exists like /acount/notExists than it should work.
I will open a JIRA improvement ticket for this functionality
EDIT:
JIRA ticket about this issue
https://jira.springsource.org/browse/SPR-8837?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=72648#comment-72648
handleNoSuchRequestHandlingMethod isn't part of the HandlerExceptionResolver interface, so just declaring a method of that name will do nothing. It's a protected method specific to DefaultHandlerExceptionResolver, and is called from its resolveException method (which is part of the interface):
if (ex instanceof NoSuchRequestHandlingMethodException) {
return handleNoSuchRequestHandlingMethod((NoSuchRequestHandlingMethodException) ex, request, response, handler);
}
To reproduce the same functionality, you can either subclass DefaultHandlerExceptionResolver and override the methods you need to, or you need to add a case in your resolveException method that handles NoSuchRequestHandlingMethodException.

Using Spring 3 #ExceptionHandler with commons FileUpload and SizeLimitExceededException/MaxUploadSizeExceededException

I am having trouble with catching and gracefully handling commons fileupload's FileUploadBase.SizeLimitExceededException or spring's MaxUploadSizeExceededException when uploading large files.
From what I can tell these exceptions are thrown during data binding, before the controller is actually reached, therefore resulting in a 500 and no calling of the exception handler method. Has anyone come across this before, and what is the best way for handling these exceptions properly?
thanks to thetoolman for this simple solution. I extended it a bit. I wanted to leave the file handling untouched and transport the Exception to the Controller.
package myCompany;
public class DropOversizeFilesMultipartResolver extends CommonsMultipartResolver {
/**
* Parse the given servlet request, resolving its multipart elements.
*
* Thanks Alexander Semenov # http://forum.springsource.org/showthread.php?62586
*
* #param request
* the request to parse
* #return the parsing result
*/
#Override
protected MultipartParsingResult parseRequest(final HttpServletRequest request) {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
List fileItems;
try {
fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
} catch (FileUploadBase.SizeLimitExceededException ex) {
request.setAttribute(EXCEPTION_KEY, ex);
fileItems = Collections.EMPTY_LIST;
} catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
return parseFileItems(fileItems, encoding);
}
}
and in the controller
#InitBinder("fileForm")
protected void initBinderDesignForm(WebDataBinder binder) {
binder.setValidator(new FileFormValidator());
}
#RequestMapping(value = "/my/mapping", method = RequestMethod.POST)
public ModelAndView acceptFile(HttpServletRequest request, Model model, FormData formData,
BindingResult result) {
Object exception = request.getAttribute(DropOversizeFilesMultipartResolver.EXCEPTION_KEY);
if (exception != null && FileUploadBase.SizeLimitExceededException.class.equals(exception.getClass())) {
result.rejectValue("file", "<your.message.key>");
LOGGER.error(exception);
}
the spring config remains the same. It would be really nice to have the exception transported to the validator, but I haven't figured out how to do this yet.
I know this is old, but I was looking for a solution to this as well and could not find anything. We are providing RESTful services using Spring and we are doing file upload and were not sure how to handle this. I came up with the following and hopefully it will be useful to someone:
All our exceptions are handled with annotations, so we have our error handler resolver set-up like this:
#Configuration
public class MyConfig{
#Bean
public AnnotationMethodHandlerExceptionResolver exceptionResolver(){
final AnnotationMethodHandlerExceptionResolver resolver = new AnnotationMethodHandlerExceptionResolver();
resolver.setMessageConverters(messageConverters());
resolver;
}
}
Then a common class that can handle the exception
public class MultipartExceptionHandler
{
#ExceptionHandler(MaxUploadSizeExceededException.class)
#ResponseStatus(value = HttpStatus.PRECONDITION_FAILED)
#ResponseBody
protected CustomError handleMaxUploadSizeExceededException(final HttpServletRequest request,
final HttpServletResponse response, final Throwable e)
throws IOException
{
logger.error(e);
CustomError c = new CustomErrorMaxFileSize("Max file size exceeded", MAX_FILE_SIZE);
return c;
}
#ExceptionHandler(MultipartException.class)
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
#ResponseBody
protected CustomError handleGenericMultipartException(final HttpServletRequest request,
final HttpServletResponse response, final Throwable e)
throws IOException
{
logger.error(e);
CustomError c = new CustomErrorGeneric("There was a problem with the upload");
return c;
}
}
Then we subclass the commons multipart resolver and implement the HandlerExceptionResolver interface
#Component(value="multipartResolver") // Spring expects this name
public class MyMultipartResolver extends CommonsMultipartResolver implements HandlerExceptionResolver
{
// This is the Spring bean that handles exceptions
// We defined this in the Java configuration file
#Resource(name = "exceptionResolver")
private AnnotationMethodHandlerExceptionResolver exceptionResolver;
// The multipart exception handler with the #ExceptionHandler annotation
private final MultipartExceptionHandler multipartExceptionHandler = new MultipartExceptionHandler();
// Spring will call this when there is an exception thrown from this
// multipart resolver
#Override
public ModelAndView resolveException(
final HttpServletRequest request,
final HttpServletResponse response,
final Object handlerParam,
final Exception ex)
{
// Notice that we pass this.multipartExceptionHandler
// and not the method parameter 'handlerParam' into the
// exceptionResolver. We do this because the DispatcherServlet
// doDispatch() method calls checkMultipart() before determining
// the handler for the request. If doing the multipart check fails
// with a MultipartException, Spring will never have a reference
// to the handler and so 'handlerParam' will be null at this point.
return exceptionResolver.resolveException(request, response, this.multipartExceptionHandler, ex);
}
}
This seems to be a quite common problem. I've had similar problems and similar questions have been asked, see for example this question. I have yet to see a nice solution to the problem. You could use a vanilla servlet filter to handle these exceptions, but that will duplicate your error handling since you already have an ExceptionHandler.

Resources