Sitemesh and spring Problems with MVC decorator patterns

I have a sitemesh with spring, this is the config: decorator.xml

<?xml version="1.0" encoding="UTF-8"?>
<decorators defaultdir="/styles">
    <excludes>
        <pattern>/exclude.jsp</pattern>
        <pattern>/exclude/*</pattern>
    </excludes>
    <decorator page="application/themeManager/theme.jsp" name="dos">
        <pattern>/*</pattern>
    </decorator>
</decorators>

      

And this is my web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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"
    version="2.4">

    <!-- The master configuration file for this Spring web application -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/config/web-application-config.xml
        </param-value>
    </context-param>

    <!-- Enables Spring Security -->
    <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>


    <!-- Agregamos el filtro de sitemesh que permite interceptar todas las llamadas que necesitamos -->
    <filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>

    <!-- Loads the Spring web application context -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Serves static resource content from .jar files such as spring-faces.jar -->
    <servlet>
        <servlet-name>Resources Servlet</servlet-name>
        <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>

    <!-- Map all /resources requests to the Resource Servlet for handling -->
    <servlet-mapping>
        <servlet-name>Resources Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>

    <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    <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></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map all *.spring requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>

      

This work, but when I change the template in decorator.xml to something like

<decorator page="application/themeManager/theme.jsp" name="dos">
    <pattern>/spring/cliente/index</pattern>
</decorator>

      

it doesn't work, i try to combine a lot and nothing. Then I change the mapping for the spring servlet in the web.xml file as follows

         spring MVC Dispatcher Servlet * .htm   

and define a new template like this:

<decorator page="application/themeManager/theme.jsp" name="dos">
    <pattern>/cliente/index.htm</pattern>
</decorator>

      

And it works, so is there a way to make this work with this mapping for a spring servlet?

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

      

+2


a source to share


4 answers


The problem is SiteMesh is using Request.getServletPath () which in your spring mvc application will return "/ spring" for everything. I found this by implementing the com.opensymphony.module.sitemesh.DecoratorMapper interface and using that instead of the usual ConfigDecoratorMapper. I was then able to test the various arguments used to match decorators to requests. Unfortunately, I think this leaves you with only one option - to use the * .html suffix on the DispatcherServelet mapping, or some variation of it.

Another option would be to configure the PageDecoratorMapper and use this tag in your original undecorated page to specify which layout to use:



 <meta name="decorator" content="layoutName" /> 

      

Though then you strip the benefits of URL mappings.

+4


a source


I had this exact problem. What happens is that any part of the url you specify in the web.xml is removed by the web server before being passed to Spring, but only if you put the template at the end. You already found that when your url is www.myapp.com/spring/cliente/index.html if you put this in your web.xml

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

      

Spring will only see part of the request path after / spring. In this case, you need to specify your RequestMapping as "/cliente/index.html".



You can also specify your servlet mapping this path.

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

      

Then Spring will see the entire request path and you can specify your request mappings like this "/ spring / cliente / index.html". The same goes for Sitemesh. He only sees what the web server is passing through.

+2


a source


Maybe it will be helpful for someone, I have the same problem and after researching on google and stading the sitemesh source files solve the problem by extending ConfigDecoratorMapping. Here he is:

/**
 * Created by IntelliJ IDEA.
 * User: Inf-root
 * Date: 30.06.11
 * Time: 1:00
 *
 */

public class ConfigDecoratorMapperSpringMvcSupport extends ConfigDecoratorMapper {

    private static final Logger LOG = Logger.getLogger(ConfigDecoratorMapperSpringMvcSupport.class);

    private ConfigLoader configLoader = null;

     /** Create new ConfigLoader using '/WEB-INF/decorators.xml' file. */
    public void init(Config config, Properties properties, DecoratorMapper parent) throws InstantiationException {
        LOG.debug("init()...");
        super.init(config, properties, parent);
        try {
            String fileName = properties.getProperty("config", "/WEB-INF/decorators.xml");
            configLoader = new ConfigLoader(fileName, config);
        }
        catch (Exception e) {
            throw new InstantiationException(e.toString());
        }
    }

    /** Retrieve {@link com.opensymphony.module.sitemesh.Decorator} based on 'pattern' tag. */
    public Decorator getDecorator(HttpServletRequest request, Page page) {
        LOG.debug("getDecorator()...");
        String thisPath = request.getServletPath();
        LOG.debug("\tThisPath: " + thisPath);
        String requestURI = request.getRequestURI();
        LOG.debug("\t\tGet request URI: " + requestURI);
        //TODO check indexes
        thisPath = "/springURITemplate" + requestURI.substring(request.getContextPath().length(), requestURI.length() - 1);
        LOG.debug("\t\t\tThisPath: " + thisPath);
        String name = null;
        try {
            name = configLoader.getMappedName(thisPath);
        }
        catch (ServletException e) {
            e.printStackTrace();
        }
        LOG.debug("\tResolved decorator name: " + name);
        Decorator result = getNamedDecorator(request, name);
        LOG.debug("Decorator is null ? " + (result == null));
        return result == null ? super.getDecorator(request, page) : result;
    }
}

      

and my decorators.xml contains something like this

<?xml version="1.0" encoding="ISO-8859-1"?>
<decorators defaultdir="/web/decorators">
    <decorator name="admin_decorator" page="admin_decorator.jsp">
        <pattern>/springURITemplate/a/administration*</pattern>
    </decorator>
</decorators>

      

Tested on tomcat 7 with Spring 3.0.5

+2


a source


Have you tried doing / spring / cliente / index * or / spring / cliente / index / *?

0


a source







All Articles