tags:

views:

609

answers:

4

Trying to implement clean URLs (without .form, .do, etc.) with Spring MVC 3.0 (actually it's a basic example from Spring reference). The problem that it just don't work: http://localhost:8080/ct/helloWorld gives a 404 page.

Below are my sources, plese help to find an error.

HelloWorldController.java

package controllers;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller()
public class HelloWorldController {
    @RequestMapping("/helloWorld")
    public ModelAndView helloWorld() {
     ModelAndView mav = new ModelAndView();
     mav.setViewName("helloWorld");
     mav.addObject("message", "Hello World!");
     return mav;
    }
}

ct-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;

    <context:component-scan base-package="controllers" />

    <bean id="viewResolver"
     class="org.springframework.web.servlet.view.UrlBasedViewResolver">
     <property name="viewClass"
      value="org.springframework.web.servlet.view.JstlView" />
     <property name="prefix" value="/WEB-INF/" />
     <property name="suffix" value=".jsp" />
    </bean>
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> 
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> 
</beans>

web.xml

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"&gt;
    <display-name>
    ct</display-name>


    <servlet>
    <servlet-name>ct</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>


<servlet-mapping>
    <servlet-name>ct</servlet-name>
    <url-pattern>/ct/*</url-pattern>
</servlet-mapping>


</web-app>

console output

12.11.2009 0:49:25 org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:ct' did not find a matching property.
12.11.2009 0:49:25 org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jre6\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Program Files/Java/jre6/bin/client;C:/Program Files/Java/jre6/bin;C:\Program Files\PC Connectivity Solution\;C:\PROGRA~1\RATIONAL\RATION~1\NUTCROOT\bin;C:\PROGRA~1\RATIONAL\RATION~1\NUTCROOT\bin\x11;C:\PROGRA~1\RATIONAL\RATION~1\NUTCROOT\mksnt;C:\Program Files\Borland\Delphi7\Bin;C:\Program Files\Borland\Delphi7\Projects\Bpl\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Microsoft SQL Server\80\Tools\Binn\;C:\Program Files\Microsoft SQL Server\90\DTS\Binn\;C:\Program Files\Microsoft SQL Server\90\Tools\binn\;C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\;C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PrivateAssemblies\;C:\Program Files\TortoiseSVN\bin;C:\Program Files\QuickTime\QTSystem\;e:\my downloads\develop tools\nant-0.86-beta1\bin\;C:\Program Files\Rational\common;C:\Program Files\Rational\ClearQuest;C:\Program Files\Rational\Rose\TopLink\;C:\Program Files\Rational\Rational Test;C:\Program Files\CodeGear\Delphi Prism\bin
12.11.2009 0:49:25 org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
12.11.2009 0:49:25 org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 769 ms
12.11.2009 0:49:25 org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
12.11.2009 0:49:25 org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.20
12.11.2009 0:49:26 org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring FrameworkServlet 'ct'
12.11.2009 0:49:26 org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'ct': initialization started
12.11.2009 0:49:26 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing WebApplicationContext for namespace 'ct-servlet': startup date [Thu Nov 12 00:49:26 MSK 2009]; root of context hierarchy
12.11.2009 0:49:26 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from ServletContext resource [/WEB-INF/ct-servlet.xml]
12.11.2009 0:49:27 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@197507c: defining beans [helloWorldController,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,viewResolver,org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0,org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0]; root of factory hierarchy
12.11.2009 0:49:27 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/helloWorld] onto handler [controllers.HelloWorldController@1c2fff0]
12.11.2009 0:49:27 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/helloWorld.*] onto handler [controllers.HelloWorldController@1c2fff0]
12.11.2009 0:49:27 org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/helloWorld/] onto handler [controllers.HelloWorldController@1c2fff0]
12.11.2009 0:49:28 org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'ct': initialization completed in 2641 ms
12.11.2009 0:49:28 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
12.11.2009 0:49:28 org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
12.11.2009 0:49:28 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/79  config=null
12.11.2009 0:49:28 org.apache.catalina.startup.Catalina start
INFO: Server startup in 3451 ms

java project structure

+2  A: 

Your web.xml is mapping the Spring DispatcherServlet to the url pattern /ct/* on top of the location your web application is being deployed to.

So if your web application is being deployed to /ct try going to http://localhost:8080/ct/ct/helloWorld

Chances are that you want the Spring DispatcherServlet to be mapped to all urls for your web application. Change the servlet-mapping to:

<servlet-mapping>
    <servlet-name>ct</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

and your original url should work as expected.

gavinjames
OK, now requests reaches the controller, thanks.But when controller whants to render the view, request to JSP-view is being served by DispathcerServlet, I've got following message in console:WARNING: No mapping found for HTTP request with URI [/ct/WebContent/WEB-INF/helloWorld.jsp] in DispatcherServlet with name 'ct'and result is again 404 page. Is there any way to serve jsp request bypassing DispatcherServlet?
kilonet
OK, try changing the class of your view resolver to org.springframework.web.servlet.view.InternalResourceViewResolver.UrlBasedViewResolver expects to be able to translate your symbolic view name into a URI it can use to render the view. That's probably not what you want to do.Generally you don't want your JSP views directly accessible, and by putting them under WEB-INF they're not. InternalResourceViewResolver will be able to access them though.
gavinjames
Changing view resolver to InternalResourceViewResolver did't help. In http://stackoverflow.com/questions/1234298/can-springmvc-be-configured-to-process-all-requests-but-exclude-static-content-d/1235311#1235311 there is advise to use SimpleUrlHandlerMapping to exclude addresses containing '.jsp' from served by Spring DispatcherServlet. I wonder, how can I do this?
kilonet
A: 

Have you created your helloWorld.jsp page?

I tried out your code (NB: using 2.5.6), and saw a 404 on the browser, and the following error message in the server log:

File "/path/to/my/WEB-INF/helloWorld.jsp" not found

Where /path/to/my will be different for your env.

Without helloWorld.jsp, the view resolver will fail. Adding this jsp, and all is well.

toolkit
A: 

The path in your RequestMapping should be the full path, not just the pathInfo (the stuff after the matched string in the web.xml). So your RequestMapping should specify @RequestMapping("/ct/HelloWorld")

Alternatively, your problem may be that you aren't running your app as the root app and is actually running at the path /ct. In that case, your web.xml isn't matching anything because the /ct which designates the application context is not used when comparing the url-patterns in order to determine the servlet context. In that case, you need to access the url /ct/ct/HelloWorld in order to send the request to your servlet. But you'll still need @RequestMapping("/ct/HelloWorld") in order for the controller to be mapped to that request (but it doesn't care about the initial /ct which designates the app).

Personally, I actually think it is clear to map based on a suffix, but to use a generic suffix. I map *.html to my servlet and controllers which respond to those requests send back html. Similarly, I use *.json and *.xml for json and xml requests. I handle static html and other static content at the load balancer, so tomcat never sees them.

+1  A: 

OK, for now solution is:

web.xml

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

HelloWorldController.java

@Controller
public class HelloWorldController {

    @RequestMapping("/helloWorld")
    public String list() {
     return "helloWorld";
    } 
  }

ct-servlet.xml

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

    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
kilonet