26

I am having trouble getting @ControllerAdvice to work. I updated my namespace location, which were 3.1 in my xml files. I moved the class with the controller to the same package as the controller. I am using 3.2.0 release jars. If I put the @ExceptionHandler annotation in the controller code, it works, but not in a separate class with the @ControllerAdvice. When the @ControllerAdvice class fails, I get my uncaught exception handler view. Anyone have ideas on how to trouble shoot this one?

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
Joe
  • 747
  • 3
  • 8
  • 21

7 Answers7

17

If you use classpath scanning, probably you have to add new include filter to your <context:component-scan> element:

<context:include-filter type="annotation" 
    expression="org.springframework.web.bind.annotation.ControllerAdvice" />

Default scanning does not lookup this annotation, following spring-context-3.2.xsd for component-scan:

"Scans the classpath for annotated components that will be auto-registered as Spring beans. By default, the Spring-provided @Component, @Repository, @Service, and @Controller stereotypes will be detected."

tunguski
  • 763
  • 7
  • 12
  • That makes sense why it does not working. I will test it tonight and see if it works. – Joe Sep 27 '13 at 12:42
  • BEWARE! It works out of the box, but this annotation is necessary when you are unit testing! – Chexpir Mar 07 '14 at 14:49
  • 2
    Also make sure that this is in the webmvc context file and not the main application context. – Eric B. Apr 05 '14 at 16:53
10

For this problem, The first thing is confirming your config,

  1. You need make sure that the @ControllerAdvice Class under your component-scan base package.
  2. Make suer you use <mvc:annotation-driven/> in your spring-servlet.xml. or have @EnableWebMvc in your @ControllerAdvice Class

When you have the config right, the ControllerAdvice should already work, Now you said You got your uncaught exception handler view. I guess you got that in your InegrationTest, And you used mockMvc to test that, If so, you need put @WebAppConfiguration and build mokcMvc as follow:

 @Autowired
private WebApplicationContext wac;

mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();

Using standaloneSetup(controller) will not work because lack of WebApplicationContext.

Arne Burmeister
  • 20,046
  • 8
  • 53
  • 94
xianlinbox
  • 969
  • 10
  • 10
  • In my case @EnableWebMvc was enough – Igor G. Apr 03 '14 at 11:46
  • You can also add the ControllerAdvice class in the standaloneSetup: `MockMvcBuilders.standaloneSetup(new MyController(myService)) .setControllerAdvice(new MyControllerAdvice()).build();` – Adrian Cosma Apr 21 '16 at 11:58
7

There is no extra configuration required. It should just work. Look at this link for more details. This provide very simple example:

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118
Krishna
  • 7,154
  • 16
  • 68
  • 80
7

I had this same problem, in my case the problem was that there was a dependent library that had inside it a class with the @ControllerAdvice and @Order(Ordered.HIGHEST) annotation, to solve the problem I added the @Order(Ordered.HIGHEST) annotation in my classe, and now it works.

Since my exception class is in the same controller package spring gave my class higher priority even though both classes have the same @Order(Ordered.HIGHEST)

@ControllerAdvice
@Order(Ordered.HIGHEST)
public class RestResponseEntityExceptionHandler 
  extends ResponseEntityExceptionHandler { 
3

I struggled with the same problem where my @ControllerAdvice class would not load while unit testing REST controllers' exceptions. If you are using spring boot (version 4) then you can use additional methods added by spring to load controller advice classes in standalone setting up your controllers.

mockMvc = MockMvcBuilders
   .standaloneSetup(new YourRestController())
   .setControllerAdvice(new ControllerAdviceClass())
   .build();

This will straight-away initialize your controller advice class and your Junit test should be able to jump in to @ExceptionHandler methods defined in your controller advice class.

Vasia Zaretskyi
  • 349
  • 3
  • 9
Vishal
  • 1,963
  • 2
  • 20
  • 23
  • Holy shit, thank you so much!! BTW, you have a missing parenthesis. It should be `MockMvcBuilders.standaloneSetup(new YourRestController()).setControllerAdvice( ...`. Note the parenthesis after `YourRestController()`. – Cameron Hudson Oct 12 '19 at 04:46
1

For me, @ControllerAdvice was not working at all cost. Even adding @EnableWebMvc or @WebAppConfiguration didn't make any change.

The way I was able make it working was,

  • adding @ExceptionHandler methods for my AbstractController class, the class that all the other controllers are extending upon.

I think @ControllerAdvice is supposed to do the same thing, i.e. compile the @ExceptionHandler methods defined under the class specified by @ControllerAdvice, into a common place where every controller can refer from. But unfortunately it was not working for me.

Supun Wijerathne
  • 11,964
  • 10
  • 61
  • 87
0

I solved it by defining ControlAdvice class in Configuration beans as shown below:

@Primary 
@Bean 
public RestResponseEntityExceptionHandler restResponseEntityExceptionHandler (){    
       return new RestResponseEntityExceptionHandler (); 
}
humanshu
  • 139
  • 1
  • 6