Java tutorial
package tv.arte.resteventapi.web.errors; /* * #%L * RestEventAPI * %% * Copyright (C) 2014 ARTE G.E.I.E * %% * This program is free software: you can redistribute it and/or modify * it under the terms of The MIT License (MIT) as published by the Open Source * Initiative. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See The * MIT License (MIT) for more details. * * You should have received a copy of The MIT License (MIT) * along with this program. If not, see <http://opensource.org/licenses/MIT> * #L% */ import java.util.Collection; import java.util.Locale; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.MessageSource; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.http.HttpStatus; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.view.json.MappingJackson2JsonView; import tv.arte.resteventapi.core.RestEventApiError; import tv.arte.resteventapi.core.RestEventApiMessage; import tv.arte.resteventapi.core.RestEventApiStandardResponse; import tv.arte.resteventapi.core.exceptions.NoResultInApiException; import tv.arte.resteventapi.core.validation.FieldValidationError; import tv.arte.resteventapi.core.validation.RestEventApiValidationException; /** * Global exception handling for front controllers * * @author Simeon Petev * @since 0.1 */ @ControllerAdvice public class GlobalDefaultExceptionHandler { private Logger logger = LoggerFactory.getLogger(GlobalDefaultExceptionHandler.class); public static final String DEFAULT_ERROR_VIEW = "error"; @Autowired @Qualifier("restEventApiDefaultErrorView") private MappingJackson2JsonView restEventApiDefaultErrorView; @Autowired private MessageSource messageSource; /** * Handle all exceptions of type {@link ImageRepositoryException} thrown by (or passing trough) the Controller's layer * * @param response The HttpServletResponse * @param e Thrown RestEventApiValidationException * @return * @throws Exception */ @ExceptionHandler(value = MethodArgumentNotValidException.class) public ModelAndView restEventApiMethodArgumentNotValidExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException e) throws Exception { RestEventApiStandardResponse<RestEventApiMessage> restEventApiStandardResponse = new RestEventApiStandardResponse<RestEventApiMessage>(); Locale userLocale = request.getLocale(); String descriprionNotAvailableDefaultMessage = RestEventApiError.PRE_DEFINED.RIA_ERR_G_DESC_NOT_AVAILABLE .getDefaultMessageText(); for (ObjectError globalError : e.getBindingResult().getGlobalErrors()) { restEventApiStandardResponse.addError(new RestEventApiMessage(globalError.getDefaultMessage(), this.messageSource.getMessage(globalError.getCode(), globalError.getArguments(), descriprionNotAvailableDefaultMessage, userLocale))); } for (FieldError fieldError : e.getBindingResult().getFieldErrors()) { String messageCode = null; String defaultMessageText = null; if (fieldError.isBindingFailure()) { messageCode = RestEventApiError.PRE_DEFINED.RIA_ERR_V_BINDING.getCode(); defaultMessageText = RestEventApiError.PRE_DEFINED.RIA_ERR_V_BINDING.getDefaultMessageText(); } else { //TODO: Find an appropriate way to search pre-defined RestEventAPiError messageCode = fieldError.getDefaultMessage(); defaultMessageText = descriprionNotAvailableDefaultMessage; } restEventApiStandardResponse .addError(new FieldValidationError(messageCode, this.messageSource.getMessage(messageCode, fieldError.getArguments(), defaultMessageText, userLocale), fieldError.getField())); } ModelAndView mav = new ModelAndView(); mav.addObject(restEventApiStandardResponse); mav.setView(restEventApiDefaultErrorView); return mav; } /** * Handle all exceptions of type {@link ImageRepositoryException} thrown by (or passing trough) the Controller's layer * * @param response The HttpServletResponse * @param e Thrown RestEventApiValidationException * @return * @throws Exception */ @SuppressWarnings("unchecked") @ExceptionHandler(value = RestEventApiValidationException.class) public ModelAndView restEventApiValidationExceptionHandler(HttpServletResponse response, RestEventApiValidationException e) throws Exception { if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) { throw e; } RestEventApiStandardResponse<RestEventApiMessage> restEventApiStandardResponse = new RestEventApiStandardResponse<RestEventApiMessage>(); restEventApiStandardResponse .setErrors((Collection<RestEventApiMessage>) (Collection<?>) e.getValidationErrorMessages()); ModelAndView mav = new ModelAndView(); mav.addObject(restEventApiStandardResponse); mav.setView(restEventApiDefaultErrorView); if (e.getResponseHttpStatusCode() != null) { response.setStatus(e.getResponseHttpStatusCode()); } else { response.setStatus(HttpStatus.BAD_REQUEST.value()); } return mav; } /** * Handle all exceptions of type {@link BindException} thrown by (or passing trough) the Controller's layer * * @param response The HttpServletResponse * @param e Thrown RestEventApiValidationException * @return * @throws Exception */ @ExceptionHandler(value = BindException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) public ModelAndView springBindExceptionExceptionHandler(HttpServletRequest request, BindException e) throws Exception { RestEventApiStandardResponse<RestEventApiMessage> restEventApiStandardResponse = new RestEventApiStandardResponse<RestEventApiMessage>(); Locale userLocale = request.getLocale(); String descriprionNotAvailableDefaultMessage = RestEventApiError.PRE_DEFINED.RIA_ERR_G_DESC_NOT_AVAILABLE .getDefaultMessageText(); for (ObjectError globalError : e.getGlobalErrors()) { restEventApiStandardResponse.addError(new RestEventApiMessage(globalError.getDefaultMessage(), this.messageSource.getMessage(globalError.getCode(), globalError.getArguments(), descriprionNotAvailableDefaultMessage, userLocale))); } for (FieldError fieldError : e.getFieldErrors()) { String messageCode = null; String defaultMessageText = null; if (fieldError.isBindingFailure()) { messageCode = RestEventApiError.PRE_DEFINED.RIA_ERR_V_BINDING.getCode(); defaultMessageText = RestEventApiError.PRE_DEFINED.RIA_ERR_V_BINDING.getDefaultMessageText(); } else { //TODO: Find an appropriate way to search pre-defined RestEventAPiError messageCode = fieldError.getDefaultMessage(); defaultMessageText = descriprionNotAvailableDefaultMessage; } restEventApiStandardResponse .addError(new FieldValidationError(messageCode, this.messageSource.getMessage(messageCode, fieldError.getArguments(), defaultMessageText, userLocale), fieldError.getField())); } ModelAndView mav = new ModelAndView(); mav.addObject(restEventApiStandardResponse); mav.setView(restEventApiDefaultErrorView); return mav; } /** * Handle all exceptions of type {@link ImageRepositoryException} thrown by (or passing trough) the Controller's layer * * @param response The HttpServletResponse * @param e Thrown NoResultInApiException * @return * @throws Exception */ @ExceptionHandler(value = NoResultInApiException.class) @ResponseStatus(HttpStatus.NOT_FOUND) public ModelAndView noResultInApiExceptionHandler(HttpServletResponse response, NoResultInApiException e) throws Exception { if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) { throw e; } RestEventApiStandardResponse<RestEventApiMessage> restEventApiStandardResponse = new RestEventApiStandardResponse<RestEventApiMessage>(); restEventApiStandardResponse.addError(RestEventApiError.PRE_DEFINED.RIA_ERR_G_SEARCH_NO_RESULTS); ModelAndView mav = new ModelAndView(); mav.addObject(restEventApiStandardResponse); mav.setView(restEventApiDefaultErrorView); return mav; } /** * Handle all exceptions thrown by Controller's layer and that have not been already handled * * @param response The HttpServletResponse * @param e Thrown exception * @return * @throws Exception */ @ExceptionHandler(value = Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ModelAndView defaultErrorHandler(HttpServletResponse response, Exception e) throws Exception { if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) { throw e; } RestEventApiStandardResponse<RestEventApiMessage> restEventApiStandardResponse = new RestEventApiStandardResponse<RestEventApiMessage>(); restEventApiStandardResponse.addError(RestEventApiError.PRE_DEFINED.RIA_ERR_G_UNKNOWN); if (e instanceof NullPointerException) { //Log full stacktrace in case of NullPointer logger.error(ExceptionUtils.getFullStackTrace(e)); } ModelAndView mav = new ModelAndView(); mav.addObject(restEventApiStandardResponse); mav.setView(restEventApiDefaultErrorView); return mav; } }