Struts2 Performance Testing
Important Note: The following results are obtained when HTTP monitor process is enabled on NetBeans. Disabling this monitor process substantially improves response times. I will update this post with revised metrics soon.
I recently did performance testing on the latest version of Struts2 framework (2.2.3.1). I wanted to see how many requests a simple Struts2 application can handle on a single Tomcat instance. I also wanted to check whether there are any major performance issues with Struts 2 framework.
The simple Struts 2 application I developed was hosted on Tomcat 7 server from the NetBeans IDE. I used JMeter on a separate machine to simulate the load. The performance test was done in two phases,
Load Testing (Phase 1) – Struts2 application was hosted on NetBeans IDE with Tomcat 7. JMeter was run on a separate machine and performance metrics were collected from JMeter and Windows 7 Performance Monitor. In this phase I wanted to see what is the maximum concurrent user load that could be applied without considerable degradation in response time.
Performance Profile (Phase 2) – Struts2 application was hosted on NetBeans IDE with Tomcat 7. NetBeans code profiler was attached to the Tomcat session. JMeter was run on a separate machine and performance metrics were collected from JMeter, Windows 7 Performance Monitor and NetBeans Profiler. In this phase I was looking for any obvious bottlenecks in the Struts2 framework.
Sample Struts2 Application For Performance Testing
The sample application was created using the Struts2 Maven blank archetype. This application contained a simple stub class to simulate data fetch and a simple JSP file with Struts2 custom tags to display the data.
- Click here to download the Struts2 Maven sample application with default interceptor stack
- Click here to download the Struts2 Maven sample application without interceptors (used in test 3)
Tools Used for Struts2 Performance Testing
Following Tools were used for performance testing and capturing various performance metrics,
- Windows 7 64 bit with JDK 1.6 64 bit
- NetBeans IDE 7.0.1
- NetBeans Profiler
- Apache JMeter 2.5.1
- Windows 7 Performance Monitor
- Struts2 Framework 2.2.3.1
Struts2 Performance Testing Setup
My Struts2 performance testing setup consisted of the following rig,
- Network - Intel Gigabit controllers on 100Mbps LAN
- Tomcat Server Machine – Intel I5 2500K, 16GB RAM, Windows 7 – 64 bit
- JMeter Test Machine – Intel Quad Core Q9300, 4GB RAM, Windows 7 – 32 bit
Struts2 Performance Testing Results (Phase I)
Test 1 – 500 concurrent users – A load of 500 concurrent users with 100 iterations was applied using JMeter. The ramp up period was 1 second (delay between starting each user). The following diagram shows the response times at this load,

The average response time at a load of 500 concurrent users is around 1 second. The maximum response time observed is 3 seconds. The following diagram shows the performance metrics obtained from the Windows 7 machine running the application,

The average CPU time is 59%. There is plenty of CPU time available even at 500 concurrent users.
Test 2 – 2000 concurrent users – A load of 2000 concurrent users with 25 iterations was applied using JMeter. The ramp up time was 1 second. The following diagram shows the response times at this load,

The average response time for 2000 concurrent users is under 2 seconds. However some of the requests took about 9 seconds to complete. There are no errors even at this high load. The network utilization of the 100Mbps network is shown below,

The following diagram shows the performance metrics obtained from the Windows 7 machine running the tomcat server,

The average CPU time is over 92%. This means that above this load, there will be substantial reduction in performance. To handle more load there are two options,
- Upgrade the machine (better CPU, multiple CPUs etc.)
- Run multiple Tomcat instances with a load balancer in front
Struts2 Profiling Results (Phase II)
I used NetBeans profiler to check the hotspots in Struts2 framework code. The profiler was setup to profile only application code and Struts2 framework code.
A load of 250 concurrent users with 10 iterations was applied with a ramp up time of 1 second. The response times recorded was much higher due to netbeans profiler overhead. The following diagram from NetBeans profiler shows the most costly methods in terms of CPU time.

Let us analyze some of the methods in the above list and see whether any optimizations are possible.
The first method is the iterator in the JSP for displaying the table. Note that this is the time taken for the iterator alone and doesn’t include the time taken for individual property tags.
The prepare() method in Dispatcher is the second costly method. This method manages the locale and encoding of request/response. Optimization is probably possible in this method.
The isActive() method on UtilTimerStack check whether Xwork profiling is turned on. The back trace for this method shows useful information,

This shows that we have a lot interceptors being called in our application. This are interceptors are part of the default interceptor stack inherited via "struts-default" package. We basically need to create a custom interceptor stack for our application which removes all the unused interceptors.
The doExecute() timing seems to be time taken for writing the response to the client. Most of the time in this is taken by Tomcat classes.
The ONGL seems to be another time hog. Methods such as get(), getValue() and convertValue() which operates on the custom tags is costly.
Finally AnnotationValidationInterceptor is causing the invocation of another costly method isAnnotatedBy().
From the analysis it appears unused interceptors and OGNL are the main areas which can cause performance problems in a simple Struts 2 application under high load.
Conclusion
There are no major performance issues or bottlenecks in Struts2 . A properly designed Struts2 application can handle thousands of concurrent users on a single Tomcat instance. To optimize Struts2 performance, I recommend using a custom interceptor stack with a selected set of interceptors that your application needs.
Struts2 Tiles Integration
Introduction
For any Web application with a sizeable number of application screens it is essential to have a design which promotes page reuse and screen composition flexibility. There are two common patterns used for maximizing reuse when similar application screens are built; Decorator pattern and Composite view pattern. Apache Tiles is a composite view pattern framework for Java web applications. This is a step by step tutorial on integrating Apache Tiles framework in a Struts 2 application. Struts 2 simplifies the adoption of Tiles framework by providing a plugin for integration.
I use the following tools for this tutorial,
- Oracle Java JDK 1.6
- Apache Struts 2.2.3.1
- Apache Tiles 2.0.6
- Struts 2 Tiles Plugin 2.2.3.1
- Eclipse or NetBeans with Maven 3
Apache Tiles Features – Quick Introduction To Tiles
Let us say a Web application requires a number of application pages which requires same header data. The traditional way of avoiding duplication of header content is to use JSP includes in all the pages. This promotes reuse of the same header page in all the screens. In order to change header content, you just need to edit one file. However there is one major disadvantage to this. If you want to change the layout of your application, you will have to change all the pages you have created for your application!
This is where Apache Tiles comes for our rescue. Tiles can extract the layout information and then individual pages can decide what layout they want to use. This way layout change will be limited to changes in a single layout file. See the following Struts 2 Tiles sample application to learn how Tiles can compose a screen from individual pages and a layout file. Check out Tiles tutorial to learn more about Apache Tiles.
Apache Tiles can be used in complex page composition use cases by using some of its key features,
- Page definitions can be nested or can inherit from other page definitions
- It is possible to create tiles page definitions at compile time or at runtime
- View prepares enables preparation of data before rendering page definitions
Creating a Struts 2 Tiles Application
Create a simple Struts 2 application using Maven archetypes. Follow the Struts 2 Maven Eclipse tutorial or Struts 2 Maven NetBeans tutorial to setup a Struts 2 project using Maven. Delete all the files generated except web.xml, struts.xml and pom.xml from the project. Add the Struts 2 Tiles plugin as a project dependency by appending the following entry to the dependencies section of pom.xml in your project.
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-tiles-plugin</artifactId>
<version>2.2.3.1</version>
<scope>compile</scope>
</dependency>
Note that Struts 2 Tiles Plugin 2.2.3.1 project has a dependency with Tiles 2.0.6 (automatically downloaded by Maven). If you want to use latest Tiles jars (2.2.2), you can manually add the dependency in pom.xml and exclude the 2.0.6 dependencies from Struts 2 Tiles Plugin. Alternatively you can manually setup the project instead of using Maven.
Add the Struts2TilesListener as an event listener by adding the following lines to web.xml.
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
Our application requirement is to create 3 application screens all of which will have the same layout. The only thing that will vary between the screens is the body area. Tiles is an ideal choice to develop a common template for these screens.

