tags:

views:

2116

answers:

2

I'm not quite a newcomer to Spring but what I'm attempting now I've never done. Iteemed basic when I started but I've run into a problem. What I'm trying to do is map requests to the servlet root (correct terminology?). I'm at the point where URLs are mapped to correct view but all the static content - css, javascript, images - that is part of the page cannot be found.

So in my web.xml my servlet tag looks like this

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

My controller looks something like this:

@RequestMapping("/shop")
public class TheShopController extends MyBaseController {

    public static String VIEW = "Tile.Shop";

    @Override
    @RequestMapping(method = RequestMethod.GET)
    protected ModelAndView processRequest(HttpServletRequest req, HttpServletResponse resp) {
        ModelAndView mav = new ModelAndView(VIEW);
        return mav;
    }

}

MyBaseController is very simple. It looks like this:

public abstract class MyBaseController extends AbstractController {

    protected Logger log = Logger.getLogger(getClass());

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) 
        throws Exception {

        ModelAndView mav = processRequest(req, resp);
        return mav;
    }

    protected abstract ModelAndView processRequest(HttpServletRequest req, HttpServletResponse resp);
}

I'm using Tiles in my view layer. My configuration is as follows:

/WEB-INF/tiles-defs.xml

As I mentioned, the views are found but the static resources that are a port of the page can't be found. Here is some typical logging out put:

2010-01-24 17:25:01,777 DEBUG [http-8080-7] servlet.DispatcherServlet (DispatcherServlet.java:690) - DispatcherServlet with name 'springapp' processing GET request for [/springapp/static/css/account.css] 2010-01-24 17:25:01,778 WARN [http-8080-4] servlet.DispatcherServlet (DispatcherServlet.java:962) - No mapping found for HTTP request with URI [/springapp/static/css/shop.css] in DispatcherServlet with name 'springapp' 2010-01-24 17:25:01,778 DEBUG [http-8080-6] servlet.FrameworkServlet (FrameworkServlet.java:677) - Successfully completed request 2010-01-24 17:25:01,778 WARN [http-8080-5] servlet.DispatcherServlet (DispatcherServlet.java:962) - No mapping found for HTTP request with URI [/springapp/static/css/offers.css] in DispatcherServlet with name 'springapp' 2010-01-24 17:25:01,778 WARN [http-8080-3] servlet.DispatcherServlet (DispatcherServlet.java:962) - No mapping found for HTTP request with URI [/springapp/static/css/scrollable-buttons.css] in DispatcherServlet with name 'springapp'

Going to http://localhost:8080/springapp/shop works fine but the css and images are missing.

I think that using Tiles is somehow complicating things but I"m reluctant to get rid of it. I'm wondering if I need to adjust my view resolution configuration needs to be tweeked somehow? Chaining view resolvers maybe? I'm just not that experienced in doing that.

Any help much appreciated.

+4  A: 

The problem is that requests for the static content go to the dispatcherServlet, because it's mapped as <url-pattern>/</url-pattern>. It's a very common problem in applications with "RESTful" URLs (that is, without any prefix in the DispatcherServlet mapping).

There are several possible ways to solve this problem:

1. Use URL rewrite filter
See mvc-basic example here

2. Set a prefix for the default servlet:

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

That is, request for /static/images/image.png will return the file named /images/image.png However, this way is incompatible across different servlet containers (doesn't work in Jetty), see workarounds here

3. Set static content extensions for the default servlet:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.png</url-pattern>
    <url-pattern>*.js</url-pattern>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>

4. Do not use RESTful URLs, use URLs with prefix:

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

5. Do not use RESTful URLs, use URLs with extension:

<servlet-mapping> 
    <servlet-name>springapp</servlet-name> 
    <url-pattern>*.do</url-pattern> 
</servlet-mapping>
axtavt
What I really want to do is use the @RequestMapping annotation with the @PathVariable annotation to achieve the use of RESTful urls. Eventually all static resources will be served by apache but that will be in a production environment. I need static resources served by tomcat when running locally, like in development. I've used urlrewrite filter before, and I liked it, but I'd like to find another way.
richever
I went with a combination of org.tuckey.urlrewrite filter and #4 from above. Thanks!
richever
+1  A: 

As an alternative to the proposed solution number (2, default servlet which behaves differently from servlet container to servlet container), I would recommend taking a look into the Resource Servlet (org.springframework.js.resource.ResourceServlet) from the Spring Webflow project.

For more details please have a look at http://stackoverflow.com/questions/1483063/spring-mvc-3-and-handling-static-content-am-i-missing-something

ngeek