Spring @ControllerAdvice not applied when packageName or assignableTypes is specified

Dirk Bolte :

A sample project demonstrating the issue can be found at: https://github.com/dirkbolte/javaexceptionhandlertest

I have a controller which is declared to produce JSON content:

@RestController
public class TestController {

    @GetMapping(value = "exception", produces = MediaType.APPLICATION_JSON_VALUE)
    public void test() {
    }
}

The corresponding controller advice should map any exception to a BAD_REQUEST :

@RestControllerAdvice
public class MyExceptionHandler {
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = Exception.class)
    public void exceptionhandler() {
    }
}

I test that a call with a wrong accept header results in the correct error response code (as procudes specifies something different):

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class TestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test() throws Exception {
        mockMvc.perform(
            MockMvcRequestBuilders.get("/exception")
                                  .accept(MediaType.APPLICATION_PDF)
        ).andExpect(status().isBadRequest());
    }
}

The code above "fails successfully" :-) . In my production code I want to limit the controller advice to a certain controller (alternatively to a certain package), thus I specified assignableTypes on @ControllerAdvice: @RestControllerAdvice(assignableTypes = TestController.class) . Now the test fails as the exception handler isn't called anymore. Same happens when specifying basePackages or basePackageClasses - or when using an interface.

The version on GitHub shows the test failure, so I hope it is easy to reproduce.

How can I use a ControllerAdvice explicitly for one or more Controller?

R.G :

The requested URL will not get mapped to any Controller method here. This would result in a Status 406 error (due to the specified accept type). Since no exception is thrown from the Controller methods the ControllerAdvice would not be invoked.

On dispatcher level, org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#getExceptionHandlerMethod will be called with handlerMethod = null which is why only generic controller advices are applied.

The ControllerAdvice would work here, if the request contains additional metadata that the controller method is configured for and/or an exception is thrown from within that method.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=194803&siteId=1