First create a file named tiles.xml under WEB-INF folder (the folder where web.xml is located). By default this is where Tiles will look for its configuration file. We will add an abstract screen definition and then extend the definition to create 3 page definitions corresponding to the above screens. In each screen definition we will override the body section by passing the name of the JSP file which contains the content of that screen.
<?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="struts2tiles.mainLayout" template="/templates/mainlayout.jsp">
<put-attribute name="header" value="/common/header.jsp"/>
<put-attribute name="body" value=""/>
<put-attribute name="footer" value="/common/footer.jsp"/>
</definition>
<definition name="struts2tiles.home" extends="struts2tiles.mainLayout">
<put-attribute name="body" value="/pages/home.jsp"/>
</definition>
<definition name="struts2tiles.page1" extends="struts2tiles.mainLayout">
<put-attribute name="body" value="/pages/page1.jsp"/>
</definition>
<definition name="struts2tiles.page2" extends="struts2tiles.mainLayout">
<put-attribute name="body" value="/pages/page2.jsp"/>
</definition>
</tiles-definitions>
First let us create the template file (mainlayout.jsp). This uses Tiles tags to compose the screen from various attributes passed to the template via page definitions.
<%@ 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>
<table border="1" cellpadding="2" cellspacing="2" align="center">
<tr style="background-color: #66f;">
<td>
<tiles:insertAttribute name="header" />
</td>
</tr>
<tr style="background-color: #aaa;">
<td width="350">
<tiles:insertAttribute name="body" />
</td>
</tr>
<tr style="background-color: #f66;">
<td >
<tiles:insertAttribute name="footer" />
</td>
</tr>
</table>
</body>
</html>
Let us now create the common jsps (header.jsp and footer.jsp).
<h1>Header</h1>
<h1>Footer</h1>
Let us create the individual page content (home.jsp, page1.jsp and page2.jsp). These contain dummy data to test our implementation.
<h1>Home</h1>
<h1>Page 1</h1>
<h1>Page 2</h1>
Update the struts.xml with the following content.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false"/>
<constant name="struts.devMode" value="true"/>
<package name="default" extends="struts-default">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
</result-types>
<action name="Home" class="org.struts2.struts2tiles.Home">
<result name="success" type="tiles">struts2tiles.home</result>
</action>
<action name="Page1" class="org.struts2.struts2tiles.Page1">
<result name="success" type="tiles">struts2tiles.page1</result>
</action>
<action name="Page2" class="org.struts2.struts2tiles.Page2">
<result name="success" type="tiles">struts2tiles.page2</result>
</action>
</package>
</struts>
Note that the result type "tiles" is defined as a the TilesResult class. So whenever Struts encounters a result of the type "tiles" it will invoke TilesResult. TilesResult will use the content of the result tag to find the corresponding page definition in tiles.xml! So in this example, Home action has a "success result" of type" tiles" and hence TilesResult will look for struts2tiles.home definition in tiles.xml.
Create all the action classes specified in struts.xml (Home, Page1 and Page2). These action classes are used to forward the request to various view pages (Tiles page definitions in this case).
package org.struts2.struts2tiles;
import com.opensymphony.xwork2.ActionSupport;
public class Home extends ActionSupport{
@Override
public String execute() {
return SUCCESS;
}
}
package org.struts2.struts2tiles;
import com.opensymphony.xwork2.ActionSupport;
public class Page1 extends ActionSupport {
@Override
public String execute() {
return SUCCESS;
}
}
package org.struts2.struts2tiles;
import com.opensymphony.xwork2.ActionSupport;
public class Page2 extends ActionSupport{
@Override
public String execute() {
return SUCCESS;
}
}
Run the project and access the various screens by invoking the following links if you are using NetBeans (Use port 8080 for Eclipse).
http://localhost:8084/Struts2Tiles-1.0-SNAPSHOT/Home.action
http://localhost:8084/Struts2Tiles-1.0-SNAPSHOT/Page1.action
http://localhost:8084/Struts2Tiles-1.0-SNAPSHOT/Page2.action
If you manually setup the Struts 2 Tiles application in your IDE(if you don’t like Maven for some reason!), ensure that you add the following jars in the lib folder,
asm-3.1.jar asm-commons-3.1.jar asm-tree-3.1.jar commons-beanutils-1.7.0.jar commons-digester-1.8.jar commons-fileupload-1.2.2.jar commons-io-2.0.1.jar commons-lang-2.5.jar commons-logging-1.1.1.jar commons-logging-api-1.1.jar freemarker-2.3.16.jar javassist-3.11.0.GA.jar ognl-3.0.1.jar struts2-config-browser-plugin-2.2.3.1.jar struts2-core-2.2.3.1.jar struts2-tiles-plugin-2.2.3.1.jar tiles-api-2.0.6.jar tiles-core-2.0.6.jar tiles-jsp-2.0.6.jar xwork-core-2.2.3.1.jar
Download Struts 2 Tiles Example
- Click here to download Struts 2 Tiles example source code (Struts 2 Maven Project) – Use this tutorial to setup the source code in NetBeans.
Developing Struts2 Applications Using Eclipse, M2Eclipse Plugin and Maven
In this step by step tutorial I will show you how Eclipse IDE, M2Eclipse Plugin and Maven can be used to develop Struts 2 Web applications. In order to create and run Struts 2 Maven projects in Eclipse, you need to download the following,
- Eclipse IDE – Eclipse Indigo 3.7.1 or higher for Java EE Developers
- M2Eclipse Plugin – Maven integration plugin from Eclipse repository
- M2E-WTP Connector – Connector plugin for tight integration between M2Eclipse plugin and Eclipse WTP
- Tomcat Server – Apache Tomcat 7 or above
Pre-requisites
Oracle JDK 6 is required in your machine. Also ensure that the environment variable JAVA_HOME points to your JDK installation. You can download JDK 6 from here.
Installing Eclipse IDE
Download Eclipse Indigo 3.7.1 or higher. Download Eclipse IDE for Java EE Developers (32 bit) zip file and extract the zip file to a folder of your choice.
Start Eclipse IDE and configure the Java JDK as the default JRE as shown below (Preferences => Java => Installed JREs). Note that JDK 6 is selected as the default JRE.

