Richard’s Weblog

February 23, 2009

Apache Tiles 2, integration with Spring-MVC

Filed under: Spring Framework,template system,Web development — Richard @ 5:26 pm
Tags: ,

UPDATE : I’ve written another example using Tiles 3.0.3 and SpringMVC 3.2.7. See here.

In a recent post, I showed a brief example of using Apache Tiles 2 to configure a classic layout in a J2EE environment. In this one, I’ll take that old book inventory search engine example I used in other previous writings, adding Tiles 2 support.

But before diving into the Tiles integration, let’s summarize the example. I have a single controller, managing a form submission and displaying the search results. This controller only uses one view, the same to display the form and the results. No particular ViewResolver nor HandlerMapping were configured, so I’m using the ones supplied by Spring MVC, out-of-the-box. Now let’s take a look at my configuration files, starting with the deployment descriptor, web.xml :

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

    <servlet>
        <servlet-name>core</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext.xml</param-value>
	</init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>core</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>/searchBook.do</welcome-file>
    </welcome-file-list>

</web-app>

Nothing particular here, just configuring the DispatcherServlet to be mapped on all “.do” urls.
My applicationContext.xml file looks like this :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-2.5.xsd">

    <bean name="/searchBook.do" class="com.x.samples.bookbay.search.SearchController">
        <property name="commandClass" value="com.x.samples.bookbay.search.SearchCriteria"/>
        <property name="formView" value="/book/searchForm.jsp"/>
        <property name="successView" value="/book/searchForm.jsp"/>
    </bean>

</beans>

My controller is a SimpleFormController, directly pointing at the target JSP.
My directory structure looks like this :
springtilesintegration-dir11

I want to define a template, so I create a directory named “template” directly under the root directory of my application. This directory will contain my template file, the header file etc :

  • template.jsp
  • header.jsp
  • menu.jsp
  • footer.jsp

Using Tiles requires me to define my tiles in a configuration file. I’ll stack my Tiles specific configurations in a “defs” directory, under WEB-INF. For now, I have only one Tiles configuration file, called “myTilesConfigurationFile.xml” :

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
       "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
       "http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>

    <definition name="defaultTemplate" template="/template/template.jsp">
        <put-attribute name="header" value="/template/header.jsp" />
        <put-attribute name="menu" value="/template/menu.jsp" />
        <put-attribute name="footer" value="/template/footer.jsp" />
    </definition>

    <definition name="searchBook" extends="defaultTemplate">
        <put-attribute name="body" value="/book/searchForm.jsp"/>
    </definition>

</tiles-definitions>

I won’t show the code of these JSP, since it’s pretty much the same as in my previous example on using Tiles.
My Tiles configuration file defines two tiles : the template and a tile named “searchBook”, that only extends the template, specifying the body will be the search form (the page that displays the form and the search results, “/book/searchForm.jsp”). Now I must have a JSP that uses tiles tag library to include the “searchBook” definition. This file will be “/book/search.jsp” :

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<tiles:insertDefinition name="searchBook" />

Three things remain for the example to be completed. I must tell my controller to use my new search.jsp file as a success and form view. I also need to add tiles library and related dependency to my project, and finally I must “bootstrap” Tiles to have it read my definition file. I start by telling my controller to use search.jsp :

<bean name="/searchBook.do" class="com.x.samples.bookbay.search.SearchController">
    <property name="commandClass" value="com.x.samples.bookbay.search.SearchCriteria"/>
    <property name="formView" value="/book/search.jsp"/>
    <property name="successView" value="/book/search.jsp"/>
</bean>

For my example to work (I’m using Tiles 2.1.2 and Spring 2.5.6), I have to include all the libs:

  • tiles-servlet-2.1.2.jar
  • tiles-jsp-2.1.2.jar
  • tiles-core-2.1.2.jar
  • tiles-api-2.1.2.jar
  • commons-beanutils-1.8.0.jar (dependency)
  • commons-digester-1.8.1.jar (dependency)
  • commons-logging-1.1.1.jar (dependency)
  • spring-core.jar
  • spring-web.jar
  • spring-context.jar
  • spring-beans.jar
  • spring-webmvc.jar
  • aopalliance.jar
  • jstl-1.2.jar ( can be found here )

Now the only thing that is left to do is to “bootstrap” Tiles. According to the Spring 2.5 documentation, I should do it this way, in my applicationContext.xml :

<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
    <property name="definitions">
        <list>
            <value>/WEB-INF/defs/myTilesConfigFile.xml</value>
        </list>
    </property>
</bean>

This should work perfectly, BUT
There seems to be a problem bootstrapping Tiles versions 2.1 with the TilesConfigurer of Spring 2.5.6. When launching the web application with this configuration, I get this error :

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tilesConfigurer' defined i
n ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is
 java.lang.UnsupportedOperationException: Class org.apache.tiles.web.util.ServletContextAdapter not recognized a T
ilesApplicationContext
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAut
owireCapableBeanFactory.java:1338)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutow
ireCapableBeanFactory.java:473)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapa
bleBeanFactory.java:409)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowir
eCapableBeanFactory.java:380)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBea
nRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:402)
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:316)
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:316)
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:282)
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:126)
        at javax.servlet.GenericServlet.init(GenericServlet.java:212)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1172)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:992)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4058)
        at org.apache.catalina.core.StandardContext.start(StandardContext.java:4371)
        at org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1116)
        at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1214)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:293)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
        at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1337)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1601)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1610)
        at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1590)
        at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.UnsupportedOperationException: Class org.apache.tiles.web.util.ServletContextAdapter not recognized a TilesApplicationContext
        at org.apache.tiles.factory.TilesContainerFactory.createContainer(TilesContainerFactory.java:219)
        at org.springframework.web.servlet.view.tiles2.TilesConfigurer.createTilesContainer(TilesConfigurer.java:214)
        at org.springframework.web.servlet.view.tiles2.TilesConfigurer.afterPropertiesSet(TilesConfigurer.java:201)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
        ... 30 more

