Monday, January 19, 2015

Spring 4 and Tiles 3 programmatic or annotation based configuration

In the following tutorial, we are going to use programmatic / no-xml based spring 4.0.1 MVC project and Apache tile 3 configuration. I have used maven with STS 3.6.2.RELEASE to create the project.


Following are the versions user in this tutorial

  • Spring: 4.0.1.RELEASE
  • Java: 1.8
  • Servlet-api: 3.1.0
  • Servlet-jsp: 2.2
  • Servlet-jstl: 1.2
  • Apache tiles: 3.0.5

Now, lets see step by step approach of programmatic configuration of spring mvc project.


  • Create Project
    For project creation checkout "Spring 4 programmatic or annotation based configuration

  • Add following dependencies to pom.xml
    <!-- Apache Tiles -->
    <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-api</artifactId>
    <version>3.0.5</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-core</artifactId>
    <version>3.0.5</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-jsp</artifactId>
    <version>3.0.5</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-servlet</artifactId>
    <version>3.0.5</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-template</artifactId>
    <version>3.0.5</version>
    <scope>compile</scope>
    </dependency>
    <dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-el</artifactId>
    <version>3.0.5</version>
    <scope>compile</scope>
    </dependency>
  • Add TilesViewResolver and TilesConfigurer to MVCConfig class file
    package com.test.web.config;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.support.ReloadableResourceBundleMessageSource;
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
    import org.springframework.web.servlet.view.tiles3.TilesView;
    import org.springframework.web.servlet.view.tiles3.TilesViewResolver;

    /**
     * @author Bhimu
     *
     *<code>Spring MVC configuration class</code>
     */
    @EnableWebMvc
    @Configuration
    @ComponentScan(basePackages = { "com.skillzview.web" })
    public class MVCConfig extends WebMvcConfigurerAdapter {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }


    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
    }


    /**
    * <code>Resolves views selected for rendering by @Controllers to tiles resources in the Apache TilesConfigurer bean</code>
    */
    @Bean
    public TilesViewResolver getTilesViewResolver() {
    TilesViewResolver tilesViewResolver = new TilesViewResolver();
    tilesViewResolver.setViewClass(TilesView.class);
    return tilesViewResolver;
    }


    /**
    * <code>Configures Apache tiles definitions bean used by Apache TilesViewResolver to resolve views selected for rendering by @Controllers</code>
    */
    @Bean
    public TilesConfigurer getTilesConfigurer() {
    TilesConfigurer tilesConfigurer = new TilesConfigurer();
    tilesConfigurer.setCheckRefresh(true);
    tilesConfigurer.setDefinitionsFactoryClass(TilesDefinitionsConfig.class);

    // Add apache tiles definitions
    TilesDefinitionsConfig.addDefinitions();

    return tilesConfigurer;
    }
    }
  • Create TilesDefinitionsConfig which implements DefinitionsFactory interface.
    package com.test.web.config;

    import java.util.HashMap;
    import java.util.Map;

    import org.apache.tiles.Attribute;
    import org.apache.tiles.Definition;
    import org.apache.tiles.definition.DefinitionsFactory;
    import org.apache.tiles.request.Request;

    /**
     * @author Bhimu
     *
     * <code>Apache tiles configuration class. Implements DefinitionsFactory to provide programmatic configuration for Apache tiles.</code>
     *
     */
    public final class TilesDefinitionsConfig implements DefinitionsFactory {

    private static final Map<String, Definition> tilesDefinitions = new HashMap<String,Definition>();
    private static final Attribute BASE_TEMPLATE = new Attribute("/WEB-INF/views/layout/defaultLayout.jsp");

    @Override
    public Definition getDefinition(String name, Request tilesContext) {
    return tilesDefinitions.get(name);
    }

    /**
    * @param name <code>Name of the view</code>
    * @param title <code>Page title</code>
    * @param body <code>Body JSP file path</code>
    *
    * <code>Adds default layout definitions</code>
    */
    private static void addDefaultLayoutDef(String name, String title, String body) {
    Map<String, Attribute> attributes = new HashMap<String,Attribute>();

    attributes.put("title", new Attribute(title));
    attributes.put("header", new Attribute("/WEB-INF/views/layout/header.jsp"));
    //attributes.put("menu", new Attribute("/WEB-INF/views/layout/menu.jsp"));
    attributes.put("body", new Attribute(body));
    attributes.put("footer", new Attribute("/WEB-INF/views/layout/footer.jsp"));

    tilesDefinitions.put(name, new Definition(name, BASE_TEMPLATE, attributes));
    }

    /**
    * <code>Add Apache tiles definitions</code>
    */
    public static void addDefinitions(){
    addDefaultLayoutDef("home", "Home", "/WEB-INF/views/home.jsp");
    }
    }
  • Create layout JSP files.
  • defaultLayout.jsp contents.
    <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>  
    <html>
      <head>    
       <title><tiles:insertAttribute name="title" ignore="true"></tiles:insertAttribute></title>
    </head>
    <body style="background-color: #FFF">
    <div class="page">
           <tiles:insertAttribute name="header" />
           <div class="content">
            <div id="body">
                <tiles:insertAttribute name="body" />
               </div>
           </div>
           <tiles:insertAttribute name="footer" />
       </div>
    </body>
    </html>
  • Put whatever content you want in header, footer and body(home.jsp) pages.

