0

I'm trying to add Apache Tiles to a simple Spring MVC webapp I'm playing with and I can't seem to get it to work (it worked without Tiles). Any request I make gives back 400 bad request, nothing appears in the log (even set to DEBUG) so I'm not sure where to start debbuging. As far as I can tell the Controller mapped method is never called as there's logging in there and it doesn't appear in the log (plus before that I would get a lot of debug info from spring about resolving the mapping to the controller before it was actually called - which now doesn't appear).

My config files are as follows (all under /WEB-INF/): web.xml:

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <display-name>myapp</display-name>    

    <!-- Enable escaping of form submission contents -->
    <context-param>
        <param-name>defaultHtmlEscape</param-name>
        <param-value>true</param-value>
    </context-param>        
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
    </context-param>

    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter>
        <filter-name>HttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>HttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- Creates the Spring Container shared by all Servlets and Filters -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Handles Spring requests -->
    <servlet>
        <servlet-name>myapp</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>myapp</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <session-config>
        <session-timeout>10</session-timeout>
    </session-config>
</web-app>

myapp-servlet.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
    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.1.xsd                 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd                 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <!-- The controllers are autodetected POJOs labeled with the @Controller 
        annotation. -->
    <context:component-scan base-package="com.myapp.controller"
        use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller"
            type="annotation" />
    </context:component-scan>

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources -->
    <mvc:resources location="/resources/" mapping="/resources/**" />

    <!-- Allows for mapping the DispatcherServlet to "/" by forwarding static 
        resource requests to the container's default Servlet -->
    <mvc:default-servlet-handler />

    <mvc:annotation-driven />

    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles.xml</value>
            </list>
        </property>
    </bean>    
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>
</beans>

tiles.xml

<tiles-definitions>    
    <definition name="product_detail" template="/WEB-INF/layout/detail.jsp">
        <put-attribute name="header" value="/WEB-INF/view/header.jsp" />
        <put-attribute name="banner" value="" />
        <put-attribute name="body" value="/WEB-INF/view/product.jsp" />
        <put-attribute name="footer" value="/WEB-INF/view/footer.jsp" />
    </definition>
</tiles-definitions>

The layout just contains one div for each part wrapping a tag. All the views contain simple code like a header or a div.

And for the controller ProductController.java:

@Controller
@RequestMapping("/product")
public class ProductController {

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

    @Autowired
    private ProductService productService;

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public ModelAndView getProduct(@PathVariable Long id) {
        logger.info("GET product " + id);
        Product product = productService.find(id);
        ModelAndView mv = new ModelAndView("product_detail", "product", product);
        return mv;
    }
}

Deploying this with maven embedded tomcat plugin and going to localhost:8080/myapp/product/1 just gives HTTP 400 code without any other indication that something went wrong. There is a product in the DB with that id and everything from the controller down works, as I tried it before adding tiles.

Sorry for the code drop but I can't get this to work for some time now, and I have no idea what else to try or where to start debugging.

Is there some way to force logging what the problem was when a 400 bad request is returned?

Andrei Fierbinteanu
  • 7,656
  • 3
  • 31
  • 45

1 Answers1

0

You're missing the reference to your myapp-servlet.xml in the servlet configuration.

<!-- Handles Spring requests -->
<servlet>
    <servlet-name>myapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/myapp-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>myapp</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
marcaurele
  • 502
  • 1
  • 6
  • 14
  • Unfortunately, that doesn't solve it. And I'm pretty sure it loads it because setting a bad path gives a FileNotFound error. Also I was under the impression that if you don't provide one it looks for servletname-servlet.xml autmatically in WEB-INF, and I think that was the case before, since no error was thrown on loading the container. And the start up log also contained messages about mapping the controller method, which presumes it found the servlet.xml file where I defined the Controller scanning. – Andrei Fierbinteanu Jul 26 '12 at 17:23