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?
Comment From: wilkinsona
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
Comment From: Harown
Unfortunately, omitting @EnableWebMvc has no effect.
Comment From: wilkinsona
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.
Comment From: Harown
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.
Comment From: Berg-it
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
Comment From: bclozel
@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.
Comment From: Berg-it
@bclozel: You are right! I'll see how can I active this property. Thnak you
Comment From: AndRossi
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.
Comment From: bclozel
@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.
Comment From: AndRossi
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 :/
Comment From: bclozel
You're mapping everything with your static path pattern, so this behavior is expected. For further questions, please use StackOverflow.
Comment From: zhangjiaxin281
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
Comment From: bclozel
@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.
Comment From: NikhilAdsul
Can anyone help me for that i am getting The type NoSuchRequestHandlingMethodException is deprecated. and error: package org.springframework.web.servlet.mvc.multiaction does not exist
in spring MVC application. with spring version 5.7.2
Comment From: bclozel
@NikhilAdsul this doesn't seem related at all. Could you try asking on StackOverflow? You should add more information as well: a complete stacktrace, your build file (gradle or maven) at a minimum.
Comment From: NikhilAdsul
Can anyone help me for that i am getting The type NoSuchRequestHandlingMethodException is deprecated. and error: package org.springframework.web.servlet.mvc.multiaction does not exist
in spring MVC application. with spring version 5.7.2
ok