0

I know this is usually an issue that happens the other way around, so I am caught a little of guard here :D

I have built a user-management backend that provides a UI with data. When this architecture is deployed on our dev-server, everything works beautifully. However, as soon as I try to run the integration tests (which we do using a maven cargo tomcat) or if I use the war file in a local tomcat, the exception handlers aren't used at all. Spring simply displays a standard 500 response with the exception transformed into the body.

Perusing SO for similar issues has only resulted in the advice that I should use @EnableWebMVC, but that is neither applicable to what my backend is trying to accomplish, nor does it change anything.

How should I go about looking for the solution to this issue? Specifically, can I somehow observe if my controlleradvice is even scanned, and is there a reason why it might not be?

EDIT: These are the relevant files:

SpringConfiguration:

@Configuration
@ComponentScan(basePackageClasses = {UserManagementSpringConfiguration.class})
@EnableWebSecurity
public class UserManagementSpringConfiguration {

@Configuration
public static class ResourceMappingConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/ui/*/usermanagement").setViewName("forward:/usermanagement-ui/index.html");
//            registry.addViewController("/ui/*/*/generator/").setViewName("forward:/generator-ui/index.html");
        registry.addViewController("/ui/*/usermanagement/*").setViewName("forward:/usermanagement-ui/index.html");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // cache setting, otherwise fonts are not loaded in IE over https
        CacheControl cacheControl = CacheControl.noCache().mustRevalidate();
        registry.addResourceHandler("/ui/**/*").addResourceLocations("/usermanagement-ui/")
                    .setCacheControl(cacheControl);
        }

    }

}

ControllerAdvice:

@ControllerAdvice
public class CustomResponseEntityExceptionHandler {

    public static final Logger LOG = EISLoggerFactory.getLogger(CustomResponseEntityExceptionHandler.class);

    @PostConstruct
    public void postConstruct() {
        LOG.debug("CustomExceptionHandler loaded and ready for use");
    }

    @ExceptionHandler(PasswordMismatchException.class)
    public final ResponseEntity<ErrorDetails> handlePasswordChangeMismatch(
            PasswordMismatchException ex,
            WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(
                new Date(),
                ex.getMessage(),
                request.getDescription(false),
                MessageKeys.mismatchedPassword);
        return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
    }
}
adiga
  • 34,372
  • 9
  • 61
  • 83
Alex Eggers
  • 328
  • 3
  • 16
  • 1
    Maybe adding in the controlleradvice a method which prints something in logs and annotate the method with [@PostConstruct](http://docs.jboss.org/jbossas/javadoc/7.1.2.Final/javax/annotation/PostConstruct.html) could help for debuging –  Nov 27 '18 at 12:59
  • @ValentinCarnu That's a really good idea! I'll try it and see what happens. – Alex Eggers Nov 27 '18 at 13:35
  • @ValentinCarnu It seems the ControllerAdvice is getting loaded. Just doesn't seem to be used. – Alex Eggers Nov 27 '18 at 15:54
  • does the application run as a war inside a tomcat server in the dev environment? –  Nov 27 '18 at 16:12
  • Yes. Just a Tomcat server. – Alex Eggers Nov 28 '18 at 08:42
  • Check if there are any [@Profile annotation](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html), this is just a shot in the dark as the yesterday tests shown the bean is loaded. Maybe you can post the controlleradvice and the parts of the configuration which are relevant for the controller advice. Also check this [Springboot exception handler doesn't catch exception](https://stackoverflow.com/questions/41191349/springboot-exception-handler-doesnt-catch-exception) maybe you find a hint –  Nov 28 '18 at 10:18
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/184395/discussion-between-valentin-carnu-and-alex-eggers). –  Nov 28 '18 at 11:15

1 Answers1

0

It turns out that one of the modules that we wrote and that my project contains defines an ExceptionHandler for Throwable.class. On my machine, this ControllerAdvice is registered before my own ControllerAdvice, which causes Spring to look there first. Since Throwable fits the bill, Spring asks no further questions and just uses that handler.

The solution to my immediate problem was to add @Order(Ordered.HIGHEST_PRECEDENCE) to my ControllerAdvice. Since the exceptions I define within are quite specific, this will not cause any issues.

I have yet to find an explanation for why the order in which the two ControllerAdvice classes are registered is so consistently different between my machine and our dev server. Will update if I find anything. For now, I consider this issue to be answered.

This SO question was essential to solving this particular problem. Perhaps it helps someone in the future to link it here: Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers

Thanks to ValentinCarnu for pointing me to it!

Alex Eggers
  • 328
  • 3
  • 16