How does the DispatcherServlet, Resolver and Controllers interact? [duplicate]
Asked Answered
I

2

17

Ok so I have encountered the fairly common errror:

WARNING: No mapping found for HTTP request with URI [/WEB-INF/jsp/index.jsp] in DispatcherServlet with name 'app'

I'm looking at the existing answers and I've not seen a really good explanation of how the components interact. Seeing as I can't solve my issue based on the existing answers, I'm hoping someone can provide a detailed explanation of the function of DispatcherServlet and Resolvers.

Developing in Eclipse, I have the following structure:

/src/com/whiuk/philip/web/controller/IndexController.java
/WebContent
/WebContent/WEB-INF
/WebContent/WEB-INF/web.xml
/WebContent/WEB-INF/app-servlet.xml
/WebContent/WEB-INF/jsp/index.jsp

Eclipse Deployment Assembly means it deploys as follows:

/src -> WEB-INF/classes
/WebContent -> /
/ivy.xml[*] -> WEB-INF/lib

I have a web.xml file that defines a DispatcherServlet and a mapping to all files (/*)

<servlet>
    <servlet-name>app</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

I have a app-servlet.xml file that scans the packages and defines a InternalResourceViewResolver:

<context:component-scan base-package="com.whiuk.philip.web" />
<mvc:annotation-driven />
<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

I have a IndexController that has a RequestMapping for index:

 @Controller
 public class IndexController {
      @RequestMapping(value = "/index", method = RequestMethod.GET)
      public ModelAndView index() {
             return new ModelAndView();
      }
 }

Logs show this is registered:

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
INFO: Mapped "{[/index],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}"
onto public org.springframework.web.servlet.ModelAndView 
com.whiuk.philip.web.controller.IndexController.index()

Finally I have a index.jsp file.

Can someone please explain what the misconfiguration is that results in the error shown at the top and, if possible, provide a sentence or so on the purpose of DispatcherServlet, Resolvers and how they feed into Controllers.

Irizarry answered 23/12, 2012 at 23:49 Comment(0)
V
8

Essentially what is happening is, since you have Spring's DispatcherServlet mapped to /*, it tends to be called for every request(which is okay), but unfortunately gets invoked even when the request gets dispatched to the JSP page (/WEB-INF/jsp/index.jsp), instead of the containers default servlet getting invoked.

The fix that I am aware of is the following:

Map it to the default servlet path / instead:

<servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

One issue that you would see with above is that the resources under the root of your webapp will unfortunately get handled by DispatcherServlet which will not know what do with it, the fix is to register a default-servlet-handler this way:

<mvc:default-servlet-handler />
Valueless answered 24/12, 2012 at 0:26 Comment(1)
Ah thanks! I think I did try something similar, but forgot that the @RequestMapping was set to '/index' not '/index*' or '/' so it ignored requests for '/index.jsp' thus making me think the Dispatcher/Resolver setup was still at fault. Still not sure I have the mappings totally right to get directory indexes. Anyway, thanks.Irizarry
F
52

I will try to explain the "flow" of a request in a Spring Web MVC application.

When sending a request to your application the following happens:

  • The request arrives at your server (e.g. Tomcat). Depending on the context path in the url the server decides to which application the request belongs.
  • Depending on the url and the servlet mapping in the web.xml file of your application the server knows which servlet should handle the request.
  • The request is passed to the servlet filter chain which can modify or reject requests
  • The servlet takes control over the request. In case of your Spring application the spring Dispatcherservlet receives the request. Now Spring kicks in
  • The request is processed by mvc intercepters preHandle methods
  • The request is mapped to a controller based on the url. The corresponding controller method will be called.
  • Your controller is processing the request. Many different responses can be returned in controllers (jsp, pdf, json, redirects, etc.). For now i assume you want to render a simple jsp view. Result of the controller are two things: a model and a view. The model is a map that contains the data you want to access later in your view. The view at this stage is most of the time a simple string containing a view name.
  • Registered springs mvc interceptors can kick in again using the postHandle method (e.g. for modifying the model)
  • The 'view' result of your controller is resolved to a real View using a ViewResolver. Depending on the ViewResolver the result can be jsp page, a tiles view, a thymeleaf template or many other 'Views'. In your case the ViewResolver resolves a view name (e.g. 'myPage') to a jsp file (e.g. /WEB-INF/jsp/myPage.jsp)
  • The view is rendered using the model data returned by your controller
  • The response with the rendered view will be passed to mvc interceptors again (afterCompletion method)
  • The response leaves the dispatcher servlet. Here ends spring land.
  • The response passes servlet filters again
  • The response is send back to client

Feel free to correct me if I'am not 100% correct or if I missed something :-)

Flanagan answered 24/12, 2012 at 0:39 Comment(2)
Thanks for the overview. I can see it's fairly complex and you've shown me a lot of places where I need to read up on so I'm comfortable with how it fits together.Irizarry
Best explanation about dispaterServletDepartment
V
8

Essentially what is happening is, since you have Spring's DispatcherServlet mapped to /*, it tends to be called for every request(which is okay), but unfortunately gets invoked even when the request gets dispatched to the JSP page (/WEB-INF/jsp/index.jsp), instead of the containers default servlet getting invoked.

The fix that I am aware of is the following:

Map it to the default servlet path / instead:

<servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

One issue that you would see with above is that the resources under the root of your webapp will unfortunately get handled by DispatcherServlet which will not know what do with it, the fix is to register a default-servlet-handler this way:

<mvc:default-servlet-handler />
Valueless answered 24/12, 2012 at 0:26 Comment(1)
Ah thanks! I think I did try something similar, but forgot that the @RequestMapping was set to '/index' not '/index*' or '/' so it ignored requests for '/index.jsp' thus making me think the Dispatcher/Resolver setup was still at fault. Still not sure I have the mappings totally right to get directory indexes. Anyway, thanks.Irizarry

© 2022 - 2024 — McMap. All rights reserved.