views:

117

answers:

3

I'm trying to improve my spring mvc configuration so as to not require a new config file for every servlet I add, but I'm running into problems. I've tried using this tutorial as a starting point, but I'm running into an issue that I can't figure out.

The problem is that when I do a GET to my servlet, I get back a 404 error. Here's my config and a representative java snippet from a Controller:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&gt;
    <display-name>SightLogix Coordination System</display-name>

    <description>SightLogix Coordination System</description>

    <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>     
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>
                    /WEB-INF/application-context.xml
                    /WEB-INF/application-security.xml
                </param-value>
            </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/slcs/*</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/application-context.xml
            /WEB-INF/application-security.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>
                org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

application-context.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:mvc="http://www.springframework.org/schema/mvc"
    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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd"

    default-init-method="init" default-destroy-method="destroy">

    <mvc:annotation-driven />

    <context:component-scan base-package="top.level" />
</beans>

application-security.xml:

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"&gt;

    <http>
        <intercept-url pattern="/**" access="ROLE_MANAGER" requires-channel="https" />
        <http-basic />
    </http>

    <authentication-manager>
        <authentication-provider user-service-ref="myUserDetailsService">
            <password-encoder hash="sha"/>
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="myUserDetailsService"
        class="path.to.my.UserDetailsServiceImpl">
    </beans:bean>

</beans:beans>

Snippet of a Controller class (one of many, but they all look essentially like this):

@Controller
@RequestMapping("/foo.xml")
public class FooController
{       
    @RequestMapping(method=RequestMethod.GET)
    public void handleGET(HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        ...

Can anyone tell me what I'm doing incorrectly? Thanks!

A: 

This doesn't answer your question directly, but I've always found it helpful to enable debug logging in Spring when I can't figure out what is going wrong.

Below are two that I commonly use in my logging.properties file:

org.springframework.beans.factory.support.level=FINEST
org.springframework.security.level=FINEST
Taylor Leese
+3  A: 

The only thing out of place here is that you've used the same context config files for both the root webapp context and your servlet context. This is almost guaranteed to be a bad idea, and will result in a lot of weird behaviour. This may well be the cause of your problem.

The ContextLoaderListener is configured with the contextConfigLocation <context-param>, and creates and manages the root WebApplicationContext.

The ServletDispatcherServlet is configured with the contextConfigLocation <init-param>, and creates and manages the servlet WebApplicationContext.

The root WebApplicationContext is the parent of the servlet appcontext, i.e any beans in the root WebApplicationContext are visible to those beans in the servlet WebApplicationContext.

Your first step should be to separate those configurations. With the correct beans in the correct places (e.g. all MVC stuff has to go in the servlet context). Do not share bean definitions between the two, it'll just get confusing and/or broken.

skaffman
With that sort of configuration, the servlet init param should point to an empty bean definition file - the context loader listener is going to load all the beans, then they'll all be overridden by themselves when the dispatcher servlet loads. While I agree with you in principle with separating out the MVC stuff into the servlet's specific configuration files, in this case there's only one servlet so this isn't really needed - it's when two or more servlets pop up that separation becomes more important.
MetroidFan2002
I separated out the context files for my application and my servlets, but I'm still getting that 404 error.
Seth
A: 

Do you have more than one GET RequestMapping in your controller by any chance? If there are more than one and there is ambiguity in resolving them to a particular request Spring does not map to any of the ambiguous GET mappings.

Eqbal