Mahmoud Saleh
Mahmoud Saleh

Reputation: 33605

Can't map dispatcherServlet to context root

this is the current configuration i am using for spring mvc:

1- web.xml:

<servlet>  
    <servlet-name>spring</servlet-name>  
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/config/dispatcherServlet.xml</param-value>
   </init-param>
<load-on-startup>1</load-on-startup>
</servlet>

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

2- dispatcherServlet.xml:

<context:component-scan base-package="com.app" />
 <context:annotation-config />
<mvc:annotation-driven />   
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
</bean>

3- Controller: my web pages are under webapp folder directly

@Controller
public class SearchController {

private Log log = LogFactory.getLog(getClass());

@RequestMapping("/search.jsp")
public String search(Model model, HttpServletRequest request,
        HttpSession session) {
          log.debug("Search Controller");
          return "search";
 }

ISSUE: when trying to access the search page as follows:

http://localhost:8080/MyAPP/search.jsp

the controller is not invoked, but when i was mapping the dispatcher servlet to /mapping/* and accessing the search page as follows:

http://localhost:8080/MyAPP/mapping/search.jsp

the controller was invoked correctly, i am using spring 3.0.5.RELEASE.

please advise, thanks.

Upvotes: 6

Views: 3869

Answers (2)

andyb
andyb

Reputation: 43823

I think you are forgetting about the built in default servlet configured in your web server/servlet container. For example in Tomcat7/conf/web.xml there exists:

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>

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

<!-- The mappings for the JSP servlet -->
<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
    <url-pattern>*.jspx</url-pattern>
</servlet-mapping>

which is catching the *.jsp before it ever gets to Spring. I tested this locally by removing all of the Spring configuration and could still get the search.jsp.

How DefaultAnnotationHandlerMapping works should be useful in explaining why this works they way it does.

When you had <url-pattern>/mapping/*</url-pattern> you created a more specific match than the simple / so requests were ignored by the default (i.e. Tomcat) servlet and routed to your correctly configured controller.

One way to fix this is to force everything through your servlet by using <url-pattern>/*</url-pattern> but you will also need to make a few other changes to avoid mapping resolution problems.

I moved the *.jsp files into the (standard?) subdirectory /WEB-INF and added

<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>/WEB-INF/*</url-pattern>
</servlet-mapping>

to web.xml and changed dispatcherServlet.xml to match like so:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/"/>
    <property name="suffix" value=".jsp"/>
</bean>

If you do not make these changes, a request to /search.jsp would be resolved by the InternalResourceViewResolver you configured to /search.jsp sending Tomcat into an infinite forwarding loop!

No mapping found for HTTP request with URI [/WEB-INF/pages/apiForm.jsp] may be useful here.

Aside: For most of my Spring XML configured projects I use /WEB-INF/views to keep the view layer separate from any configuration in the /WEB-INF root.

Upvotes: 1

Kevin Bowersox
Kevin Bowersox

Reputation: 94469

The following mapping will cause the dispatcher servlet to handle urls that were not explicitly mapped by other url mappings within web.xml. Think of this as almost a catch all mapping, as long as the url was not handled by some other mapping.

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

When you configure the ViewResolver as follows:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/"/>
    <property name="suffix" value=".jsp"/>
</bean>

The ViewMapping must point to a JSP within your project or else the catch all mapping provided for the dispatcher is going to attempt to handle the forward/redirect to the appropriate view. You must make sure that a view exists within your project for the result of the viewresolver, which is /search.jsp. This means there must be a search.jsp within the root of your projects web content folder. It is much more common to see these views placed within the WEB-INF folder and a mapping of:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/"/>
    <property name="suffix" value=".jsp"/>
</bean>

Upvotes: 0

Related Questions