Struts2 and Tiles Tutorial

This updated tutorial shows how to build and deploy on WildFly a Struts 2 application powered by Apache Tiles, a template framework for Java Web applications.

Pre-requisites: we recommend checking this tutorial to learn how to deploy Struts2 applications on WildFly: Getting started with Struts 2 on WildFly

Apache Tiles allows authors to define page fragments which can be assembled into a complete page at runtime. These fragments, or tiles, can be used as reusable templates in order to reduce the duplication of common page elements or even embedded within other tiles.

To enable Apache tiles, you need at first some configuration steps in web.xml file. Then, you need to add a specific configuration file (tiles.xml) for this framework. The next section discusses this step.

Configuring Struts 2 and Apache Tiles

Firstly, to configure Apache tiles, you need to add an entry for Tiles listener in web.xml. Following here is the web.xml file which contains both the StrutsTiles listener and the Struts2 dispatcher:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="struts_blank" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
   <display-name>Struts Blank</display-name>
   <listener>
      <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
   </listener>
   <context-param>
      <param-name>tilesDefinitions</param-name>
      <param-value>/WEB-INF/tiles.xml</param-value>
   </context-param>
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
   </filter>
   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

As you can see from the above code, we need to include three main items in our configuration:

  • The StrutsTilesListener to automatically tie Tiles support into Struts
  • The StrutsPrepareAndExecuteFilter which handles both the preparation and execution phases of the Struts dispatching process
  • Finally, we pass as argument to the above filter the configuration file /WEB-INF/tiles.xml. This file contains the Tiles definition for our web application.

ClassNotFoundException: org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

If you are using Struts 2 version 2.5 you need to change from: org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter to:
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter

Next, let’s add the tiles.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!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="baseLayout" template="/layout.jsp">
       <put-attribute name="title" value="" />
       <put-attribute name="header" value="/header.jsp" />
       <put-attribute name="menu" value="/menu.jsp" />
       <put-attribute name="body" value="" />
       <put-attribute name="footer" value="/footer.jsp" />

   </definition>
   <definition name="/welcome.tiles" extends="baseLayout">
       <put-attribute name="title" value="Welcome page" />
       <put-attribute name="body" value="/welcome.jsp" />
   </definition>

</tiles-definitions>

This configuration file sets up the default layout (baseLayout) which includes Title, Header, Menu, Body and Footer. Besides, it also adds another definition (welcome.tiles) that extends the main template and just set its body.

Adding the JSPs to the project

The first JSP we will add is layout.jsp. This template will contain the different segments used in the web page (Header, Footer, Menu etc).

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><tiles:insertAttribute name="title" ignore="true" /></title>
     
</head>
<body id="home">
<div id="header">
    <tiles:insertAttribute name="header" />
</div>
<div id="wrap">
    <div id="content">
        <tiles:insertAttribute name="body" />
    </div>
    <div id="sidebar">
        <tiles:insertAttribute name="menu" />
    </div>
    <div id="footer">
        <tiles:insertAttribute name="footer" />
    </div>
</div>
</body>
</html>

Next, create the following JSP files with the following content in each of them.
header.jsp

<div style="padding:16px;background-color:blue">
<h3>This is the Page Header</h3>
</div>

Then, include the footer.jsp

<div style="padding:16px;background-color:red">
<h3>This is the Page Footer</h3>

Then, include the menu.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<br/>
<s:url  namespace="/" action="logout.action" value="To exit ->" />


<s:url  action="logout.action" var="urlTag" />

<s:a href="%{urlTag}">Logout</s:a>

<s:a errorText="Sorry your request had an error."
    href="%{testUrlId}">

</s:a>
</div>

Finally, include the welcome.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
 
<head>
<title>Struts 2 - Tiles example Application</title>
</head>
<body>
    <h2>Welcome, <s:property value="username" />!</h2>
       
    Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor 
    incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 
    quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi 
    consequat. 
    Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu 
    fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident,
    sunt in culpa qui officia deserunt mollit anim id est laborum.
</body>
</html>

As you can see the welcome page dumps a property username which derives from the following index.jsp page:
index.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Struts 2 - Login Application</title>
</head>
<body>
<h2>Struts 2 - Login Application</h2>
 
<s:form action="login.action" method="post">
    <s:textfield name="username" label="Username" size="20" />
    <s:password name="password" label="Password" size="20" />
    <s:submit method="execute" label="Login" align="center" />
</s:form>
</body>
</html>

Coding the Struts 2 action

In Struts terms, Action classes act as the controller in the MVC pattern. Action classes respond to a user action, execute business logic and then return a result that tells Struts what view to render.

Here is the Struts2 Login action which authenticates the user and returns the appropriate action:

package struts2.example;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport{
    private String username;
    private String password;
 
    public String authenticate() {
 
        if (this.username.equals("admin")
                && this.password.equals("admin")) {
            return "success";
        } else {
            addActionError(getText("error.login"));
            return "error";
        }
    }
 
    public String logout() {
            return "logout";
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
}

Struts 2 Configuration

The main configuration file of a Struts2 application is struts.xml. You need to place this file in the application’s classpath. For example, in a Maven project, place it under src/main/resources. Following up the build phase, the Maven builder will place it into WEB_INF/classes.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
  <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
  <constant name="struts.devMode" value="true"/>
  
    <package name="default" extends="struts-default" namespace="/">
        <result-types>
            <result-type name="tiles"
                class="org.apache.struts2.views.tiles.TilesResult" />
        </result-types>
 
        <action name="login" method="authenticate"
            class="struts2.example.LoginAction">
            <result name="success" type="tiles">/welcome.tiles</result>
            <result name="error" type="tiles">/index.jsp</result>
        </action>
 
        <action name="logout" method="logout" 
            class="struts2.example.LoginAction">
            <result name="logout">/index.jsp</result>
        </action>
    </package>
</struts>

Building the application

In order to build and package your application, you can use the following pom.xml file which contains the dependencies for Jakarta EE 8 applications along with Struts2 and Tiles dependencies:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mastertheboss</groupId>
    <artifactId>struts-demo</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>struts-demo Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <struts2.version>2.5.26</struts2.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>8.0.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>${struts2.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-tiles-plugin</artifactId>
            <version>${struts2.version}</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>struts-demo</finalName>
    </build>
</project>

Testing the application

Next, deploy the application on WildFly. Upon requesting the welcome page, the Login screen will appear:

Enter “admin” / “admin” to continue. You will be redirected to the Welcome page:

Conclusion

This article was a walk through the design and configuration of a simple Struts 2 application which uses Apache Tiles as templating framework.

Source code: https://github.com/fmarchioni/mastertheboss/tree/master/web/struts-tiles-demo