We are all set with configuration. now run your application. I have used tomcat 8 to run the project.

Spring 4 programmatic or annotation based configuration

In the following tutorial, we are going to use programmatic / no-xml based spring 4.0.1 MVC project configuration. I have used STS 3.6.2.RELEASE to create the project.

Following are the versions user in this tutorial.

  • Spring: 4.0.1.RELEASE
  • Java: 1.8
  • Servlet-api: 3.1.0
  • Servlet-jsp: 2.2
  • Servlet-jstl: 1.2
Now, lets see step by step approach of programmatic configuration of spring mvc project.

  • Create a spring mvc project.

    1. Select from menu: File > New > Spring Project.
    2. Provide a project name select "Spring MVC Project" as template.
    3. Next, provide top-level package and say finish.


  • Make following changes to pom.xml

    • Change spring and java versions
    • <java-version>1.8</java-version>
      <org.springframework-version>4.0.1.RELEASE</org.springframework-version>
    • Add maven-war-plugin to compile successfully even if there is no web.xml
    • <plugins>
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-war-plugin</artifactId>
      <configuration>
      <failOnMissingWebXml>false</failOnMissingWebXml>
      </configuration>
      </plugin>
      </plugins>
    • Add servlet dependencies.
    • <!-- Servlet -->
      <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>compile</scope>
      </dependency>
      <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
      <scope>compile</scope>
      </dependency>

  • Create following class files.

    1. WEB Application initializer.
    2. package com.test.web.config;

      import javax.servlet.ServletContext;
      import javax.servlet.ServletRegistration;

      import org.springframework.web.WebApplicationInitializer;
      import org.springframework.web.context.ContextLoaderListener;
      import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
      import org.springframework.web.servlet.DispatcherServlet;

      /**
       * @author Bhimu
       *
       *<code>Web application configuration class</code>
       */
      public class WebAppInitializer implements WebApplicationInitializer {

          @Override
          public void onStartup(ServletContext container) {
              // Create the 'root' Spring application context
              AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
              //rootContext.register();

              // Manage the lifecycle of the root application context
              container.addListener(new ContextLoaderListener(rootContext));

              // Create the dispatcher servlet's Spring application context
              AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
              dispatcherServlet.register(MVCConfig.class);
                 
              // Register and map the dispatcher servlet
              ServletRegistration.Dynamic dispatcher = container.addServlet("app-dispacher", new DispatcherServlet(dispatcherServlet));
              dispatcher.setLoadOnStartup(1);
              dispatcher.addMapping("/");
             
          }

       }
    3. Create Spring MVC configuration class
    4. package com.test.web.config;

      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.ComponentScan;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
      import org.springframework.web.servlet.config.annotation.EnableWebMvc;
      import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
      import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
      import org.springframework.web.servlet.view.InternalResourceViewResolver;

      /**
       * @author Bhimu
       *
       *<code>Spring MVC configuration class</code>
       */
      @EnableWebMvc
      @Configuration
      @ComponentScan(basePackages = { "com.test.web" })
      public class MVCConfig extends WebMvcConfigurerAdapter {


      @Override
      public void addResourceHandlers(ResourceHandlerRegistry registry) {
      registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
      }


      @Override
      public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
      configurer.enable();
      }


      /**
      * <code>Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory</code>
      */
      @Bean
      public InternalResourceViewResolver jspViewResolver() {
      InternalResourceViewResolver bean = new InternalResourceViewResolver();
      bean.setPrefix("/WEB-INF/views/");
      bean.setSuffix(".jsp");
      return bean;
      }
      }
    5. Delete following file/dir from WEB-INF (We don't need these xml configuration files)
    6. spring (dir)
      web.xml (file)

We are all set with configuration. now run your application. I have used tomcat 8 to run the project.