javaspringspring-mvctomcatstatic-resource

Spring MVC default-servlet-handler configuration blocking JSTL view


I have simple Spring configuration

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

<!-- Scan for components under this package -->
<context:component-scan base-package="com.osfg.test" />

And my controller is

package com.osfg.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author athakur
 */
@Controller
public class TestController {

    @RequestMapping(value="/test", method=RequestMethod.GET)
    public String welcome() {
        return "test";
    }

}

And my JSP is

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>OSFG Test Page</title>
<link href="CSS/test.css" rel="stylesheet">
</head>
<body>

<h1>Hello World!</h1>

</body>
</html>

This configuration works fine (CSS does not get applied though). enter image description here

So I add

<mvc:default-servlet-handler />

to my Spring configuration and now the page itself stops loading giving 404.

Also surprisingly everything works fine (with CSS) will following config

<mvc:view-controller path="/test" view-name="test"/>
<mvc:default-servlet-handler />

Direct rendering no controller involvement.


Solution

  • Looks like I found the issue. Somehow the default-sevlet-handler is overriding the DefaultAnnotationHandlerMapping handler? which is why annotation based handler is failing. Following scenarios worked for me -

    1. Use <mvc:annotation-driven/>. This seems to enable default beans including DefaultAnnotationHandlerMapping So combination of

       <mvc:annotation-driven/>
       <mvc:default-servlet-handler />
      

    worked.

    1. Explicitly define the handler mapping and handler adapter you need with highest preference (chaining). Spring scans all handler mappings and assigns an order property Integer.MAX (if not explicitly defined) which gives it lowest preference. Then these handler mappings are sorted based on this order. Also if two handler mappings are same it looks like it takes bean which is defined first. So following worked for me -

      <mvc:default-servlet-handler />
      
      <bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
          <property name="order" value="0" />
      </bean>
      <bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
      

    So I am guessing default-sevlet-handler creates it's own handler mapping which overrides the annotation one all being at same preference.