Spring-boot: Spring not throwing NoHandlerFoundException anymore

Created on 18 May 2017  路  13Comments  路  Source: spring-projects/spring-boot

After we upgraded from Spring Boot 1.4.0 to 1.5.3 our web application does not throw the NoHandlerFoundException anymore. Configuration looks like the following:

in application.properties:

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

the corresponding exception controller:

@ControllerAdvice
@EnableWebMvc
public class ExceptionController 
{
       // works
       @ExceptionHandler(AccessDeniedException.class)
    public String handleAccessDeniedException(AccessDeniedException ex, HttpServletRequest request) {
        return "403";
    }

    // doesn't work anymore
    @ExceptionHandler(NoHandlerFoundException.class)
    public String handleNotFoundError(NoHandlerFoundException ex, HttpServletRequest request) {
        return "404";
    }
}

We had no problems with Spring 1.4.0 but it stopped working in 1.5.3. Why is the exception not thrown anymore?

invalid

Most helpful comment

While preparing a sample application we've found the culprit:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
            "classpath:/META-INF/resources/", "classpath:/resources/",
            "classpath:/static/", "classpath:/public/" };

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
    }
}

Replacing the URl pattern with the subfolder containing the static resources spring.mvc.throw-exception-if-no-handler-found=true have the desired effect. Thank you.

All 13 comments

Did you have @EnableWebMvc with both 1.4 and 1.5? I would expect it to turn off the auto-configuration of Spring MVC making spring.mvc.throw-exception-if-no-handler-found=true have no effect

Unfortunately, omitting @EnableWebMvc has no effect.

Something that is, I think, the same as you are doing works for me with both 1.4.6 and 1.5.3. Can you please provide a small sample that reproduces the problem you're seeing? Something that works with 1.4.0 but fails with 1.5.3 would be ideal.

While preparing a sample application we've found the culprit:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
            "classpath:/META-INF/resources/", "classpath:/resources/",
            "classpath:/static/", "classpath:/public/" };

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
    }
}

Replacing the URl pattern with the subfolder containing the static resources spring.mvc.throw-exception-if-no-handler-found=true have the desired effect. Thank you.

By default, the聽DispatcherServlet聽does not throw a聽NoHandlerFoundException.聽You need to enable that:

I use Spring Boot 1.5.4.RELEASE:

I added
@EnableWebMvc

and in my prop file I added

server.error.whitelabel.enabled: false
spring.mvc.throw-exception-if-no-handler-found: true

@Berg-it adding @EnableWebMvc should totally switch off Spring Boot's auto-configuration for Spring MVC - so all spring.mvc.* configuration properties will be ignored. See the reference documentation on that.

@bclozel: You are right! I'll see how can I active this property. Thnak you

Sorry to re-open this issue, but I am experiencing a very closely related problem.
I am developing a small webapp with Spring Boot, HTML controllers and Thymeleaf.

I am not using @EnableWebMvc (and I would prefer not to use it).
What I would like to do is both these two things :

  • make sure that an exception is thrown if no handlers are found
  • have my static resources available for the client

Is there a way to accomplish this?

My issue is basically the same as this StackOverflow page: https://stackoverflow.com/questions/39973945/no-handler-found-exception-and-static-recources-in-spring-boot

Thanks.

@AndRossi the answer on that SO thread is right.

When the resource handler doesn't find a static resource to serve, it's not delegating to the next handler in line, but rather responding with an HTTP 404. The only way to achieve what you want is to map your static resources under a specific sub-path like /static configure the spring.mvc.throw-exception-if-no-handler-found configuration property. That exception will be sent as long as the static resources handler is not involved.

Hi @bclozel, thank you for the lightning-fast answer!

Unfortunately I have tried that answer but it does not seem to work in my scenario.
This is what my configuration currently looks like:

spring.thymeleaf.cache:false

spring.servlet.multipart.max-file-size=100MB
spring.servlet.multipart.max-request-size=100MB

spring.datasource.url=jdbc:postgresql://localhost:5432/db-name
spring.datasource.username=...
spring.datasource.password=...
spring.jpa.properties.hibernate.default_schema=db.name

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.hibernate.ddl-auto = update

spring.mvc.throw-exception-if-no-handler-found=true
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/static/

In my environment, it does allow the client to get the static resources, but missing URIs do not throw any exceptions :/

You're mapping everything with your static path pattern, so this behavior is expected. For further questions, please use StackOverflow.

I'm sorry, I asked again,@bclozel, @AndRossi ,Set by the @androssi method, getting static resources is fine in my environment, but the lack of uris does not throw NoHandlerFoundException

I want to do both at the same time:

  • If the handler cannot be found, be sure to throw an exception
  • Provide my static resources to customers

But the existing configuration has not been solved

application.yaml

spring:
  resources:
    static-locations: "classpath:/static/"
  mvc:
    throw-exception-if-no-handler-found: true
    static-path-pattern : "/**"

ControllerExceptionAdvice

@ControllerAdvice
public class ControllerExceptionAdvice {

    @ExceptionHandler(NoHandlerFoundException.class)
    public void noHandlerFoundExceptionExceptionResolvers(HttpServletResponse response) throws Exception {
        writeResponse(response, JsonResult.JsonResult(false, "resources lost!", 404));
    }


    private void writeResponse(HttpServletResponse response, JsonResult message) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        response.getWriter().write(Json.encode(message)  );
    }

}

https://github.com/zhangjiaxin281/testNoHandler.git

@zhangjiaxin281 same answer, actually.
The NoHandlerFoundException is thrown when no HandlerMapping has been found; HandlerMapping as in RequestMappingHandlerMapping or SimpleHandlerMapping, not as "an annotated controller method that handles the request".

In your case, when an incoming request comes in at "/something" and no controller handler is detected with RequestMappingHandlerMapping , the next registered HandlerMapping instances are considered. Since you've registered static resource handling on /**, this means that it will handle /**, so the NoHandlerFoundException will never be thrown.

Now the static resources handling might respond with an HTTP 404, but this is an expected response for such a handler. Either the static resource is there and we respond with it, or we respond with a 404.

Was this page helpful?
0 / 5 - 0 ratings