Installing M2Eclipse Plugin
M2Eclipse plugin enables Maven build tool integration in Eclipse. Maven is a build and project management tool and can substantially simplify dependency management and project creation. Using Maven, it is possible to create a Struts 2 application compatible with a specific version of Struts 2 without any manual intervention.
M2Eclipse plugin is now part of Eclipse project and is packaged in Eclipse IDE for Java Developers. However it is not included in Eclipse IDE for Java EE Developers. Hence you need to manually install it from Eclipse IDE. Also note that current version of M2Eclipse contains embedded Maven 3 (Maven 3.0.2) and hence there is no need to download Maven separately (However if you want to use a later version you can configure external Maven installation).
From Eclipse IDE, Click on "Help" => "Install New Software". Click on Add to add the M2Eclipse Plugin repository as shown below. The M2Eclipse plugin URL is – http://download.eclipse.org/technology/m2e/releases.

Click on OK. Select "Maven Integration for Eclipse" as shown below and click on Next to complete plugin installation. Restart Eclipse after installation.

After restart, Eclipse preferences will have a new section for Maven as shown below,

Maven – A Quick Introduction
Maven is a project management/build manager tool for Java projects. Using Maven you can capture library dependencies and other project properties in a file named pom.xml. POM stands for Project Object Model and it contains project dependencies, various project build phases and repository information for the project and its dependencies. For building large solutions containing multiple Java and Web projects, Maven is an indispensable tool.
Another major concept in Maven is the idea of archetypes. Archetypes represents a model or a template for a project. For example, there is an archetype available for Struts2 in Maven (created by Struts 2 team and published to Maven repository). Using this archetype we can build a sample Struts2 project without manually copying dependent jar files or creating configuration files. The created Struts2 project will also contain a well defined pom.xml using which we can compile the Struts2 application or run it on the application server.
Configuring Maven in Eclipse
By default, Maven sets up two repositories for all the artifacts. The local repository and the remote maven repository. You can view the contents of these by accessing Window => Show View => Other => Maven => Maven Repositories from Eclipse.

