@ControllerAdvice Not Shooting

I am working on a Spring MVC / Webflow application (version 3.2) and am trying to handle exception handling, where I can output my own exception message to the log file and error.jsp. The problem I am facing is that the exception handler does not start. I created the following class and annotated it with " @ControllerAdvice " and put it in the same package as my controller, which throws an exception:

 @ControllerAdvice public class MyCustomExceptionController { @ExceptionHandler(MyCustomException.class) public ModelAndView handleMyException(MyCustomException ex) { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("/error/error"); modelAndView.addObject("errorId", ex.getErrorId()); modelAndView.addObject("message", ex.getErrorMessage()); return modelAndView; } } 

and added the following to the mvc-config file:

 <mvc:annotation-driven/> 

And included the following in his app-config file:

 <context:component-scan base-package="package containing my controllers and MyCustomExceptionController"> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> </context:component-scan> 

Any ideas why this is not working?

+8
java spring spring-mvc exception-handling
source share
2 answers

The <mvc:annotation-driven/> element implicitly registers a ExceptionHandlerExceptionResolver bean. This class has an initExceptionHandlerAdviceCache() method, which scans beans in context to find those whose class type is annotated using @ControllerAdvice .

He does this by first calling ControllerAdviceBean.findAnnotatedBeans(ApplicationContext) . Inside this method, ApplicationContext#getBeanDefinitionNames() . The javadoc of this method states

Does not consider any hierarchy in which the factory may participate

To clarify what this means. When you declare a ContextLoaderListener in a deployment descriptor, it loads what we call the root or ApplicationContext and makes it available in ServletContext . When you declare a DispatcherServlet , it creates its own ApplicationContext servlet and uses any ApplicationContext that it finds in the ServletContext attributes loaded by the ContextLoaderListener as the parent in this context. Hierarchy looks like this

 Root ApplicationContext // loaded by the ContextLoaderListener | Servlet ApplicationContext // loaded by the DispatcherServlet 

Each ApplicationContext has access to beans in parent contexts, but not vice versa.

The above method does not recommend using beans in parent contexts and therefore only has access to beans in the current ApplicationContext ( BeanFactory really).

As such, if your

 <context:component-scan .../> 

declared in the root of the ApplicationContext , as I assume, from the name app-config , but

 <mvc:annotation-driven /> 

is declared in the ApplicationContext servlet, again taking from mvc-config , then ExceptionHandlerExceptionResolver looks for @ControllerAdvice beans it won't find. It looks for beans in the servlet context, but they are not there, they are in the root context.

+8
source share

If someone else encounters a problem like this, I discovered an error that I had.

I had only one RequestMapping ( http: // localhost: 8080 / myapp / verify / verify )

In the InterceptorController in the PreHandle method, I explicitly threw an exception -> throw new MyCustomException("error","error.jsp") to check my handling of @ControllerAdvice Exception .

When I switched to http: // localhost: 8080 / myapp / , I would see that the interceptor controller was called, my custom exception was thrown, but the @ControllerAdvice class with my @ExceptionHandler(MyCustomException.class) never called.

I added @RequestMapping(value="/") and it solved my problems. Since I was trying to navigate to a URI that did not have @RequestMapping associated with it, I was getting a 'NoHandlerFoundException' that 'NoHandlerFoundException' my Exception from the bubble up.

In short, make sure that the URI you are trying to call has an associated @RequestMapping associated with it or a method in the ExceptionHandler class to work with NoHandlerFoundException .

Hope this helps.

0
source share

All Articles