/** * Resolve the exception by iterating over the list of configured exception resolvers. * The first one to return a ModelAndView instance wins. Otherwise {@code null} is returned. */ @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { if (resolvers != null) { for (HandlerExceptionResolver handlerExceptionResolver : resolvers) { ModelAndView mav = handlerExceptionResolver.resolveException(request, response, handler, ex); if (mav != null) { return mav; } } } return null; }
/** * A method available to subclasses for adding default {@link HandlerExceptionResolver}s. * <p>Adds the following exception resolvers: * <ul> * <li>{@link ExceptionHandlerExceptionResolver} * for handling exceptions through @{@link ExceptionHandler} methods. * <li>{@link ResponseStatusExceptionResolver} * for exceptions annotated with @{@link ResponseStatus}. * <li>{@link DefaultHandlerExceptionResolver} * for resolving known Spring exception types * </ul> */ protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new ExceptionHandlerExceptionResolver(); exceptionHandlerExceptionResolver.setContentNegotiationManager(mvcContentNegotiationManager()); exceptionHandlerExceptionResolver.setMessageConverters(getMessageConverters()); if (jackson2Present) { List<ResponseBodyAdvice<?>> interceptors = new ArrayList<ResponseBodyAdvice<?>>(); interceptors.add(new JsonViewResponseBodyAdvice()); exceptionHandlerExceptionResolver.setResponseBodyAdvice(interceptors); } exceptionHandlerExceptionResolver.setApplicationContext(this.applicationContext); exceptionHandlerExceptionResolver.afterPropertiesSet(); exceptionResolvers.add(exceptionHandlerExceptionResolver); ResponseStatusExceptionResolver responseStatusExceptionResolver = new ResponseStatusExceptionResolver(); responseStatusExceptionResolver.setMessageSource(this.applicationContext); exceptionResolvers.add(responseStatusExceptionResolver); exceptionResolvers.add(new DefaultHandlerExceptionResolver()); }
@Override protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { if (handlerExceptionResolvers == null) { return; } for (HandlerExceptionResolver resolver : handlerExceptionResolvers) { if (resolver instanceof ApplicationContextAware) { ((ApplicationContextAware) resolver).setApplicationContext(getApplicationContext()); } if (resolver instanceof InitializingBean) { try { ((InitializingBean) resolver).afterPropertiesSet(); } catch (Exception ex) { throw new IllegalStateException("Failure from afterPropertiesSet", ex); } } exceptionResolvers.add(resolver); } }
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { RestExceptionHandler handler = new RestExceptionHandler(); handler.setOrder(Ordered.HIGHEST_PRECEDENCE + 1); RestErrorDefinition<Exception> authErrorDefinition = new RestErrorDefinition<>(HttpStatus.BAD_REQUEST, ErrorType.ACCESS_DENIED, new DefaultExceptionMessageBuilder() ); Map<Class<? extends Throwable>, RestErrorDefinition> errorMappings = ImmutableMap.<Class<? extends Throwable>, RestErrorDefinition>builder() .put(OAuth2Exception.class, authErrorDefinition) .put(AuthenticationException.class, authErrorDefinition) .putAll(ExceptionMappings.DEFAULT_MAPPING) .build(); DefaultErrorResolver defaultErrorResolver = new DefaultErrorResolver(errorMappings); handler.setErrorResolver(new ReportPortalExceptionResolver(defaultErrorResolver)); handler.setMessageConverters(messageConverters.getConverters()); exceptionResolvers.add(handler); }
@Override protected void configureHandlerExceptionResolvers( List<HandlerExceptionResolver> exceptionResolvers) { super.configureHandlerExceptionResolvers(exceptionResolvers); if (exceptionResolvers.isEmpty()) { addDefaultHandlerExceptionResolvers(exceptionResolvers); } if (this.mvcProperties.isLogResolvedException()) { for (HandlerExceptionResolver resolver : exceptionResolvers) { if (resolver instanceof AbstractHandlerExceptionResolver) { ((AbstractHandlerExceptionResolver) resolver) .setWarnLogCategory(resolver.getClass().getName()); } } } }
private void testLogResolvedExceptionCustomization(final boolean expected) { HandlerExceptionResolver exceptionResolver = this.context .getBean(HandlerExceptionResolver.class); assertThat(exceptionResolver) .isInstanceOf(HandlerExceptionResolverComposite.class); List<HandlerExceptionResolver> delegates = ((HandlerExceptionResolverComposite) exceptionResolver) .getExceptionResolvers(); for (HandlerExceptionResolver delegate : delegates) { if (delegate instanceof AbstractHandlerMethodAdapter) { assertThat( new DirectFieldAccessor(delegate).getPropertyValue("warnLogger")) .is(new Condition<Object>() { @Override public boolean matches(Object value) { return (expected ? value != null : value == null); } }); } } }
@Test public void testForwardingToError() throws Exception { EvernoteException evernoteException = new EvernoteException("MESSAGE", new EDAMUserException()); MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletResponse response = new MockHttpServletResponse(); // mimic how exception info is registered in logic ((HandlerExceptionResolver) errorAttributes).resolveException(request, response, null, evernoteException); request.setAttribute(WebUtils.ERROR_STATUS_CODE_ATTRIBUTE, HttpStatus.BAD_REQUEST.value()); // return error 400 MockHttpServletRequestBuilder requestBuilder = post("/error"); copyRequestAttributes(requestBuilder, request); ResultActions result = mockMvc.perform(requestBuilder.contentType(MediaType.APPLICATION_JSON)); result.andDo(print()); result.andExpect(status().isBadRequest()); result.andExpect(jsonPath("$.timestamp").exists()); result.andExpect(jsonPath("$.status").value(400)); result.andExpect(jsonPath("$.error").exists()); result.andExpect(jsonPath("$.exception").exists()); result.andExpect(jsonPath("$.message").value("MESSAGE")); }
@Test public void handlerExceptionResolver() throws Exception { HandlerExceptionResolverComposite compositeResolver = (HandlerExceptionResolverComposite) mvcConfiguration.handlerExceptionResolver(); assertEquals(0, compositeResolver.getOrder()); List<HandlerExceptionResolver> expectedResolvers = compositeResolver.getExceptionResolvers(); assertEquals(ExceptionHandlerExceptionResolver.class, expectedResolvers.get(0).getClass()); assertEquals(ResponseStatusExceptionResolver.class, expectedResolvers.get(1).getClass()); assertEquals(DefaultHandlerExceptionResolver.class, expectedResolvers.get(2).getClass()); ExceptionHandlerExceptionResolver eher = (ExceptionHandlerExceptionResolver) expectedResolvers.get(0); assertNotNull(eher.getApplicationContext()); }
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { exceptionResolvers.add(new HandlerExceptionResolver() { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { try { log.error("An error has occured: {}", ex.getMessage()); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return new ModelAndView(); } catch (Exception handlerException) { log.warn("Handling of [{}] resulted in Exception", ex.getClass().getName(), handlerException); } return null; } }); }
@Override public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { exceptionResolvers.forEach(resolver -> { if (resolver instanceof ResponseStatusExceptionResolver) ((ResponseStatusExceptionResolver) resolver).setMessageSource(null); }); }
@Bean public HandlerExceptionResolver customExceptionHandlerExceptionResolver() { CustomExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new CustomExceptionHandlerExceptionResolver( true); exceptionHandlerExceptionResolver.getErrorResolver() .add(new ErrorMappingResolver()) .setDefaultErrorResolver(new DefaultErrorResolver()); return exceptionHandlerExceptionResolver; }
/** * Configure a bean to record all exceptions thrown by the controllers * * @return the handler exception resolver */ @Bean public HandlerExceptionResolver sentryExceptionResolver() { if (this.isSentryEnabled) { return new io.sentry.spring.SentryExceptionResolver(); } else { // allow definitions of other handler return null; } }
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { exceptionResolvers.add(new HandlerExceptionResolver() { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) { Result result = new Result(); logger.warn(e.getMessage()); if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误” result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); } else if (e instanceof IllegalArgumentException) { //参数检查异常 result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); }else if (e instanceof NoHandlerFoundException) { result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在"); } else if (e instanceof ServletException) { result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); } else if (e instanceof AccessDeniedException){ result.setCode(ResultCode.PERMIT).setMessage(e.getMessage()); } else { result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员"); String message; if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s", request.getRequestURI(), handlerMethod.getBean().getClass().getName(), handlerMethod.getMethod().getName(), e.getMessage()); } else { message = e.getMessage(); } logger.error(message, e); } responseResult(response, result); return new ModelAndView(); } }); }
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { exceptionResolvers.add(new HandlerExceptionResolver() { public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) { Result result = new Result(); if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误” result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); logger.info(e.getMessage()); } else { result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员"); String message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s", request.getRequestURI(), handlerMethod.getBean().getClass().getName(), handlerMethod.getMethod().getName(), e.getMessage()); logger.error(message, e); } } else { if (e instanceof NoHandlerFoundException) { result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在"); } else { result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage(e.getMessage()); logger.error(e.getMessage(), e); } } responseResult(response, result); return new ModelAndView(); } }); }
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { RestExceptionHandler handler = new RestExceptionHandler(); handler.setOrder(Ordered.HIGHEST_PRECEDENCE); DefaultErrorResolver defaultErrorResolver = new DefaultErrorResolver(ExceptionMappings.DEFAULT_MAPPING); handler.setErrorResolver(new ReportPortalExceptionResolver(defaultErrorResolver)); handler.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter())); exceptionResolvers.add(handler); }
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { // NOTE: Do not change the order! Only first resolution is used. // By default Spring MVC does not log exceptions from @Controller methods. if (!runtimeEnvironmentUtil.isIntegrationTestEnvironment()) { exceptionResolvers.add(new LoggingHandlerExceptionResolver()); } // Process exception using @ExceptionHandler method inside @Controller exceptionResolvers.add(exceptionHandlerExceptionResolver()); // Return status code specified using @ResponseStatus in exception class exceptionResolvers.add(new ResponseStatusExceptionResolver()); // Send HTTP status code depending on the exception which is mapped to error page in web.xml exceptionResolvers.add(new DefaultHandlerExceptionResolver()); }
/** * Returns a {@link HandlerExceptionResolverComposite} containing a list * of exception resolvers obtained either through * {@link #configureHandlerExceptionResolvers(List)} or through * {@link #addDefaultHandlerExceptionResolvers(List)}. * <p><strong>Note:</strong> This method cannot be made final due to CGLib * constraints. Rather than overriding it, consider overriding * {@link #configureHandlerExceptionResolvers(List)}, which allows * providing a list of resolvers. */ @Bean public HandlerExceptionResolver handlerExceptionResolver() { List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<HandlerExceptionResolver>(); configureHandlerExceptionResolvers(exceptionResolvers); if (exceptionResolvers.isEmpty()) { addDefaultHandlerExceptionResolvers(exceptionResolvers); } HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite(); composite.setOrder(0); composite.setExceptionResolvers(exceptionResolvers); return composite; }
@Test @SuppressWarnings("unchecked") public void handlerExceptionResolver() throws Exception { ApplicationContext context = initContext(WebConfig.class); HandlerExceptionResolverComposite compositeResolver = context.getBean("handlerExceptionResolver", HandlerExceptionResolverComposite.class); assertEquals(0, compositeResolver.getOrder()); List<HandlerExceptionResolver> expectedResolvers = compositeResolver.getExceptionResolvers(); assertEquals(ExceptionHandlerExceptionResolver.class, expectedResolvers.get(0).getClass()); assertEquals(ResponseStatusExceptionResolver.class, expectedResolvers.get(1).getClass()); assertEquals(DefaultHandlerExceptionResolver.class, expectedResolvers.get(2).getClass()); ExceptionHandlerExceptionResolver eher = (ExceptionHandlerExceptionResolver) expectedResolvers.get(0); assertNotNull(eher.getApplicationContext()); DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(eher); List<Object> interceptors = (List<Object>) fieldAccessor.getPropertyValue("responseBodyAdvice"); assertEquals(1, interceptors.size()); assertEquals(JsonViewResponseBodyAdvice.class, interceptors.get(0).getClass()); LocaleContextHolder.setLocale(Locale.ENGLISH); try { ResponseStatusExceptionResolver rser = (ResponseStatusExceptionResolver) expectedResolvers.get(1); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); MockHttpServletResponse response = new MockHttpServletResponse(); rser.resolveException(request, response, context.getBean(TestController.class), new UserAlreadyExistsException()); assertEquals("User already exists!", response.getErrorMessage()); } finally { LocaleContextHolder.resetLocaleContext(); } }
@Test public void configureExceptionResolvers() throws Exception { List<WebMvcConfigurer> configurers = new ArrayList<WebMvcConfigurer>(); configurers.add(new WebMvcConfigurerAdapter() { @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { exceptionResolvers.add(new DefaultHandlerExceptionResolver()); } }); delegatingConfig.setConfigurers(configurers); HandlerExceptionResolverComposite composite = (HandlerExceptionResolverComposite) delegatingConfig.handlerExceptionResolver(); assertEquals("Only one custom converter is expected", 1, composite.getExceptionResolvers().size()); }
/** * {@inheritDoc} * * Error page is tried to be resolved at public/error, the exception attribute is set to {@literal exception}. */ @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { SimpleMappingExceptionResolver smer = new SimpleMappingExceptionResolver(); smer.setDefaultErrorView("public/error"); smer.setExceptionAttribute("exception"); exceptionResolvers.add(smer); }
@ConditionalOnMissingBean(HandlerExceptionResolver.class) public @Bean SimpleMappingExceptionResolver simpleMappingExceptionResolver() { SimpleMappingExceptionResolver smer = new SimpleMappingExceptionResolver(); smer.setDefaultErrorView("public/error"); smer.setExceptionAttribute("exception"); return smer; }
@Bean public HandlerExceptionResolver handlerExceptionResolver() { return new HandlerExceptionResolver() { @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { return null; } }; }
private List<HandlerExceptionResolver> extractResolvers() { List<HandlerExceptionResolver> list = new ArrayList<HandlerExceptionResolver>(); list.addAll(this.beanFactory.getBeansOfType(HandlerExceptionResolver.class) .values()); list.remove(this); AnnotationAwareOrderComparator.sort(list); return list; }
@Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { if (this.resolvers == null) { this.resolvers = extractResolvers(); } for (HandlerExceptionResolver mapping : this.resolvers) { ModelAndView mav = mapping.resolveException(request, response, handler, ex); if (mav != null) { return mav; } } return null; }
/** * We need to override the base method so this "@Bean" will get invoked and ultimately call configureMessageConverters. Otherwise, it doesn't get called. * This implementation doesn't do anything except call the super method. * * @return the RequestMappingHandlerAdapter. */ @Bean @Override public HandlerExceptionResolver handlerExceptionResolver() { return super.handlerExceptionResolver(); }
@Override protected void configureHandlerExceptionResolvers( List<HandlerExceptionResolver> exceptionResolvers) { addDefaultHandlerExceptionResolvers(exceptionResolvers); // The index is 1, in order to add it after the ExceptionHandlerExceptionResolver exceptionResolvers.add(1, new UncheckedExceptionResolver(mappingJackson2JsonView(), messageSource())); }
protected HandlerExceptionResolver[] exceptionResolvers() { HandlerExceptionResolver defaultHandlerExceptionResolver = new DefaultHandlerExceptionResolver(); return new HandlerExceptionResolver[]{uncheckedExceptionResolver(), defaultHandlerExceptionResolver}; }
/** * Resolves specific types of exceptions to corresponding logical view names * for error views. * * <p> * View name resolved using bean of type InternalResourceViewResolver * (declared in {@link MvcViewConfig}). */ @Override public void configureHandlerExceptionResolvers( List<HandlerExceptionResolver> exceptionResolvers) { SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); // results into 'WEB-INF/jsp/exception.jsp' exceptionResolver.setDefaultErrorView("exception"); // needed otherwise exceptions won't be logged anywhere exceptionResolver.setWarnLogCategory("warn"); exceptionResolvers.add(exceptionResolver); }
@Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) { final ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver(); resolver.setWarnLogCategory(resolver.getClass() .getName()); exceptionResolvers.add(resolver); }