The reason to this, basically, is that since Tiles 2.1, some configuration elements became deprecated, and Spring 2.5.6 is still using these elements. A JIRA issue is already created for this bug, and a fix seems to be planned for version 3.0.0 M3. However, at the time of this writing, the code of org.springframework.web.servlet.view.tiles2.TilesConfigurer is the same in the 2.5.6 as in the latest 3.0.0 build. So, to patch the problem, I wrote this little TilesConfigurer based on the one provided by Spring. It is essentially an adapted copy of the original TilesConfigurer :

/*
 * Copyright 2002-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.x.web.tiles2;

import java.util.Enumeration;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tiles.TilesApplicationContext;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.TilesException;
import org.apache.tiles.access.TilesAccess;
import org.apache.tiles.context.AbstractTilesApplicationContextFactory;
import org.apache.tiles.definition.DefinitionsFactory;
import org.apache.tiles.definition.digester.DigesterDefinitionsReader;
import org.apache.tiles.evaluator.el.ELAttributeEvaluator;
import org.apache.tiles.factory.AbstractTilesContainerFactory;
import org.apache.tiles.factory.TilesContainerFactory;
import org.apache.tiles.preparer.BasicPreparerFactory;
import org.apache.tiles.servlet.context.ServletTilesApplicationContext;
import org.apache.tiles.servlet.context.wildcard.WildcardServletTilesApplicationContextFactory;
import org.apache.tiles.web.util.ServletContextAdapter;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.servlet.view.tiles2.SpringLocaleResolver;
import org.springframework.web.servlet.view.tiles2.TilesView;

/**
 * Helper class to configure Tiles2 for the Spring Framework. See
 * <a href="http://tiles.apache.org">http://tiles.apache.org</a>
 * for more information about Tiles, which basically is a templating
 * mechanism for JSP-based web applications.
 *
 * <p>The TilesConfigurer simply configures a TilesContainer using a set
 * of files containing definitions, to be accessed by {@link TilesView}
 * instances.
 *
 * <p>TilesViews can be managed by any {@link org.springframework.web.servlet.ViewResolver}.
 * For simple convention-based view resolution, consider using
 * {@link org.springframework.web.servlet.view.UrlBasedViewResolver} with the
 * "viewClass" property set to "org.springframework.web.servlet.view.tiles2.TilesView".
 *
 * <p>A typical TilesConfigurer bean definition looks as follows:
 *
 * <pre>
 * &lt;bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
 *   &lt;property name="definitions">
 *     &lt;list>
 *       &lt;value>/WEB-INF/defs/general.xml&lt;/value>
 *       &lt;value>/WEB-INF/defs/widgets.xml&lt;/value>
 *       &lt;value>/WEB-INF/defs/administrator.xml&lt;/value>
 *       &lt;value>/WEB-INF/defs/customer.xml&lt;/value>
 *       &lt;value>/WEB-INF/defs/templates.xml&lt;/value>
 *     &lt;/list>
 *   &lt;/property>
 * &lt;/bean></pre>
 *
 * The values in the list are the actual files containing the definitions.
 *
 * @author Juergen Hoeller
 * @author Richard Jr Barabé
 * @since 2.5
 * @see TilesView
 * @see org.springframework.web.servlet.view.UrlBasedViewResolver
 */
public class SpringTilesConfigurer implements ServletContextAware, InitializingBean, DisposableBean {

    protected final static Log logger = LogFactory.getLog(SpringTilesConfigurer.class);

    private final Properties tilesPropertyMap = new Properties();

    private ServletContext servletContext;

    private TilesApplicationContext tilesContext;

    public SpringTilesConfigurer() {
            this.tilesPropertyMap.put(
		            AbstractTilesApplicationContextFactory.APPLICATION_CONTEXT_FACTORY_INIT_PARAM,
		            WildcardServletTilesApplicationContextFactory.class.getName());
            this.tilesPropertyMap.put(
				    TilesContainerFactory.PREPARER_FACTORY_INIT_PARAM,
				    BasicPreparerFactory.class.getName());
		    this.tilesPropertyMap.put(
				    DefinitionsFactory.LOCALE_RESOLVER_IMPL_PROPERTY,
				    SpringLocaleResolver.class.getName());
		    this.tilesPropertyMap.put(TilesContainerFactory.ATTRIBUTE_EVALUATOR_INIT_PARAM, ELAttributeEvaluator.class.getName());
		    this.tilesPropertyMap.put(TilesContainerFactory.CONTAINER_FACTORY_MUTABLE_INIT_PARAM,
	                Boolean.toString(false));
    }

    /**
     * Set the Tiles definitions, i.e. the list of files containing the definitions.
     * Default is "/WEB-INF/tiles.xml".
     */
    public void setDefinitions(String[] definitions) {
        if (definitions != null) {
            String defs = StringUtils.arrayToCommaDelimitedString(definitions);
            if (logger.isInfoEnabled()) {
                logger.info("TilesConfigurer: adding definitions [" + defs + "]");
            }
            this.tilesPropertyMap.put(DefinitionsFactory.DEFINITIONS_CONFIG, defs);            
        }
    }
    
    /**
     * Set whether to validate the Tiles XML definitions. Default is "true".
     */
    public void setValidateDefinitions(boolean validateDefinitions) {
        this.tilesPropertyMap.put(DigesterDefinitionsReader.PARSER_VALIDATE_PARAMETER_NAME,
                Boolean.toString(validateDefinitions));
    }
    
    /**
     * Set the {@link org.apache.tiles.definition.DefinitionsFactory} implementation to use.
     * Default is {@link org.apache.tiles.definition.UrlDefinitionsFactory},
     * operating on definition resource URLs.
     * <p>Specify a custom DefinitionsFactory, e.g. a UrlDefinitionsFactory subclass,
     * to customize the creation of Tiles Definition objects. Note that such a
     * DefinitionsFactory has to be able to handle {@link java.net.URL} source objects,
     * unless you configure a different TilesContainerFactory.
     */
    public void setDefinitionsFactoryClass(Class<?> definitionsFactoryClass) {
        this.tilesPropertyMap.put(TilesContainerFactory.DEFINITIONS_FACTORY_INIT_PARAM,
                definitionsFactoryClass.getName());
    }
    
