Apache Struts has traditionally been associated with XML configuration, particularly the struts.xml file used to define actions and results. Struts 2 can also use its Convention Plugin and annotations to reduce that configuration substantially.

This tutorial demonstrates a Struts 2.5 application in which action and result mappings are declared with annotations instead of struts.xml. The application still uses web.xml to register the Struts filter, so "zero configuration" here specifically means that no Struts action-configuration XML file is required.

Struts 2.5 Maven configuration

Maven can manage the libraries required by the application. The important Struts dependencies in this example are struts2-core and struts2-convention-plugin. The Servlet API is supplied by the application server and should therefore use provided scope.

This article preserves the Struts 2.5 generation used by the original example. For a new application, use a currently supported Struts release and align all Struts module versions rather than copying these historical version numbers into a production project.

<dependencies>

  <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-core</artifactId>

    <version>2.5.33</version>

  </dependency>

  <dependency>

    <groupId>org.apache.struts</groupId>

    <artifactId>struts2-convention-plugin</artifactId>

    <version>2.5.33</version>

  </dependency>

  <dependency>

    <groupId>javax.servlet</groupId>

    <artifactId>javax.servlet-api</artifactId>

    <version>3.1.0</version>

  </dependency>

</dependencies>

Struts 2.5 web.xml configuration

To route incoming HTTP requests through Struts, register StrutsPrepareAndExecuteFilter in the application's deployment descriptor. Because this is a Struts 2.5-era example, it uses the older Java EE javax.servlet namespace rather than the newer Jakarta jakarta.servlet namespace.

Here is the updated web.xml file in its entirety:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"

xmlns="https://java.sun.com/xml/ns/javaee"

xsi:schemaLocation="https://java.sun.com/xml/ns/javaee

https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

id="apache-struts-config-example"

version="3.0">

  <display-name>Example Not Struts Config XML</display-name>

  <filter>

    <filter-name>struts2</filter-name>

    <filter-class>

    org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter

    </filter-class>

  </filter>

  <filter-mapping>

    <filter-name>struts2</filter-name>

    <url-pattern>/*</url-pattern>

  </filter-mapping>

</web-app>

Struts flow of execution

The Struts flow of execution for any web based request-response cycle follows the same basic pattern:

  • Form data is sent to the server through a web based HTML form
  • The request is mapped to a Struts action class
  • Fields in the HTML form are mapped to properties in the action class
  • The execute method of the action class is invoked
  • A web page is invoked to render the response for the client

In this Apache Struts example the following components will be used to implement the Struts flow:

  • A file named index.jsp which contains the HTML form and an input box named firstName
  • A Java class named HelloAction with a property named firstName and an execute method
  • A file named results.jsp that includes the firstName property in the response it renders back to the client

The Struts HTML input form

There are three key elements to the index.jsp that allow the server-side Apache Struts components to process the web request:

  • The HTML form used to send user input to the server
  • The action of the form that references hello.action
  • The input field assigned the name value of firstname

Here is the full code for the input.jsp:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Struts input example</title>
</head>
<body>
  <form action="hello.action" method="post">
    <label>
      May I ask your name?
      <input type="text" name="firstName">
    </label>
    <input type="submit" value="Submit">
  </form>
</body>
</html>

The Struts Action class

The HTML form invokes a server-side resource named hello.action. This component is embodied in source code through the class named HelloAction.java. Notice the class includes an @Action annotation which defines its name, and a @Result annotation that indicates the results.jsp file should be used to render a response to the client if the execute method runs successfully. There is also a property named firstName which maps to the input field in the HTML form with the same name.

package com.mcnz.struts;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;

@Action("/hello")
@Result(name = "success", location = "/results.jsp")
public class HelloAction {

    private String firstName;

    public String execute() {
        System.out.println("Inside execute of hello.action");
        System.out.println("Value of firstName is: " + firstName);
        return "success";
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

Historically, these action and result mappings would commonly be declared in struts.xml. Here, the Convention Plugin discovers the action while the @Action and @Result annotations provide the mapping metadata, so a separate Struts action-configuration file is unnecessary.

The Struts result page

When execute() returns success, Struts selects results.jsp according to the @Result annotation. The JSP can then read the action's firstName property with the Struts tag library.

<%@ page contentType="text/html; charset=UTF-8" %>

<%@ taglib prefix="s" uri="/struts-tags" %>

<html>

<body>

  Results page

  Hello <s:property value="firstName"/> !!!

</body>

</html>

With the required files created and coded, the Apache Struts example can be packaged as file named struts-example.war and deployed to any Java applications server such as Tomcat or Jetty. The URL to access the index.jsp file will take the form:

https://localhost:8080/struts-example/index.jsp

Struts 2.5 and production applications

Struts 2.5 is a legacy release line. Treat this page as an explanation of the configuration technique rather than a recommendation to start a new application on the exact dependency versions shown here. For production work, select a currently supported Struts release, keep all Struts modules on compatible versions and follow the project's current upgrade and security guidance.

How to write an Apache Struts example

In review, the steps to code a simple Apache Struts 2 example without a Struts config XML file are:

  • Add the required Struts and Servlet API dependencies to the Maven project
  • Register StrutsPrepareAndExecuteFilter in web.xml
  • Create a standard web page with an input form and a reference to a Struts action
  • Code a Struts action class with an execute() method to handle the HTML form submission
  • Create a JSP that can render a response when the Struts action indicates execution succeeded

And that’s all there is to creating an Apache Struts example application that does not require a Struts config XML file.

Full Apache Struts 2.5 example Maven file

The earlier dependency fragment showed only the libraries required by the example. The complete historical-style POM below also configures the compiler for Java 8 bytecode. Again, use current supported dependency versions for a new production application.

<project xmlns="https://maven.apache.org/POM/4.0.0"

  xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mcnz</groupId>

  <artifactId>struts-example-no-struts-config-xml</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <packaging>war</packaging>

  <!-- Example Struts App with no Struts Config XML file -->

  <dependencies>

    <dependency>

      <groupId>org.apache.struts</groupId>

      <artifactId>struts2-core</artifactId>

      <version>2.5.33</version>

    </dependency>

    <dependency>

      <groupId>org.apache.struts</groupId>

      <artifactId>struts2-convention-plugin</artifactId>

      <version>2.5.33</version>

    </dependency>

    <dependency>

      <groupId>javax.servlet</groupId>

      <artifactId>javax.servlet-api</artifactId>

      <version>3.1.0</version>

    </dependency>

  </dependencies>

  <build>

    <plugins>

      <plugin>

        <groupId>org.apache.maven.plugins</groupId>

        <artifactId>maven-compiler-plugin</artifactId>

        <version>3.8.0</version>

        <configuration>

          <source>1.8</source>

          <target>1.8</target>

        </configuration>

      </plugin>

    </plugins>

  </build>

</project>