Why does Spring MVC respond with 404 and say "There is no mapping for the HTTP request with the URI [...] in the DispatcherServlet"?

I am writing a Spring MVC application deployed on Tomcat. See the following minimum, complete, and testable example.

public class Application extends AbstractAnnotationConfigDispatcherServletInitializer { protected Class<?>[] getRootConfigClasses() { return new Class<?>[] { }; } protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { SpringServletConfig.class }; } protected String[] getServletMappings() { return new String[] { "/*" }; } } 

Where SpringServletConfig is located

 @Configuration @ComponentScan("com.example.controllers") @EnableWebMvc public class SpringServletConfig { @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; } } 

Finally, I have @Controller in the com.example.controllers package

 @Controller public class ExampleController { @RequestMapping(path = "/home", method = RequestMethod.GET) public String example() { return "index"; } } 

The context name of my application is Example . When I submit a request for

 http://localhost:8080/Example/home 

the application responds with HTTP Status 404 and registers the following

 WARN osweb.servlet.PageNotFound - No mapping found for HTTP request with URI '[/Example/WEB-INF/jsps/index.jsp]' in 'DispatcherServlet' with name 'dispatcher' 

I have a JSP resource on /WEB-INF/jsps/index.jsp . I was expecting Spring MVC to use my controller to process the request and redirect to the JSP, so why does it respond with 404?




This should be a canonical post for questions about this warning post.

+78
java spring spring-mvc servlets
Jan 10 '17 at 19:53 on
source share
6 answers

Your standard Spring MVC application will serve all requests through the DispatcherServlet that you registered in your servlet container.

DispatcherServlet looks at its ApplicationContext and, if available, the ApplicationContext registered in the ContextLoaderListener for special beans, it must set its request servicing logic. These components are described in the documentation .

Perhaps most important, beans like HandlerMapping map

incoming requests to handlers and a list of pre- and post-processors (hook-handlers) based on some criteria, the details of which vary depending on the implementation of HandlerMapping . The most popular implementation supports annotated controllers, but other implementations exist as well.

The HandlerMapping Javadoc further describes how implementations should behave.

DispatcherServlet finds all the beans of this type and registers them in some order (can be configured). While serving the request, the DispatcherServlet goes through these HandlerMapping objects and tests each of them with getHandler to find one that can handle the incoming request, presented as an HttpServletRequest standard. Starting from 4.3.x, if it does not find it , it logs a warning about what you see

No mapping found for HTTP request with URI [/some/path] in DispatcherServlet named SomeName

and either throws a NoHandlerFoundException , or immediately sends a response with a status code 404 "Not found".

Why didnโ€™t DispatcherServlet find a HandlerMapping that could handle my request?

The most common HandlerMapping implementation is RequestMappingHandlerMapping , which handles the registration of @Controller as handlers (actually their annotated @RequestMapping methods). You can either declare a bean of this type yourself (using @Bean or <bean> , or using another mechanism), or use the built-in parameters . It:

  1. Annotate your @Configuration class with @EnableWebMvc .
  2. Declare the <mvc:annotation-driven /> element in your XML configuration.

As described in the link above, both of them will register the RequestMappingHandlerMapping bean (and many other things). However, HandlerMapping not very useful without a handler. RequestMappingHandlerMapping expects some @Controller , so you also need to declare them using the @Bean methods in the Java configuration or the <bean> declarations in the XML configuration or by scanning components of the annotated @Controller classes in both. Make sure these beans are present.

If you receive a warning message and the number 404 and correctly configure all of the above, you send a request for an invalid URI that is not processed by the @RequestMapping detected annotated handler method.

The spring-webmvc offers other built-in implementations of HandlerMapping . For example, BeanNameUrlHandlerMapping maps

from URLs to beans with names starting with a slash ("/")

and you can always write your own. Obviously, you must make sure that the request you send matches at least one of the registered HandlerMapping object HandlerMapping .

If you do not implicitly or explicitly register any HandlerMapping (or if detectAllHandlerMappings is true ), DispatcherServlet register some default values . They are defined in DispatcherServlet.properties in the same package as the DispatcherServlet class. These are BeanNameUrlHandlerMapping and DefaultAnnotationHandlerMapping (which is similar to RequestMappingHandlerMapping , but not recommended).

Debugging

Spring MVC will register handlers registered through RequestMappingHandlerMapping . For example, @Controller as

 @Controller public class ExampleController { @RequestMapping(path = "/example", method = RequestMethod.GET, headers = "X-Custom") public String example() { return "example-view-name"; } } 