    /**
     * Set the {@link org.apache.tiles.preparer.PreparerFactory} implementation to use.
     * Default is {@link org.apache.tiles.preparer.BasicPreparerFactory}, creating
     * shared instances for specified preparer classes.
     * <p>Specify {@link SimpleSpringPreparerFactory} to autowire
     * {@link org.apache.tiles.preparer.ViewPreparer} instances based on specified
     * preparer classes, applying Spring's container callbacks as well as applying
     * configured Spring BeanPostProcessors. If Spring's context-wide annotation-config
     * has been activated, annotations in ViewPreparer classes will be automatically
     * detected and applied.
     * <p>Specify {@link SpringBeanPreparerFactory} to operate on specified preparer
     * <i>names</i> instead of classes, obtaining the corresponding Spring bean from
     * the DispatcherServlet's application context. The full bean creation process
     * will be in the control of the Spring application context in this case,
     * allowing for the use of scoped beans etc. Note that you need to define one
     * Spring bean definition per preparer name (as used in your Tiles definitions).
     * @see SimpleSpringPreparerFactory
     * @see SpringBeanPreparerFactory
     */
    public void setPreparerFactoryClass(Class<?> preparerFactoryClass) {
        this.tilesPropertyMap.put(TilesContainerFactory.PREPARER_FACTORY_INIT_PARAM,
                preparerFactoryClass.getName());
    }
    
    /**
     * Set whether to use a MutableTilesContainer for this application.
     * Default is "false".
     */
    public void setUseMutableTilesContainer(boolean useMutableTilesContainer) {
        this.tilesPropertyMap.put(TilesContainerFactory.CONTAINER_FACTORY_MUTABLE_INIT_PARAM,
                Boolean.toString(useMutableTilesContainer));
    }
    
    /**
     * Set Tiles properties (equivalent to the ServletContext init-params in
     * the Tiles documentation), overriding the default settings.
     */
    public void setTilesProperties(Properties tilesProperties) {
        CollectionUtils.mergePropertiesIntoMap(tilesProperties, this.tilesPropertyMap);
    }

    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    /**
     * Creates and exposes a TilesContainer for this web application.
     * @throws TilesException in case of setup failure
     */
    public void afterPropertiesSet() throws TilesException {
        TilesContainer container = createTilesContainer();
	TilesAccess.setContainer(this.tilesContext, container);
    }

    /**
     * Create a TilesContainer for this web application.
     * @param context this web application's ServletContext
     * @return the TilesContainer to expose
     * @throws TilesException in case of setup failure
     */
    protected TilesContainer createTilesContainer() throws TilesException {
        ServletContextAdapter adaptedContext = new ServletContextAdapter(new DelegatingServletConfig());
        TilesApplicationContext preliminaryContext = new ServletTilesApplicationContext(adaptedContext);
        AbstractTilesApplicationContextFactory contextFactory = AbstractTilesApplicationContextFactory.createFactory(preliminaryContext);
        this.tilesContext = contextFactory.createApplicationContext(adaptedContext);
        AbstractTilesContainerFactory factory = AbstractTilesContainerFactory.getTilesContainerFactory(this.tilesContext);
        return factory.createContainer(this.tilesContext);
    }

    /**
     * Removes the TilesContainer from this web application.
     * @throws TilesException in case of cleanup failure
     */
    public void destroy() throws TilesException {
        TilesAccess.setContainer(this.tilesContext, null);
    }

    /**
     * Internal implementation of the ServletConfig interface, to be passed
     * to the wrapped servlet. Delegates to ServletWrappingController fields
     * and methods to provide init parameters and other environment info.
     */
    private class DelegatingServletConfig implements ServletConfig {

        public String getServletName() {
            return "TilesConfigurer";
        }

        public ServletContext getServletContext() {
            return servletContext;
        }

        public String getInitParameter(String paramName) {
            return tilesPropertyMap.getProperty(paramName);
        }

        public Enumeration<?> getInitParameterNames() {
            return tilesPropertyMap.keys();
        }
    }
    
}

This version of the TilesConfigurer enables by default the EL support. It also allow to use Wildcards in it’s definitions, and will also allow definition files to be located in the classpath ie :