Initially local repository is blank and when Maven downloads dependent jars and archetypes from remote repositories, it caches them in local repository.
The central Maven repository index can be updated by right clicking the central and selecting "Update Index". This might take a while depending on your internet connection. Once the index is updated, ideally you should be able to select one of the Struts 2 archetypes in Eclipse "New Project" to create a Struts application. However I could never get this to work. "New Project" did list a large number of archetypes from remote, but for some reason refused to show Struts 2 archetypes.
So I recommend the following work around in which we will download the central Maven archetype catalog locally and would configure it as a local catalog.
Download central Maven archetype catalog file (http://repo1.maven.org/maven2/archetype-catalog.xml) to a local folder in your system. From Eclipse go to Preferences => Maven => Archetypes and click on "Add Local Catalog". Enter the location of the catalog file downloaded in the previous step,

Click OK. We have now configured a local Maven catalog which contains details about Struts 2 archetypes. Note that if there is a future release of a newer Struts 2 version, you will need to download the updated catalog and repeat the above procedure. In the next step we will see how this catalog can be used to create a Struts 2 Maven project.
Creating a Struts 2 Application in Eclipse
From Eclipse, click on File => New Project =>Maven => Maven Project as shown below.

Click on Next and then in the next screen, click Next again. From the catalog field select the local Maven archetype catalog created earlier. Type in struts2 in the filter field to see available Struts 2 archetypes. Select Struts 2 blank archetype with version 2.2.3.1 as shown below,

Click on Next. Enter your project details as shown below. Group id represents a group id for a set of projects. Artifact id is the unique id for your project. In version number, SNAPSHOT indicates that the project is in development. The package field contains the root java package of the project.

Click on Finish to create a Struts 2 Maven Project.
The pom.xml in the project will show errors since there is a bug in the Struts 2 archetype for Struts 2.2.3.1. To correct this you need to change the version number variable names in pom.xml to actual version numbers. Change ${project.version} to 1.0-SNAPSHOT and ${struts2.version} to 2.2.3.1 (there is also a bug of using ${project.version} instead of ${struts2.version} under properties tag). The corrected pom.xml is given below,
<?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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.struts2</groupId> <artifactId>tutorial</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>Struts 2 Blank Webapp</name> <properties> <struts2.version>2.2.3.1</struts2.version> </properties> <dependencies> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.2.3.1</version> <exclusions> <exclusion> <artifactId>tools</artifactId> <groupId>com.sun</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-config-browser-plugin</artifactId> <version>2.2.3.1</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-junit-plugin</artifactId> <version>2.2.3.1</version> <scope>test</scope> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.5</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-mock</artifactId> <version>2.0.8</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>2.5</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>2.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.21</version> <configuration> <scanIntervalSeconds>10</scanIntervalSeconds> <scanTargets> <scanTarget>src/main/webapp/WEB-INF</scanTarget> <scanTarget>src/main/webapp/WEB-INF/web.xml</scanTarget> <scanTarget>src/main/resources/struts.xml</scanTarget> <scanTarget>src/main/resources/example.xml</scanTarget> </scanTargets> </configuration> </plugin> </plugins> </build> </project>
Now you will get another error – "Missing artifact com.sun:tools:jar:1.5.0". This is due to a dependency on the struts2-core artifact. You can fix the problem by replacing the dependency section of struts2-core in pom.xml with the following,
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.2.3.1</version> <exclusions> <exclusion> <artifactId>tools</artifactId> <groupId>com.sun</groupId> </exclusion> </exclusions> </dependency>
Lastly you will see an error that project configuration is not up-to-date with pom.xml. Fix this by right clicking the project and selecting Maven => Update Project Configuration. This will download all the dependent jars from remote machine via local repository cache and will also build the project. If this is the first time you are using Maven, it will take a while to download everything. Obviously your machine needs to have an active internet connection.
Now you can build your Struts 2 Maven project by right clicking the project and selecting Run As => Maven build.
However what we would like to do is to be able to integrate Maven with Eclipse WTP so that we can directly build and run the project on Tomcat or JBoss server. You need M2E-WTP connector for this.
Installing M2E-WTP Connector for WTP Support
From Eclipse IDE, select Preferences => Maven => Discovery. Click on Open Catalog button. Select the M2e-WTP connector from the following screen,

Click on Finish. In the next screen select Maven Integration for WTP and click on Next and Finish. Restart Eclipse. Now Maven and Eclipse WTP integration is complete. This enables dynamic web facet for Struts 2 maven project. In order to run our Struts 2 application, we need to install and configure Tomcat in Eclipse.
Installing and Configuring Tomcat 7 Server on Eclipse
Download Tomcat 7 zip file and extract it to a folder of your choice. From Eclipse, select Window => Show View => Other => Server => Servers. Right click on Servers window and select New => Server.

Select Tomcat 7 from Apache folder as shown below.

Click on Next. Enter the location of the Tomcat folder and then choose JRE as the JDK installed in Eclipse.

Click on Finish to create Tomcat 7 server configuration in Eclipse.
Running Struts 2 Application in Eclipse
From Eclipse, right click on the Struts 2 Maven project and select Run As => Run on Server. Select Tomcat 7 server in the next screen and voila! your first Struts 2 application is up and running on Tomcat 7. Oh Boy! it was a long journey to get here.

Adding Additional Libraries to Struts 2 Application
If you need additional libraries in your Struts 2 application, you need to add the dependency in pom.xml. Maven will automatically download the jar and will package it as part of the war file created.
How to Run Struts 2 Maven Projects in NetBeans
In an earlier tutorial I covered how Struts 2 projects can be created using Maven. In this tutorial I will show you how you can run Struts 2 Maven projects in NetBeans IDE. For this tutorial, I will be using Maven 3, Struts 2 2.2.3.1 and NetBeans 7.0.1.
Pre-requisites
This tutorial requires Oracle JDK 1.6 and NetBeans 7 installed in your machine. Check out NetBeans installation guide for details on installing NetBeans.
How to Import an Existing Struts 2 Maven Project in NetBeans
NetBeans can automatically recognize a Maven project. From NetBeans 7 onwards complete integrated support for Maven 3 is provided. Maven 3 is also bundled along with NetBeans 7 and if you already installed Maven 3 in your system, you have 2 instances of Maven 3. However both point to the same local repository.
From NetBeans click on File => Open Project. Navigate to the folder which contains your Struts 2 Maven Project. See this article if you don’t know how to create a Struts 2 Maven project from command line. NetBeans will automatically identify the "tutorial" project as shown below. Select tutorial project and click on open project. Note that the name of the project is automatically taken from the name tag in pom.xml.

The project will be imported as NetBeans project. Click on the Run icon in NetBeans. Select the Tomcat server as the default server for the project as shown below,

This will run the imported Maven Struts 2 project on the configured Tomcat server. The context path for the web application is of the form <artifactid-version number> and hence invoke the following URL for accessing the Welcome.action in the sample project,
http://localhost:8084/tutorial-1.0/example/Welcome.action
NetBeans provides automatic binding between IDE actions and various Maven goals. You can view the default binding by right clicking the project and selecting Properties => Actions. The following screenshot shows that when you select “Build Project” from NetBeans IDE, Maven’s install goal is executed.

The default settings for Run Project is to invoke the "package" goal and then leave the deployment to NetBeans IDE (netbeans.deploy=true property indicates this to the IDE). You can override this behavior so that when you invoke “Run Project”, the jetty:run goal is called. Change the goal from "package" to "jetty:run" and then remove the attribute “netbeans.deploy=true” as shown below,

Now Run the Project. The application will be hosted on Jetty server and can be accessed from the following URL,
http://localhost:8080/tutorial/example/Welcome.action
How to Create a Struts 2 Maven Project in NetBeans
Since NetBeans has built in support for Maven 3, it is easy to create a Struts 2 Maven application. This is also the preferred way of creating a new Struts 2 application in NetBeans.
From the NetBeans IDE click on New Project. From the New Project window, Select Maven/Project from archetype as shown below,

Click on next. You will be provided with an option to select a Maven archetype from local or remote repositories. If you have already run a Struts 2 Maven archetype from the command line, you will see the archetype under local repository. Otherwise you will need to find Struts 2 archetype from the remote repository and add it to local repository.

If you cannot find the Struts 2 blank archetype from the above screen, cancel new project wizard and go to Window => Other => Maven Repository Browser => Right click on Central => Update Index in NetBeans IDE.

Depending on your internet connection, this might take while, but is a one time process. The Struts 2 archetypes are available under org.apache.struts folder in the repository. Expand this folder to the struts2-archetype-blank and then right click the version you want and click on download. This will download the archetype to your local repository.

After downloading the Struts 2 archetype to local repository, return to New Project wizard. In the second page of the wizard, select the Strut 2 blank archetype from local repository,

In the next page enter the name of the project, group id, version number and optionally the main package of your project. In Maven, versions which are still under development will have the suffix of SNAPSHOT.

Click on finish to create the Struts 2 Maven project. Some of the Struts 2 Maven archetypes in repository have bugs and as of writing this article, version 2.2.3.1 also has bugs. This means that by default, you will see the project as "misconfigured Maven project in tutorial" in NetBeans.
The solution is to open the pom.xml under Project Files and then modify the ${project.version} to 1.0-SNAPSHOT and ${struts2.version} to 2.2.3.1. If you are using 2.2.3.1 version of Struts2, you can replace pom.xml with the following file,
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.struts2</groupId>
<artifactId>tutorial</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>Struts 2 Blank Webapp</name>
<properties>
<struts2.version>2.2.3.1</struts2.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.2.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>2.2.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>2.2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>2.0.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.21</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<scanTargets>
<scanTarget>src/main/webapp/WEB-INF</scanTarget>
<scanTarget>src/main/webapp/WEB-INF/web.xml</scanTarget>
<scanTarget>src/main/resources/struts.xml</scanTarget>
<scanTarget>src/main/resources/example.xml</scanTarget>
</scanTargets>
</configuration>
</plugin>
</plugins>
</build>
</project>
Now you can Run your Struts 2 application on NetBeans Tomcat by pressing F6!
Developing Struts2 Applications Using Maven 3
Introduction to Maven
Maven is a project management/build manager tool for Java projects. Using Maven you can capture library dependencies and other project properties in a file named pom.xml. POM stands for Project Object Model and it contains project dependencies, various project build phases and repository information for the project and its dependencies. For building large solutions containing multiple Java and Web projects, Maven is an indispensable tool.
Another major concept in Maven is the idea of archetypes. Archetypes represents a model or a template for a project. For example, there is a archetype available for Struts2 in Maven. Using this archetype we can build a sample Struts2 project without manually copying dependent jar files or creating configuration files. The created Struts2 project will also contain a well defined pom.xml using which we can compile the Struts2 application or run it on the Jetty Java application server. The various steps involved in Maven based Struts2 development are,
- Build a sample Struts 2 application using Maven archetype,
- Maven downloads the archetype definition and related libraries from centralized maven repository hosted online
- Maven creates a sample Struts 2 application containing various dependent jar files and creates a default pom.xml for the project
- Compile and run Struts 2 application using Maven,
- Maven reads the pom.xml in the project and builds the Struts 2 project
- Maven starts the Jetty servlet container and deploys the Struts 2 project
Check out the following step by step tutorial on developing Struts 2 applications using Maven 3. This example assumes that you are working on a Windows machine. The steps are same if you use Maven 2.
Pre-requisites
For running Maven and Struts 2 applications Java SDK is required. I recommend you download and install Oracle JDK 6 from here.
Step 1 : Download and Install Maven 3 Tool
Download the Maven binary zip file from the Maven download page. For this tutorial, I used apache-maven-3.0.3-bin.zip. Extract the zip file to a folder of your choice. Add the bin folder of the extracted file in the PATH environment variable of Windows. This ensures that you can access Maven from any folder.
I extracted Maven zip file to the folder W:\programming-final\tools. Added the path to the bin folder (W:\programming-final\tools\apache-maven-3.0.3\bin) to the Windows PATH environment variable. You can set the PATH variable in Windows 7 from Control Panel => System => Advanced System Settings => Environment Variables => Create a new user variable. Add the PATH variable as shown below,

You also need to set the JAVA_HOME environment variable in a similar manner if it is not already set. In my case JAVA_HOME points to
Now open a command prompt and check the correct installation of Maven by running the following command,
mvn -v

Step 2 : Create a Sample Struts 2 Application Using Maven 3
Before you proceed further, ensure that you have an active internet connection. This is required since Maven will be downloading Struts2 archetype files and Struts2 jars directly from the online Maven repository.
Struts 2 project provides more than one Maven archetype for creating a sample Struts 2 application. These are,
- The Blank Archetype – Use this to create a simple Struts 2 application built using XML configuration files. It is a complete example.
- The Starter Archetype – This is more advanced than the blank type and contains sitemesh and spring integration. It also demonstrates validation, conversion and resource bundles.
- The Portlet Blank Archetype – Use this if you want a JSR 168 portlet based Struts 2 application.
- The Portlet Database Archetype – This shows how to build a portlet application with database support
- The Blank Convention Archetype – This is same as blank archetype, but uses convention based approach than XML files for configuration.
- The Plugin Archetype – This archetype can be used to create a Struts 2 plugin.
We will use the blank archetype for this tutorial. Run the following command to create a simple Struts 2 application using Maven. Note that I am using "tutorial" as the group id and the artifact id of the new project. You can change it to your application name.
mvn archetype:generate -B -DgroupId=tutorial -DartifactId=tutorial -DarchetypeGroupId=org.apache.struts -DarchetypeArtifactId=struts2-archetype-blank -DarchetypeVersion=2.2.3.1
Sit back and relax, it might take a while to download and install everything. Note that for this tutorial I use Struts2 version 2.2.3.1. You might want to use the latest production release for your project.
All the jars and artifacts downloaded are cached in your machine. This means that from next time onwards, maven will use the local cached version instead of the online repository. The default location of the repository in a Windows machine is C:\Users\<your user name>\.m2\repository. Check out this folder to see what Maven has downloaded and cached during the archetype build.
Once the archetype command is finished, you will see a new project "tutorial" created under the current folder,

Note that in a Maven project, non Java files are kept in a separate resources folder. For example, in the tutorial application, struts.xml is now under resources folder instead of the src folder.
Step 3 : Verify and Edit Generated pom.xml
It seems there are bugs with some of the archetypes for Struts 2. When I used the 2.2.3.1 archetype, the variables ${project.version} and ${struts2.version} was not replaced with their actual values in pom.xml. I had to manually change them in pom.xml as 1.0 and 2.2.3.1 respectively. The updated pom.xml for Struts 2.2.3.1 blank application is given below,
<?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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tutorial</groupId>
<artifactId>tutorial</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>Struts 2 Blank Webapp</name>
<properties>
<struts2.version>2.2.3.1</struts2.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.2.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>2.2.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-junit-plugin</artifactId>
<version>2.2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>2.0.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.21</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<scanTargets>
<scanTarget>src/main/webapp/WEB-INF</scanTarget>
<scanTarget>src/main/webapp/WEB-
INF/web.xml</scanTarget>
<scanTarget>src/main/resources/struts.xml</scanTarget>
<scanTarget>src/main/resources/example.xml</scanTarget>
</scanTargets>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 4 : Build and Run Sample Struts 2 Application Using Maven 3
Change the current directory of the command prompt to the tutorial folder. This is required since the following Maven commands can be run only from the folder which contains the pom.xml. Compile the sample Struts 2 application,
mvn compile
To run the unit test cases, run the following command,
mvn test
To deploy and run the sample web application on Jetty web application server, run the following command,
mvn jetty:run
Test your sample application by accessing the following URL. Please ensure that no other application (for example, tomcat) is listening on port 8080,
http://localhost:8080/tutorial/example/Welcome.action

You might see an error in Jetty – "Could not find action or result – /tutorial/css/examplecss". This is due to a typo in the blank application (another bug in Maven archetype). You can correct it by adding the missing dot in \tutorial\src\main\webapp\example\Welcome.jsp.
When you work on any large scale projects, the command line use soon becomes cumbersome. It is also possible to install and use Maven 3 in Eclipse IDE along with Tomcat or JBoss AS. I will cover that in the next article.
Struts2 Upload File Example
Introduction to Struts2 File Upload
Struts2 has built in features for uploading a file to a server using multipart servlet request (known as form based file upload defined in RFC 1867). Struts2 provides a specific interceptor (file upload interceptor) for handling file uploads. This interceptor will provide an instance of the uploaded File object to a configured Struts2 action class. File upload interceptor is part of the core Struts2 library and hence you don’t need any additional plugins for simple file upload. In this article, I will provide a step by step example of implementing file upload in Struts2.
Pre-requisites for Struts2 File Upload Sample Application
The following example assumes that you have the IDE and a sample Struts2 application already setup. Please see this article for setting up a sample Struts2 application using NetBeans and Tomcat.
Struts2 File Upload Example Application Explained
The following sample application will demonstrate how file uploads can be implemented using built-in features of Struts2. Struts2 internally uses apache commons libraries (file upload and io) for implementing the low level aspects of file upload and hence you need to have these libraries as part of your Struts2 application.
The following application provides a file upload form using which you can upload a local file to the server. Struts2 internally stores this file as a temporary file and we will copy this file into another file for further processing. Finally the application will show the details of the uploaded file including its name and the size of the file. The application also demonstrates various configuration options for the file upload and also how to handle various error messages generated by the file upload component.
Struts2 File Upload example application has the following components,
- uploadform.jsp – A screen for selecting and uploading a file
- ShowUploadForm.java – A Struts2 action for displaying the file upload screen
- UploadMyFile.java – Another Struts2 action class for processing the uploaded file and writing it into server’s file system
- uploadresults.jsp – A screen which will display the details of the file just uploaded
- web.xml – Web application deployment descriptor where Struts2 framework is configured
- struts.xml – Struts configuration file where action class to URL mapping and view mapping is defined
- global.properties – i18n message resource file for overriding default error messages generated by file upload
File Upload Input Form (uploadform.jsp)
Let us first create a JSP file for upload file selection. Create a new JSP file fileupload.jsp file in the Web Pages folder of your NetBeans project. Replace the content of the JSP with the following,
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Struts2 File Upload Example</title></head>
<body>
<s:actionerror/>
<s:fielderror/>
<s:form action="UploadMyFile" enctype="multipart/form-data" method="POST">
<s:file name="uploadFile" label="Please select a file to upload"></s:file>
<s:submit></s:submit>
</s:form>
</body>
</html>
To create an upload form, Struts2 provides a custom tag <s:file>. This tag requires a label for the upload file field and a name which we will be using in the action class for processing the file. In order to upload a file, the servlet specification requires that the encoding of the form is of multipart type. This can be specified in the enctype attribute of the custom tag <s:form>. The action attribute of the <s:form> specifies the name of the action class to be invoked (UploadMyFile) when user submits this page.
Also note the use of custom tags <s:actionerrors/> and <s:fielderror/>. These can be used to display field specific or action specific error messages. All the interceptor level validations (maximumSize) generate both action errors and field errors. However global validations such as the size validation (struts.multipart.maxSize) only generates action errors. See the error message section below for more details.
Controller to Display File Upload Input Form (ShowUploadForm.java)
package org.struts2.samples.upload;
import com.opensymphony.xwork2.ActionSupport;
public class ShowUploadForm extends ActionSupport{
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
This action class (defined under the package org.struts2.samples.upload) simply returns a value of SUCCESS which is mapped to fileupload.jsp in struts.xml. This is the first action class invoked in the application and the URL used in the sample application in NetBeans is – http://localhost:8084/Struts2FileUpload/upload/ShowUploadForm.action
Controller to Process Uploaded File and Display Upload Details Page (UploadMyFile.java)
Define the class UploadMyFile in package org.struts2.samples.upload.
package org.struts2.samples.upload;
import com.opensymphony.xwork2.ActionSupport;
import java.io.File;
import org.apache.commons.io.FileUtils;
public class UploadMyFile extends ActionSupport{
private File uploadFile;
private String uploadFileFileName;
private long fileSize;
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public String getUploadFileFileName() {
return uploadFileFileName;
}
public void setUploadFileFileName(String uploadFileFileName) {
this.uploadFileFileName = uploadFileFileName;
}
public File getUploadFile() {
return uploadFile;
}
public void setUploadFile(File uploadFile) {
this.uploadFile = uploadFile;
}
@Override
public String execute() throws Exception {
this.fileSize = uploadFile.length();
// write file to local file system or to database as blob
String filePath = "c:/temp/testfile99";
File newFile = new File(filePath);
FileUtils.copyFile(uploadFile, newFile);
return SUCCESS;
}
}
Struts2 interceptor injects a file object into the class variable uploadFile using the setter method setUploadFile(). Note that the name of the field in fileupload.jsp, uploadFile is used to find the setter in the action class. Struts2 interceptor can automatically invoke the following methods (where X stands for the name of the "file" field in the JSP),
- setX(File file) – The file object containing the uploaded file contents
- setXContentType(String contentType) – The mime type of the uploaded file
- setXFileName(String fileName) – The actual name of the file uploaded
In our example, we have defined setUploadFileFileName() and this will automatically set the file name in the action class. We will be using this to display the file name in the results JSP.
In the execute() method, we also find the size of the file and set it to another instance variable. We also create a permanent copy of the uploaded temporary file. Finally we forward to the results page by returning SUCCESS value.
Display Upload Details (uploadresults.jsp)
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Struts2 File Upload Example</title></head>
<body>
<h1>The uploaded file name is :<s:property value="uploadFileFileName"/>
and the size of the file is : <s:property value="fileSize"/> bytes</h1>
</body>
</html>
We use the custom tag <s:property> to display the file name and size.
Configure Struts2 in Web Application (web.xml)
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd"
version="3.0">
<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>
We configure Struts2 filter for initializing the Struts2 framework.
Connect Everything Together (struts.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.custom.i18n.resources" value="global" />
<constant name="struts.multipart.saveDir" value="c:/temp" />
<constant name="struts.multipart.maxSize" value="2000000" />
<package name="upload" extends="struts-default">
<action name="ShowUploadForm" class="org.struts2.samples.upload.ShowUploadForm">
<result name="success">/uploadform.jsp</result>
</action>
<action name="UploadMyFile" class="org.struts2.samples.upload.UploadMyFile">
<interceptor-ref name="defaultStack">
<param name="fileUpload.allowedTypes">text/plain</param>
<param name="fileUpload.maximumSize">50000</param>
</interceptor-ref>
<result name="input">/uploadform.jsp</result>
<result name="success">/uploadresults.jsp</result>
</action>
</package>
</struts>
First we define a number of constant configuration attributes,
- struts.custom.i18n.resources defines a custom global i18n resources file (global.properties)
- struts.multipart.saveDir overrides the temporary file location for file upload
- struts.multipart.maxSize sets a global limit for the maximum size of the file upload. This only generates action errors and the message cannot be overridden using the property struts.messages.error.file.too.large.
Now we do the standard wiring of action classes and view files. In the case of UploadMyFile, we also define a result with name "input". This view will be invoked when errors are encountered by Struts2. In our case we take user back to the upload form and display all the action errors and field errors using custom tags.
In the case of UploadMyFile, we also override the default parameters for file upload through file upload interceptor configuration. Since our package upload extends struts-default, defaultStack is already configured. We override the defaultStack with a customized defaultStack which modifies parameters for file upload interceptor. We limit the file uploads to simple text files which are less than 50kb in size.
Override Default Error Messages (global.properties)
struts.messages.error.file.too.large=File is too large
We override the i18n property struts.messages.error.file.too.large to display a custom message when the size of the file exceeds what is specified in the maximumSize parameter to the file upload interceptor. Note that global.properties is defined as a custom global resource file in struts.xml shown above.
Configuring File Upload Behavior in Struts2
In Struts2, constant configuration values can be specified in struts.xml, web.xml or in struts.properties. The struts.properties are no longer recommended and it is retained only for backward-compatibility with WebWork. You can either configure the following values in struts.xml as <constant> tag or as <init-param> in the filter configuration in web.xml.
By default the temporary files generated during file upload is stored in a location specified by the javax.servlet.context.tempdir. In some systems where this may be pointed to a memory location and you may want to change it. The location of the temporary file can be changed by providing a value for the constant struts.multipart.saveDir.
It is also possible to set a maximum size of the file being uploaded across all upload forms in an application. This is basically configured to prevent people from uploading extremely large files and there by crashing the system. The maximum size of the file in bytes can be set using the constant struts.multipart.maxSize. It is also possible to set size limit for a specific upload action by providing the maximumSize parameter to the file upload interceptor.
It is also possible to have a custom multipart parser by overriding the struts.multipart.parser property. The default parser is jakarta and some of the other parsers available are pell and cos. These parsers require additional libraries.
Following examples show how upload properties can be configured in struts.xml or web.xml,
<struts>
<constant name="struts.multipart.saveDir" value="c:/temp" />
<constant name="struts.multipart.maxSize" value="2000000" />
....
</struts>
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>struts.multipart.maxSize</param-name>
<param-value>20000</param-value>
</init-param>
</filter>
It is also possible to apply the above attributes selectively to a specific upload action. This can be achieved by customizing the parameters passed to the file upload interceptor. The parameters supported are allowedTypes and maximumSize. The parameter allowedTypes specifies a list of comma separated content types which can be uploaded.
The allowed content types can also be controlled programmatically by looking at the content type made available via setXContentType() defined on the action class (see UploadMyFile.java).
Handling Error Messages
Struts2 defines two types of errors – field errors and action errors. Action errors are errors which are not specific to a field. Field errors are generated per field. Use the tag <s:actionerrors/> to display all the action errors in a bulleted list of non field specific errors. Use the tag <s:fielderror/> with value parameter to display errors for a specific field.
The file upload in Struts2 can generate action errors and field errors. If the errors are generated due to global constants such as struts.multipart.maxSize , Struts2 only populates action errors. But if errors are generated due to the configuration passed to the interceptor (maximumSize), both field errors and action errors are generated.
You can customize the error message displayed by customizing the following i18n message keys,
- struts.messages.error.uploading – A general error that occurs when the file could not be uploaded
- struts.messages.error.file.too.large - Occurs when the uploaded file is too large as specified by maximumSize.
- struts.messages.error.content.type.not.allowed - Occurs when the uploaded file does not match the expected content types specified
To override these keys, create a property file containing these keys in the folder where struts.xml is stored. Specify this file as the custom global message resource file by setting the struts.custom.i18n.resources constant in struts.xml.
Download Struts2 File Upload Example
Click here to download the complete Struts2 file upload sample project in NetBeans. Please note that to keep the download size small, Struts2 libraries are excluded from the zip file. You need to add them before you can run the sample application.
Developing Struts2 Applications Using NetBeans
Struts2 is a highly extensible and modular Java based MVC web application framework. It substantially reduces the effort and time required to build large enterprise web applications. Various Java development environments such as Eclipse, NetBeans etc. can be used to build web applications using Struts2. This article is a step by step guide on building Struts2 web applications using NetBeans. The article assumes that you are using a Windows machine, but the steps are similar in any platform.
Prerequisites
The following tools are required to start Struts2 development using NetBeans. Since new versions are always coming out, the versions mentioned may be different from the latest versions available for download. Usually this is not a problem since new versions are compatible with older code,
- NetBeans 7 or above (NetBeans download page : 150MB+) : Download the Java EE edition of NetBeans which contains Java SDK 6 for compiling Java code and Tomcat server/Glassfish server for running applications. When you download, there is a brief user survey which you may ignore and proceed to download.
- Struts2 binaries 2.2.3.1 or above (Struts2 download page : 75MB+) : Download the latest binary release of Struts2 which is above 2.2.3. Also ensure that you download the full distribution which contains all binaries, source code and documentation for Struts2. The newer Struts2 releases contain Javassist libraries and hence the following download is not required.
- Javassist binaries 3.7 or above (Javassist download page : 2MB+) : This is required if you are using Struts2 2.2.1 or above. If you don’t include this jar you will get runtime exception java.lang.ClassNotFoundException: javassist.ClassPool in Tomcat. However JBoss server is bundled with Javassist and hence it is not required in JBoss.
Step 1 : Install NetBeans
Double click on the installer to install NetBeans IDE. During installation select both Glassfish and Tomcat servers. Glassfish can be used when you want to try out EJB based projects. Also during installation you need to select location for NetBeans and location for Java SDK. I usually modify the location of NetBeans and retain the default for the location of Java SDK. If you have selected Glassfish and Tomcat, you can also configure the locations for them.

The installation takes about 2 minutes to complete. At the end of the installation, you have an option to provide anonymous usage data to NetBeans web site. I usually uncheck this for performance reasons.
Step 2 : Create a Struts2 Project in NetBeans
A Struts2 application is not much different from a J2EE web application. The only difference is that to build Struts2 applications you need to have additional jars in class path and also need to provide a number of configuration file.
Open NetBeans IDE by running netbeans.exe located inside the bin folder of NetBeans installation. Alternatively you can also invoke it from Windows application menu.
From NetBeans main menu, select File => New Project menu item. This opens up the project wizard as shown below. Select Java Web/Web Application from the wizard and then click next.

Give a name for your project and choose a location for storing all your projects. Based on your project name, NetBeans will create a subfolder under the location mentioned above. Click on next.
![]()
Select Tomcat as the server and click on finish.
![]()
Now you will have a sample web application named HelloWorld in NetBeans. We will modify this project to convert this into a Struts2 web application.
Step 3 : Developing and Configuring Struts2 Application
In step 2, we got a standard web application up and running. Now we will convert this into a Struts2 web application. In NetBeans, click on the "Files" view on top left window. Right click WEB-INF folder and then add lib folder under it.
Extract the Struts2 zip file downloaded in prerequisites to a temporary folder. Drag and drop the following files from lib subfolder in temporary folder to Libraries folder in NetBeans project. This is the minimum set of libraries required to create a Struts2 application.
- commons-fileupload-1.2.2.jar
- commons-io-2.0.1.jar
- commons-lang-2.5.jar
- freemarker-2.3.16.jar
- javassist-3.11.0.GA.jar (from Struts2 libraries or can be downloaded separately)
- struts2-core-2.2.3.1.jar
- xwork-core-2.2.3.1.jar
- ognl-3.0.1.jar
After the copy, "Files" view will look like the above screenshot on the right.
Now we need to configure Struts2 framework in our web application. This is done by adding the Struts2 as a filter in standard web application descriptor (web.xml). To add web.xml in NetBeans project, right click the project and click on "New" and then on "Other". From the wizard, select standard deployment descriptor as shown below and then click on "Next" and "Finish".

Replace the content in WEB-INF/web.xml with the following lines. This ensures that all requests received by the application is routed to a Struts2 controller,
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd"
version="3.0">
<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>
Now we will create a very simple HelloWorld program using MVC architecture of Struts2. Our application will print "Hello World" to the browser when user accesses a URL. In an MVC architecture, Model will be responsible for processing data, Controller for invoking appropriate model and view and View for display of the data to the end user.
Let us first create a Model class which will return the message "HelloWorld!". Create a class "HelloModel" in package "com.struts2.samples". This model object has a single business method getMessage() which will return the message to be displayed to the user. The contents of HelloModel.java is given below,
package org.struts2.samples;
/**
*
* @author jayson
*/
public class HelloModel {
public String getMessage() {
return "Hello World!";
}
}
Now let us create the controller class which would process the user request, get the data from the model object and then decide which view needs to be shown to the user. Create a class "HelloWorld" in package "com.struts2.samples". Controller classes in Struts2 is known as action classes and they usually extend from ActionSupport class. The contents of HellWorld.java is given below,
package org.struts2.samples;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorld extends ActionSupport {
private String message;
@Override
public String execute() throws Exception {
HelloModel model = new HelloModel();
message = model.getMessage();
return SUCCESS;
}
/**
* @return the message
*/
public String getMessage() {
return message;
}
/**
* @param message the message to set
*/
public void setMessage(String message) {
this.message = message;
}
}
HelloWorld extends the execute() method in ActionSupport. This method is automatically called when a URL request is configured to be forwarded to an action class (see struts.xml below). First we invoke the model object and then set the returned message in a member in HelloWorld. We then forward the user to a view pointed to by the value SUCCESS (see struts.xml below). The members in the action class can be directly referred in the view class using Struts2 custom tags.
Let us now create a simple view using JSP rendering. Create or modify index.jsp inside the Web Pages folder of the NetBeans project. The contents of index.jsp is given below,
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title><s:property value="message"/></title>
</head>
<body>
<h1><s:property value="message"/></h1>
</body>
</html>
Note the use of Struts2 custom tags. Using the taglib directive we register struts-tags under the namespace prefix s. We can then use various Struts2 custom tags in JSP. The property tag enables easy access to the variables on the top of the OGNL stack made available by Struts2 in JSP. In this case top of the stack corresponds to the action class controller which invoked this JSP. Internally Struts calls getMessage() method of the action class when the property custom tag with value "message" is encountered.
Finally to glue all the components together, create struts.xml under Source Packages in the project. This defined how a URL is mapped to an action class invocation and how the return values in action classes are mapped to view components.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="sample" extends="struts-default">
<action name="HelloWorld" class="org.struts2.samples.HelloWorld">
<result name="success">/index.jsp</result>
</action>
</package>
</struts>
Note how the action name "HelloWorld" is mapped to the actual class using the action tag in XML. Also note how the success value is mapped to the view component "index.jsp". Since the action is organized under a package named "sample", the URL for accessing the action is http://[server:port]/[application context]/sample/HelloWorld.action. The actual URL since you are developing locally would be http://localhost:8084/HelloWorld/sample/HelloWorld.action
Step 4 : Running Struts2 Application in NetBeans
To run the sample application, click on the Run menu in NetBeans. This will compile the project and would deploy the application to Tomcat and then will open default application URL in the browser. Change the URL to point to your HelloWorld action class – http://localhost:8084/HelloWorld/sample/HelloWorld.action . You will see "Hello World!" printed in the browser.
Struts2 Application Workflow in a Nutshell
When you access the URL http://localhost:8084/HelloWorld/sample/HelloWorld.action,
- Struts2 filter configured in web.xml gets invoked. This looks at the URL and looks for a matching entry for HelloWorld (.action is automatically stripped off) in "sample" package in struts.xml.
- The execute() method of the HelloWorld action class is invoked which prepares the message and returns the value of "success".
- Struts looks for a view named "success" in struts.xml under the action class HelloWorld and finds index.jsp. The request is forwarded to index.jsp.
- The custom tags in index.jsp is executed and the value for "message" attribute in action class is rendered by making a call to method getMessage().