will register the next at the INFO level

 Mapped "{[/example],methods=[GET],headers=[X-Custom]}" onto public java.lang.String com.spring.servlet.ExampleController.example() 

This is a description of the registered display. When you see a warning that the handler was not found, compare the URI in the message with the display specified here. All restrictions specified in @RequestMapping must comply with Spring MVC for selecting a handler.

Other implementations of HandlerMapping register their own statements, which should point to their mappings and corresponding handlers.

Likewise, enable Spring logging at the DEBUG level to see which beans are being registered by Spring. He must report which annotated classes he finds, which packets he scans, and which components he initializes. If you are not expecting, review the ApplicationContext configuration.

Other common mistakes

DispatcherServlet is just a typical Java EE Servlet . You register it in your typical <web.xml> <servlet-class> and <servlet-mapping> declarations, either directly through ServletContext#addServlet in WebApplicationInitializer , or using any other mechanism used by Spring boot. Therefore, you must rely on the URL mapping logic specified in the servlet specification, see chapter 12. See also

  • How are servlet URL mappings used in web.xml?

Given this, a common mistake is to register a DispatcherServlet with the display of the URL /* , returning the view name from the @RequestMapping handler @RequestMapping and waiting for the JSP to render. For example, consider a handler method, for example

 @RequestMapping(path = "/example", method = RequestMethod.GET) public String example() { return "example-view-name"; } 

with InternalResourceViewResolver

 @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; } 

you can expect the request to be redirected to the JSP resource along the path /WEB-INF/jsps/example-view-name.jsp . It will not happen. Instead, by accepting the context name Example , the DisaptcherServlet will report

No mapping was found for the HTTP request with the URI [/Example/WEB-INF/jsps/example-view-name.jsp] in the DispatcherServlet named "dispatcher"

Since the DispatcherServlet mapped to /* and /* matches everything (except for exact matches that have a higher priority), a DispatcherServlet will be selected to handle forward from JstlView ( InternalResourceViewResolver returned). In almost every case, the DispatcherServlet will not be configured to handle such a request .

Instead, in this simplified case, you should register the DispatcherServlet in / , marking it as the default servlet. The default servlet is the last match for the request. This will allow your typical servlet container to choose the internal servlet implementation mapped to *.jsp to process the JSP resource (for example, Tomcat has a JspServlet ) before attempting to use the default servlet.

This is what you see in your example.

+83
Jan 10 '17 at 19:53 on
source

I solved my problem when, in addition to the one described above: `

 @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver vr = new InternalResourceViewResolver(); vr.setPrefix("/WEB-INF/jsps/"); vr.setSuffix(".jsp"); return vr; } 

added tomcat-embed-jasper:

 <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> 

`from: JSP file does not appear in Spring boot web application

+3
Mar 14 '17 at 12:04 on
source

In my case, I followed the Interceptors Spring documentation for version 5.1.2 (when using Spring Boot v2.0.4.RELEASE ), and the WebConfig class had the @EnableWebMvc annotation, which seems to conflict with something else in my application, which prevents the proper resolution of my static resources (i.e. CSS or JS files are not returned to the client).

After trying many different things, I tried to remove @EnableWebMvc and it worked!

Edit: Here is the reference documentation that says you should remove the @EnableWebMvc annotation

Apparently, in my case, at least I am already setting up my Spring application (although not using web.xml or any other static file, it is definitely programmatic), so this was a conflict there.

+2
Nov 12 '18 at 21:42
source

I came across another cause of the same error. This may also be due to class files not generated for your controller.java file. As a result, the dispatcher servlet mentioned in web.xml cannot match it with the corresponding method in the controller class.

 @Controller Class Controller{ @RequestMapping(value="/abc.html")//abc is the requesting page public void method() {.....} } 

In eclipse in Project-> select clean โ†’ Build Project. Give a check if the class file was generated for the controller file in lines in your workspace.

0
Jan 16 '17 at 11:54 on
source

For me, I found that my target classes were generated in a folder template different from the original. Perhaps in eclipse I am adding folders to store my controllers, and not adding them as packages. As a result, I determined the wrong path in the spring config.

My target class generated classes under the app, and I meant com.happy.app

 <context:annotation-config /> <context:component-scan base-package="com.happy.app"></context:component-scan> 

I added packages (not folders) for com.happy.app and moved files from folders to packages in eclipse, and this solved the problem.

0
Feb 16 '19 at 22:05
source

Clean your server. Maybe uninstall the server and add the project again and run.

  1. Stop Tomcat Server

  2. Right-click on the server and select "Clear"

  3. Right-click the server again and select "Clean Tomcat working directory."

-one
Feb 18 '19 at 5:12
source



All Articles