<bean id="tilesConfigurer" class="com.x.web.tiles2.SpringTilesConfigurer">
    <property name="definitions">
	<list>
	    <value>/WEB-INF/**/*.tiles-def.xml</value>
            <value>classpath:/your/package/directory/anotherTileConfigFile.xml</value>
            <value>classpath:**/*.tiles-def.xml</value>
        </list>
    </property>
</bean>

In this example, I dont use wildcard nor classpath definitions, so my applicationContext looks like this :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-2.5.xsd">

    <bean id="tilesConfigurer" class="com.x.web.tiles2.SpringTilesConfigurer">
        <property name="definitions">
            <list>
	        <value>/WEB-INF/defs/myTilesConfigFile.xml</value>
            </list>
        </property>
    </bean>

    <bean name="/searchBook.do" class="com.x.samples.bookbay.search.SearchController">
        <property name="commandClass" value="com.x.samples.bookbay.search.SearchCriteria"/>
        <property name="formView" value="/book/search.jsp"/>
        <property name="successView" value="/book/search.jsp"/>
    </bean>
</beans>

This starts perfectly, and calling the URL http://host:port/searchBook.do in my browser makes my search form to be displayed in the configured template :

spingtilesintegrationfinalscreenshot

My application is now ready to use Tiles 2, but my controller still uses the JSP directly for resolving its views. It is possible to tell spring MVC to map logical view names directly to defined tiles. For this we have to set a ViewResolver to use “org.springframework.web.servlet.view.tiles2.TilesView” as its view class.
Taking a look back to my Tiles integration, one thing annoys me. The fact that I must create a jsp (/book/search.jsp) whose only purpose is to tell the web application to use the “searchBook” Tile. I can solve this by making my Controller directly call the “searchBook” tiles instead of “/book/search.jsp”.
Before configuring our Tiles view resolver, I deleted the useless /book/search.jsp, to make sure my application doesn’t use it. Next, I just have to change my applicationContext.xml to configure the ViewResolver and make my controller use the “searchBook” tile :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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-2.5.xsd">

    <bean id="tilesConfigurer" class="com.x.web.tiles2.SpringTilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/defs/myTilesConfigFile.xml</value>
            </list>
        </property>
    </bean>

    <bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
    </bean>

    <bean name="/searchBook.do" class="com.x.samples.bookbay.search.SearchController">
        <property name="commandClass" value="com.x.samples.bookbay.search.SearchCriteria"/>
        <property name="formView" value="searchBook"/>
        <property name="successView" value="searchBook"/>
    </bean>

</beans>

And now I have a Web application built on top of Spring, using Apache Tiles as its web template system.

Advertisements

71 Comments »

  1. A very useful example which gives good overview and usage of tiles2.
    I tried to use the SpringTileconfigurer class you had shared here but the compilation fails.

    I was just wondering how your SpringTilesConfigurer compiles.

    public String getContextPath() {
    return servletContext.getContextPath();
    }

    ServletContext does not have the above method.

    Please suggest!

    Comment by vikas — March 4, 2009 @ 3:38 pm | Reply

    • Oh, in servlet API V 2.4, it doesn’t, but in version 2.5, it does. Maybe I should have specified :)

      Comment by baraber — March 5, 2009 @ 4:51 am | Reply

  2. You said you use Spring MVC 2.5.6 but org.springframework.web.servlet.view.tiles2.TilesView is packed in Spring MVC 2.5.5. Can you upload running simple application with all dependencies?

    I tried to make my app work but I didnt find any complete solution via google search.

    Thanks

    Comment by cybertuner78 — March 6, 2009 @ 8:25 pm | Reply

    • Hi cybertuner78,
      after your comment, I verified my project to make sure I have not mistaken the spring mvc version. So I opened my spring-mvc.jar file to look à the manifest. It indicate that it is really in version 2.5.6. I’m not sure what is the problem you are speaking of, maybe you could post some configs or stack trace to detail it a little more ?

      Comment by baraber — March 7, 2009 @ 5:28 am | Reply

  3. Thank you sir for the immediate reply. My application works perfectly using your SpringTilesConfigurer. Have you contributed this class to spring framework?

    @CyberTuner: FYI, I am using spring mvc 2.5 and i didn’t faced any issues.

    Comment by vikas — March 9, 2009 @ 10:25 am | Reply

    • Hello vikas,
      The SpringTilesConfigurer class in my example is not complete enought to be added to Spring. As an example, it does not have any means to set a PreparerFactory class. I also don’t support some useful feature like using wildcards in my definitions configuration. I’m sure there is plenty of Tiles features this class won’t support, or won’t make configurable. A more complete class for this have been posted on the SpringSource forum : http://forum.springsource.org/showthread.php?t=65907 (Altough it don’t support the two examples mentionned above either). My class is based on this one, with the exception that I cleaned all that my example doesn’t need, to make it more readable in the context. So far it has been enough for me, but I didn’t use many features provided by tiles. If some of you out there can make it more complete, by example making it use wildcards in the definition configuration and allowing EL support in definitions, please make me know.

      Comment by baraber — March 11, 2009 @ 11:00 pm | Reply

  4. Thanks for the example It helped me out. Do you know how could I configure tiles to enable the EL Support? The official way is described here

    http://tiles.apache.org/framework/tutorial/advanced/el-support.html

    but I couldn’t figure out how to use integrate it into your solution

    Comment by Peter — March 11, 2009 @ 1:57 pm | Reply

    • Hello Peter.
      after reading your comment, I tried to enable EL, but for now I’m not successfull. If I manage to do it, I’ll post the source code, or will edit my post to show an example of using it. If anyone that read and know how to do it, make me know :)

      Comment by baraber — March 11, 2009 @ 11:04 pm | Reply

  5. Hi Barber

    I tried to hack the

    org.apache.tiles.evaluator.el.ELAttributeEvaluatr

    parameter into the context, but it did’t had any effect. By the way the wildcard are working for me by default with your code.

    Comment by Peter — March 11, 2009 @ 11:34 pm | Reply

    • Peter, I updated my post to show another version of my SpringTilesConfigurer class, that supports EL. I tested it and it seems to work perfectly. Let me know if it works for you.

      I posted that class to spring (in the jira issue) , I’m waiting for news.

      Comment by baraber — March 13, 2009 @ 4:09 pm | Reply

      • Hi Barber

        Thanks for your update the EL Support works perfectly for me too!

        Comment by Peter — March 15, 2009 @ 9:37 pm | Reply

  6. Hi Richard.
    Could you please post apache tiles 2 and spring web flow 2 integration guide?

    I’m stuck on that because I’m new to spring web flow 2.
    I think my problem is mapping to the controller.

    Could you please see my configuration?
    Any help will be much appreciated.

    Here’s my war file:
    http://www.mediafire.com/?02q4j3mgoee

    Comment by MethoD — March 14, 2009 @ 10:11 am | Reply

  7. Hi Richard.
    I’ve fixed my problem.
    And that was I forgot to include tiles tag library in my template jsp file.

    Comment by MethoD — March 14, 2009 @ 11:00 am | Reply

  8. cool thank you :-)

    Comment by Dennis — March 14, 2009 @ 6:43 pm | Reply

  9. Helle Richard,

    My application.xml is looks like as you’ve written ( I mean you have supposed that I use Your code for TilesConfigurer)

    /WEB-INF/defs/myTilesConfigFile.xml

    <!– /WebContent/WEB-INF/defs/myTilesConfigFile.xml –>

    As you can see my WEB-INF isn’t direct under the project folder, because I use Eclipse Dynamic Webproject
    and Eclipse generate a WebContent folder under my ProjetDirectory. But I’ve tried out in that way too:
    /WebContent/WEB-INF/defs/myTilesConfigFile.xml

    It doesn’t work. And I tried also to copy a WEB-INF direct to my project directory – uselessly…

    My myTilesConfigFile.xml file locates so (TilesSpring is my project directory, nagelNeuEkk is my Eclipse workspace

    c:\Kaffe\nagelNeuEkk\TilesSpring\WebContent\WEB-INF\defs\myTilesConfigFile.xml

    I’m quete at a loss :(

    Alice

    Comment by Alice — March 15, 2009 @ 8:29 pm | Reply

  10. Hello Richard,

    I’ve uploaded my applicationContext.xml file and a picture about my project directory structure.

    If you have any time, please see them. If it isn’nt trivial my error for you, I think it can be e bug in Eclipse (I’ve had a similar problem with it earlier)

    http://www.mediafire.com/?sharekey=126bfc8ca15f105d90a82c7bb0fad7ade04e75f6e8ebb871

    Thank you for all your helps!

    Alice

    Comment by Alice — March 15, 2009 @ 11:28 pm | Reply

    • Hehehe,
      I took look and found it. Under TilesSpring/WebContent/WEB-INF/defs, you named your file myTilesConfigurationFile.xml, but in your applicatonContext.xml, the name referred is myTilesConfigFile.xml, therefore the two file names are different.

      Comment by baraber — March 16, 2009 @ 12:32 am | Reply

  11. Huhh!! Million Thanks! I’m an idiot! I wasn’t able to detect it. Thank you very-very much.

    And the most important thing: Congratulations to your great TilesConfigurer solution!

    Alice

    Comment by Alice — March 16, 2009 @ 2:50 am | Reply

  12. Hi Richard,
    thanks for your tutorial, it helped me more than anything else in net.

    I have question, I have configured tiles for my project which has around 20 JSPs. I am facing two issues,

    1. In tiles-def.xml. tag needs full path of jsp for name and path attribute

    Can i replace this with view or something else ? is there any option to do that? how can you do that with view name?

    2. Tiles require me to define all my JSPs in tiles-def.xml, eventhough i am not using tiles in few JSPs (these jsps has different view than rest of the site).

    pls advice!

    Comment by Tamil Ramasamy — March 24, 2009 @ 11:25 pm | Reply

  13. Hi Richard,

    Good tutorial.
    I am working on client side form validation using Spring and Commons-validator by refering the Spring doc. If you have a tutorial on client side form validations, please share with us.

    Thank you.

    Comment by manjulab — March 26, 2009 @ 5:03 am | Reply

  14. Hi Robert,

    Did you know that your SpringTilesConfigurer fails in an OSGi environment? You are passing org.apache.tiles.servlet.context.wildcard.WildcardServletTilesApplicationContextFactory, which is in the tiles-servlet bundle, and Tiles will try to have it instantiated by org.apache.tiles.reflect.ClassUtil which is located in tiles-api bundle. The tiles-api bundle does not have an import dependency on tiles-servlet and consequently fails to instantiate the class because it can’t find it.

    Any ideas on this?

    Comment by Bjorn Harvold — March 30, 2009 @ 8:16 am | Reply

    • Hum, I must admit I had never worked in an OSGI environment. Can you help me test it ?

      Comment by baraber — March 30, 2009 @ 12:49 pm | Reply

  15. I’ve tried your example but the results are showing jsp page names instead of jsp contents by tiles. I’m new to the Spring and Tiles, so any help would be appreciated.
    -Jimmy

    Comment by jimmy — April 16, 2009 @ 6:59 pm | Reply

    • hmmm, maybe if you post me your config files I could find out …

      Comment by Richard — April 17, 2009 @ 9:01 am | Reply

  16. Here is the myTilesConfigFile.xml:
    ————————————————————————

    ———————————————————————————–

    and applicationContext.xml:

    ———————————————————————————–

    /WEB-INF/myTilesConfigFile.xml

    —————————————————————————————-

    I added ‘viewResolver’ because I’ve put jsp files into WEB-INF/jsp directory and template directory is under jsp.

    Thanks,
    Jimmy

    Comment by jimmy — April 17, 2009 @ 12:43 pm | Reply

  17. I figured it out and they are working now.

    Comment by jimmy — April 22, 2009 @ 6:54 pm | Reply

  18. Can any one provide some demo on struts2 with tiles with example.

    Thanks advance

    Comment by siddhartha — May 5, 2009 @ 2:47 am | Reply

  19. can you give me a sample code for above methods like as top.jsp, left.jsp, bottom.jsp and layout.jsp.

    I am using springmvc with tile. no idea on this regards.

    Thank you

    Comment by chinnu — May 14, 2009 @ 6:51 am | Reply

  20. I want to use tiles in my application . We are currently using JDK 1.4 . What version of tile should I be using. Will I face bootstrapping problem regarding Tiles versions 2.1 with the TilesConfigurer of Spring 2.5.6

    Comment by Jai Jonal — May 15, 2009 @ 12:22 pm | Reply

  21. Let me give u more info of my application . This is spring 2.5 ,OC4J stand alone app server ,JDK 1.4,using JSTL 1.0.6

    Comment by Jai Jonal — May 15, 2009 @ 1:19 pm | Reply

  22. This is a terrific example.
    I did have this issue that Spring’s TilesConfigurer is not updated with new Tiles2 when I was trying to upgrade Tiles with Spring 2.5.x.

    Comment by Dawn — June 1, 2009 @ 9:13 pm | Reply

  23. Two changes and i found my application working.

    1. After introducing, org.springframework.web.servlet.view.tiles2.TilesView in applicationContext.xml, had to change “showForm” and “processFormSubmission” like below:

    protected ModelAndView showForm(HttpServletRequest request,
    HttpServletResponse response, BindException errors)
    throws Exception {
    return showForm(request, errors, “searchBook”);
    }

    public ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response, Object criteria, BindException errors) throws Exception {
    getBooks((SearchCriteria) criteria);
    ModelAndView mav = new ModelAndView(“searchBook”);
    mav.addObject(“criteria”, criteria);
    return mav;
    }

    2. Instead of AbstractFormController, i had to use SimpleFormController.

    Comment by Anand — June 15, 2009 @ 6:16 am | Reply

  24. Thanks for pointing out the problem with [Class org.apache.tiles.web.util.ServletContextAdapter not recognized a TilesApplicationContext]. Really helped me out.

    Comment by anydoby — June 17, 2009 @ 6:24 am | Reply

  25. Hi! This page has been very helpful (specially your SpringTilesConfigurer). Thank you very much.

    But I found an issue,
    Apache Tiles 2.1 has dependency on jstl-1.2.jar and jstl-1.2 only works with resin-3.1.

    JSTL 1.2
    http://java.sun.com/products/jsp/jstl/
    The JSTL 1.2 Maintenace Release aligns with the Unified Expression Language (EL) that is being delivered as part of the JavaServer Pages (JSP) 2.1 specification. Thanks to the Unified EL, JSTL tags, such as the JSTL iteration tags, can now be used with JavaServer Faces components in an intuitive way.
    JSTL 1.2 is part of the Java EE 5 platform.

    Resin 3.0
    http://www.caucho.com/resin-3.0/jsp/intro.xtp
    Resin supports Sun’s JSP 2.0 specification

    I upgraded to Apache Tiles 2.1 by following your examples.
    I found errors on my application using resin-3.0.25
    but when I tested it with resin-3.1 version, the jsp pages are showing properly.
    Is there a way to upgrade to Apache Tiles 2.1 without upgrading resin or without upgrading its dependency jar to jstl-1.2.jar?

    Please help.

    -newbie badoodles

    Comment by badoodles — June 17, 2009 @ 11:51 pm | Reply

  26. Hi. I tried your example and things are working for me. But when I try to configure a preparer for my tiles definition, my custom view preparer is not getting called.
    So the situation is :
    1) in my tiles-defs.xml file :

    As you can see I have a preparer called menuPreparer whose definition resides in my tiles-config.xml file like this:

    /WEB-INF/tiles-defs.xml

    As you can see I have used your SpringTilesConfigurer.

    My MenuViewPreparer class looks like this:

    public class MenuViewPreparer implements ViewPreparer {
    public MenuViewPreparer(){

    }

    @Override
    public void execute(TilesRequestContext tilesContext, AttributeContext attribContext) {
    Attribute attrib = attribContext.getAttribute(“menuType”);
    attribContext.putAttribute(“menuItems”, new Attribute(“This is the menu item from viewPreparer”));
    String val = (String)attrib.getValue();
    System.out.println(“value of attrib menuType is: ” + val);;

    }

    But still my execute method is not getting called when the tiles definitiopn is being rendered. Am I doing something silly?

    Comment by Anuj — June 30, 2009 @ 9:23 am | Reply

  27. Since the code got filtered here is it once again :
    I tried your example and things are working for me. But when I try to configure a preparer for my tiles definition, my custom view preparer is not getting called.
    So the situation is :
    1) in my tiles-defs.xml file :

    definition name=”test.menu” preparer=”menuPreparer” template=”/jsp/menu.jsp”

    As you can see I have a preparer called menuPreparer whose definition resides in my tiles-config.xml file like this:

    bean id=”tilesConfigurer”
    class=”org.oclc.lbs.tiles.SpringTilesConfigurer”
    property name=”definitions”
    value /WEB-INF/tiles-defs.xml
    property name=”preparerFactoryClass”
    value=”org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory”

    bean id=”menuPreparer” class=”org.oclc.lbs.tiles.MenuViewPreparer” autowire=”byName”

    As you can see I have used your SpringTilesConfigurer.

    My MenuViewPreparer class looks like this:

    public class MenuViewPreparer implements ViewPreparer {
    public MenuViewPreparer(){

    }

    @Override
    public void execute(TilesRequestContext tilesContext, AttributeContext attribContext) {
    Attribute attrib = attribContext.getAttribute(”menuType”);
    attribContext.putAttribute(”menuItems”, new Attribute(”This is the menu item from viewPreparer”));
    String val = (String)attrib.getValue();
    System.out.println(”value of attrib menuType is: ” + val);;

    }

    But still my execute method is not getting called when the tiles definitiopn is being rendered. Am I doing something silly?

    Comment by Anuj — June 30, 2009 @ 9:27 am | Reply

  28. Thank you for a so useful tutorial: I was in “head bang” mode trying to configuring tiles 2.1 with spring 2.5.x, but with your article everything is running fine now.

    Comment by SLL — July 6, 2009 @ 4:58 pm | Reply

  29. Hi, very nice tutorial. Regarding the error, only in the latest tiles version that error occurs, i am using tiles 2.0.4 and I am not getting any error.

    regards,
    VaanNila

    Comment by Eswar — July 8, 2009 @ 7:16 pm | Reply

  30. Very useful tutorial, thank you. First I apologize for asking maybe self-evident questions but I’m newbie to the Spring/Tiles topic and have some trouble. Could you explain please how to bind (or map) my own controller with the particular tile? In another words, I have web page with some boxes (in terms of DOM), one of them consists of form. I’d like to have separate controller for that box and of course some other controllers for another parts of the web page as well. How to do mappings for that? I can see mappings for the whole pages (JSP), mappings for the whole Tiles definition but can’t see that for particular tile.
    Second question is how to launch Tiles view as the main page (index.html) with dedicated controller?

    Comment by AmiP — July 30, 2009 @ 7:55 pm | Reply

  31. Hi,
    Nice tutorial. I have tried your tutorial. It works fine.
    But why will my controller be invoked twice?
    Is there anything wrong?

    Comment by Agus — July 31, 2009 @ 2:23 am | Reply

  32. Hi Richard,
    Wonderful tutorial.But while trying this i am getting the following exception :( Please guide me to resolve this issue.

    javax.el.ELException: Expression cannot be null
    at org.apache.el.lang.ExpressionBuilder.createNodeInternal(ExpressionBuilder.java:87)
    at org.apache.el.lang.ExpressionBuilder.build(ExpressionBuilder.java:146)
    at org.apache.el.lang.ExpressionBuilder.createValueExpression(ExpressionBuilder.java:190)
    at org.apache.el.ExpressionFactoryImpl.createValueExpression(ExpressionFactoryImpl.java:68)
    at org.apache.tiles.evaluator.el.ELAttributeEvaluator.evaluate(ELAttributeEvaluator.java:156)
    at org.apache.tiles.evaluator.AbstractAttributeEvaluator.evaluate(AbstractAttributeEvaluator.java:44)
    at org.apache.tiles.renderer.impl.AbstractBaseAttributeRenderer.render(AbstractBaseAttributeRenderer.java:101)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:659)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:678)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:633)
    at org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:322)
    at org.apache.tiles.jsp.taglib.InsertDefinitionTag.renderContext(InsertDefinitionTag.java:66)
    at org.apache.tiles.jsp.taglib.InsertTemplateTag.render(InsertTemplateTag.java:81)
    at org.apache.tiles.jsp.taglib.RenderTag.doEndTag(RenderTag.java:220)
    at org.apache.jsp.login_jsp._jspx_meth_tiles1_005finsertDefinition_005f0(login_jsp.java:91)
    at org.apache.jsp.login_jsp._jspService(login_jsp.java:61)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
    at org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
    at org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:166)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
    at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
    at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
    at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Unknown Source)

    Comment by Karthick Pitchaiah — August 10, 2009 @ 6:06 am | Reply

  33. Hi richard,
    Any update on that issue.

    Comment by Karthick Pitchaiah — August 13, 2009 @ 7:47 am | Reply

  34. Hi, This was really useful.Thank you. I haven’t got it right completely. I’m sure I have missed out something. But couldn’t figure out. I have used your TilesConfigurer and I use Spring 2.5.6 and Tiles 2.1.2(and all the libraries as you’ve mentioned). I reckon it’s due to some jar file clash? I’m stumped! Please help. Thanks.

    STACK TRACE
    ————
    java.lang.VerifyError: (class: org/apache/tiles/evaluator/el/TomcatExpressionFactoryFactory, method: getExpressionFactory signature: ()Ljavax/el/ExpressionFactory;) Wrong return type in function
    at org.apache.tiles.evaluator.el.ELAttributeEvaluator.init(ELAttributeEvaluator.java:104)

    Comment by Sai — September 2, 2009 @ 12:06 pm | Reply

  35. Thanks !! All works fine !!
    (maybe you should show source code of SearchController, or offer a download of the example)

    Thanks again !

    Comment by Odyssée — December 3, 2009 @ 9:01 am | Reply

  36. Allstate – Auto Insurance Quotes Online – Formal Locale seeing that Passenger car Cover, Accommodations Insurance, Fiscal Products & More Rates and guaranty options (and their availability) diverge according to your formal’s regulations.All you hold to do is conjoin your make clear and auto bond with Allstate, and you muscle shelter up to 20%. Hands down, it’s the easiest way to secure a fortune of money without sacrificing standing protection.

    Comment by free travel — December 23, 2009 @ 8:33 pm | Reply

  37. This is what I did. I’m new to spring. I was also getting the above exceptions.

    Please let me know if this is wrong.

    Spring 2.5, Tiles 2.1

    Instead of putting this in my blah-servlet.xml:

    /WEB-INF/tiles-config/basic-templates.xml

    i put this in my web.xml

    org.apache.tiles.definition.DefinitionsFactory.DEFINITIONS_CONFIG
    /WEB-INF/myTilesConfigFile.xml

    org.apache.tiles.web.startup.TilesListener

    Thats it.

    So now my home.html calls my HomeController which calls my home.jsp which uses tiles. Works like a charm.

    Just because it works, I don’t know if its right. Feel free to comment.

    Thanks

    Comment by oakleyx — February 9, 2010 @ 1:34 pm | Reply

  38. Hi Richard,
    thanks for this informative post. Have you experimented with the new Spring 3.0.0.RELEASE and Tiles2? I am having some trouble enabling EL support with Tiles 2.1.4, and there seems to be very little information out there. Unfortunately the TilesConfigurer does not output any debug information on enabling this feature so I can’t tell what is happening under the covers, except that any EL placed in my definitions files is rendered as a string literal on the page. I tried your amended TilesConfigurer to no effect, and also tried changing the TilesConfigurer bean definition to include :

    org.apache.tiles.evaluator.el.ELAttributeEvaluator

    However this did nothing also.
    Any suggestions/experiences would be greatly welcomed.

    thanks.

    Comment by Adrian — February 24, 2010 @ 12:20 am | Reply

  39. I tried this tutorial with Tiles 2.2.1 and Spring 2.5.5 and was not successful using the SpringTilesConfigurer class provided by Rich. I got some sort of method not found setJspContext exception even though I had all dependencies. I had to use Tiles specific SimpleTilesListener to bootstrap Tiles and that did it. This way I was able to integrate Spring 2.5.5 and Tiles 2.1.

    Comment by Eugene — April 24, 2010 @ 12:40 pm | Reply

  40. Richard: Spring 3.0.1 has fixed the issue you mention, along with http://jira.springframework.org/browse/SPR-6097

    This how to is incredibly useful and Antonio from the Tiles2 project would like to link to it from the Tiles2 documentation.
    http://permalink.gmane.org/gmane.comp.apache.tiles.devel/10

    Any chance of updating/simplifying it now that the workaround is no longer necessary?

    Comment by mck — April 27, 2010 @ 4:09 am | Reply

  41. Hello Richard I was not able to make EL to work in templates definition.
    Can you help ?
    I am using your tilesConfigurer with no changes. I run on tomcat not resin and JSTL and JSP Expression Language ( not UL ) works fine on all pages.
    I need to make something like this:
    in the template I have:
    TITLE is

    and in templates.xml I have :

    but when I view the page I see :
    TITLE is ${navigationState.selectedFacets}
    so the expression is not evaluated.
    Can you help ? :(

    Comment by JOKe — June 15, 2010 @ 3:36 am | Reply

  42. Hello Richard I was not able to make EL to work in templates definition.
    Can you help ?
    I am using your tilesConfigurer with no changes. I run on tomcat not resin and JSTL and JSP Expression Language ( not UL ) works fine on all pages.
    I need to make something like this:
    in the template I have:
    TITLE is <tiles:getAsString name=”title” ignore=”true”/>

    and in templates.xml I have :
    <definition name=”some.fragment.name”
    template=”/WEB-INF/path/to/my/jsp/result.jsp”>
    <put-attribute name=”title” value=”${navigationState.selectedFacets}”/>
    </definition>

    but when I view the page I see :
    TITLE is ${navigationState.selectedFacets}
    so the expression is not evaluated.
    Can you help ? :(

    Comment by JOKe — June 15, 2010 @ 3:37 am | Reply

  43. Hi Rich, I try follow your steps, but i have found this error:

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’tilesConfigurer’ defined in ServletContext resource [/WEB-INF/AESAN_GEDA-servlet.xml]: Invocation of init method failed; nested exception is

    java.lang.NoSuchMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext(Ljavax/servlet/ServletContext;)Ljavax/servlet/jsp/JspApplicationContext;

    How can i fix it?
    thanks for wacthing!!

    Comment by J — August 18, 2010 @ 5:44 am | Reply

  44. Hi
    Can I get complete war file for this project? so that it will be easy for me o understand the working of project as I am new to spring framework

    Comment by Harit — December 20, 2010 @ 4:21 pm | Reply

  45. Can any body please send me the working source code of the project? Please help me. I tried to follow but got error: “The requested resource () is not available.” from the web browser but there is no error. please kindly email the source code to me: jemrusalem07@yahoo.com. Thanks alot!

    Comment by jem — April 11, 2011 @ 9:37 am | Reply

  46. Hi,

    Issue: Could not inistantiate TilesConfigure bean when i am loading
    app-servlet.xml in my standalone programe.Following is the entry in app-servlet.xml

    /WEB-INF/tiles.xml

    Exception:

    Initializing sessionFactory in EarthBaseDaoImpl
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ’tilesConfigurer’ defined in class path resource [earth-servlet.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1403)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:562)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:871)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:423)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:119)
    at com.citi.earth.common.context.AppContextFactory.getAppContext(AppContextFactory.java:30)
    at com.citi.earth.common.context.InitializerManager.initilizeMasterdata(InitializerManager.java:22)
    at com.citi.earth.common.context.InitializerManager.init(InitializerManager.java:18)
    at com.citi.earth.common.context.InitialContextServlet.init(InitialContextServlet.java:16)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:993)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4350)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4659)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:546)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1041)
    at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:964)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:502)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1277)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:321)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:445)
    at org.apache.catalina.core.StandardService.start(StandardService.java:519)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
    Caused by: java.lang.NullPointerException
    at org.springframework.web.servlet.view.tiles2.SpringTilesApplicationContextFactory$SpringWildcardServletTilesApplicationContext.(SpringTilesApplicationContextFactory.java:72)
    at org.springframework.web.servlet.view.tiles2.SpringTilesApplicationContextFactory.createApplicationContext(SpringTilesApplicationContextFactory.java:55)
    at org.springframework.web.servlet.view.tiles2.TilesConfigurer.afterPropertiesSet(TilesConfigurer.java:301)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1460)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1400)
    … 41 more

    Comment by Lakshmipathi — July 27, 2011 @ 9:08 am | Reply

  47. Hi,
    I tried with Spring 3.0.5 and Tiles 2.2.2. I am facing the same problem. Can any one throw some hints?

    Comment by shiv — August 12, 2011 @ 11:42 am | Reply

  48. A version of this for the Spring Portal Framework and DispatcherPortlet vs. DispatcherServlet would be lovely, any chance?

    Comment by Mike Oliver — September 14, 2011 @ 4:17 am | Reply

  49. […] Apache Tiles 2, integration with Spring-MVC « Richard’s WeblogFeb 23, 2009 … There seems to be a problem bootstrapping Tiles versions 2.1 with the TilesConfigurer of Spring 2.5.6. When launching the web application … […]

    Pingback by Spring tiles | Jamesandjennif — March 29, 2012 @ 1:33 pm | Reply

  50. very nice Explaination :)

    Comment by Sunil kumar kondeti — April 9, 2012 @ 6:26 am | Reply

  51. […] https://richardbarabe.wordpress.com/2009/02/23/apache-tiles-2-integration-with-spring-mvc/ This entry was posted on Friday, May 11th, 2012 at 5:21 pmand is filed under web, 編程. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. […]

    Pingback by save me time ! solve | code@butterflybone — May 11, 2012 @ 5:21 am | Reply

  52. thank you for your advise, but i not complete this event.because i see same message(problem)…… also i have other question. I have to use to sql and db exp in tile2 controller………

    Comment by nam — June 21, 2012 @ 1:56 am | Reply

  53. here is maven dependency for tiles plugin for spring 3

    org.apache.tiles
    tiles-api
    2.1.4

    org.apache.tiles
    tiles-core
    2.1.4

    org.apache.tiles
    tiles-jsp
    2.1.4

    org.apache.tiles
    tiles-servlet
    2.1.4

    commons-logging
    commons-logging
    1.1.1

    commons-beanutils
    commons-beanutils
    1.8.2

    commons-digester
    commons-digester
    1.8.1

    Comment by Java Tutorials Blog — December 20, 2012 @ 10:56 am | Reply

  54. […] 참조: https://richardbarabe.wordpress.com/2009/02/23/apache-tiles-2-integration-with-spring-mvc/ […]

    Pingback by 개발 팁 인덱싱 | Spring MVC – TilesView – tiles 2 연동 [출처] [펌] Spring MVC – TilesView – tiles 2 연동|작성자 깜장토끼 — April 1, 2013 @ 5:02 am | Reply

  55. Fantastic goods from you, man. I have understand your stuff previous to and you
    are just too wonderful. I really like what you have
    acquired here, really like what you are saying and the
    way in which you say it. You make it enjoyable and you still take
    care of to keep it wise. I can’t wait to read much more from you. This is actually a wonderful web site.

    Comment by Larue — April 26, 2013 @ 5:02 am | Reply

  56. I have learn a few good stuff here. Definitely worth
    bookmarking for revisiting. I wonder how much effort you place to create this sort of magnificent informative site.

    Comment by [主页] — May 5, 2013 @ 8:37 pm | Reply

  57. Buying a new property Your child’s education Any other personal, business or professional needSpecialty:- Door step service Minimum processing fee Free personal accident insurance Bad credit history is rarely easy. If you’re currently
    on a car loans for bad credit is because every lender decides on their criteria on their own, or
    other projects can really make your house shine.

    Comment by Bad Credit car loans — July 23, 2013 @ 11:01 pm | Reply

  58. I love what you guys are usually up too. Such clever work and
    reporting! Keep up the great works guys I’ve included you guys to our blogroll.

    Comment by social media — July 27, 2013 @ 3:13 pm | Reply

  59. thanks a lot you save my very crucial couple of hour

    Comment by Abdul Quadir — December 4, 2014 @ 2:39 am | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: