Struts2 Validation With Example

Introduction to Struts2 Validation Framework
Struts Action 2 relies on a validation framework provided by XWork to enable the application of input validation rules to your Actions before they are executed. Struts2 Validation Framework allows us to separate the validation logic from actual Java/JSP code, where it can be reviewed and easily modified later.

The Struts2 Validation Framework alleviates much of the headache associated with handling data validation, allowing you to focus on validation code and not on the mechanics of capturing data and re-displaying incomplete or invalid data.

Validation framework comes with set of useful routines to handle form validation automatically and it can handle both server side as well as client side form validation. If certain validation is not present, you can create your own validation logic by implementing java interface com.opensymphony.xwork2.Validator and plug it into validation framework as a re-usable component.

Validator uses XML configuration files to determine which validation routines should be installed and how they should be applied for a given application. validators.xml file contains all common validators declaration. If validators.xml file is not present in classpath, a default validation file is loaded from path com/opensymphony/xwork2/validator/validators/default.xml.

The first configuration file, validator-rules.xml, declares the validation routines that should be plugged into the framework and provides logical names for each of the validations. The validator-rules.xml file also defines client-side JavaScript code for each validation routine. Validator can be configured to send this JavaScript code to the browser so that validations are performed on the client side as well as on the server side.

Validators Scope
There are two types of Validators in Struts2 Validation Framework.

  1. Field Validators
  2. Non-field validators

Field validators, as the name indicate, act on single fields accessible through an action. A validator, in contrast, is more generic and can do validations in the full action context, involving more than one field (or even no field at all) in validation rule. Most validations can be defined on per field basis. This should be preferred over non-field validation wherever possible, as field validator messages are bound to the related field and will be presented next to the corresponding input element in the respecting view.

<validators>
  <field name="bar">
      <field-validator type="required">
          <message>You must enter a value for bar.</message>
      </field-validator>
  </field>
</validators>

Non-field validators only add action level messages. Non-field validators are mostly domain specific and therefore offer custom implementations. The most important standard non-field validator provided by XWork is ExpressionValidator.

<validators>
      <validator type="expression">
            <param name="expression">foo lt bar</param>
            <message>Foo must be greater than Bar.</message>
      </validator>
</validators>

Validator Example-

In this chapter we will look into how Struts’s validation framework. At Struts’s core, we have the validation framework that assists the application to run the rules to perform validation before the action method is executed.

Client side validation is usually achieved using Javascript. But one should not rely upon client side validation alone. Best practice suggests that the validation should be introduced at all levels of your application framework. Now let us look at two ways of adding validation to our Struts project.

Here we will take an example of Employee whose name, age, email and telephone would be captured using a simple page and we will put two validation to make sure that use always enters a name, age should be in between 18 and 65 email should be valid telephone should be valid.

Struts2 Validation With Example

In this example we will see how we can validate a employee page using Struts 2. Let’s first create the employee page. We use Struts UI tags to create the employee page. The <s:head /> tag should be placed in the head section of the HTML page. The s:head tag automatically generates links to the css and javascript libraries that are necessary to render the form elements.

So let us start with the main JSP page of the example.

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Employee Form - Struts2 Demo | dineshonjava.com</title>
<s:head />
</head>
 
<body>
<h2>Employee Form</h2>
 
<s:form action="employee" method="post" validate="true">
    <s:textfield name="name" key="name" size="20" />
    <s:textfield name="age" key="age" size="20" />
    <s:textfield name="email" key="email" size="20" />
    <s:textfield name="telephone" key="telephone" size="20" />
    <s:submit method="addEmployee" key="label.add.employee" align="center" />
</s:form>
</body>
</html>

myapp.properties

name= Name
age= Age
email= Email
telephone= Telephone
label.add.employee=Add Employee
 
errors.invalid=${getText(fieldName)} is invalid.
errors.required=${getText(fieldName)} is required.
errors.number=${getText(fieldName)} must be a number.
errors.range=${getText(fieldName)} is not in the range ${min} and ${max}.

For this tutorial, we will create an Action class called EmployeeAction which will contain few fields. Create a file EmployeeAction.java in package com.dineshonjava.struts2.action

package com.dineshonjava.struts2.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Dinesh Rajput
 *
 */
public class EmployeeAction extends ActionSupport {

 private static final long serialVersionUID = 1L;
 private String name;
    private Integer age;
    private String email;
    private String telephone;
    
    public String addEmployee() {
        return SUCCESS;
    }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Integer getAge() {
  return age;
 }
 public void setAge(Integer age) {
  this.age = age;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 public String getTelephone() {
  return telephone;
 }
 public void setTelephone(String telephone) {
  this.telephone = telephone;
 }
    
}

Note that EmployeeAction class has fields name, email, telephone and age. Also it has a method called addEmployee() which doesn’t have any logic, it just return SUCCESS.

Configuration file-
Now we will add entry for this new action class in struts.xml file. Open the struts.xml file which will be present under resources folder.

<?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="false" />
    <constant name="struts.custom.i18n.resources" value="myapp" />
 
    <package name="default" extends="struts-default" namespace="/">
        <action name="employee" class="com.dineshonjava.struts2.action.EmployeeAction">
            <result name="success">/success.jsp</result>
      <result name="input">/employee.jsp</result>
          <result name="error">/error.jsp</result>
        </action>
    </package>
   
</struts>

Note that we are mapping the EmployeeAction class with name employee. Also on success user will be redirected to success.jsp page. Notice that there is another result tag with name input. Whenever the validation logic encounter some validation error, it redirects the user back to page specified as input. Thus in our example, user will be redirected back to employee.jsp in case of any errors.
success.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Employee Page - Struts2 Demo | dineshonjava.com</title>
</head>
 
<body>
    <h2>Employee Added Successfully.</h2>
</body>
</html>

index.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Welcome Page - Struts2 Demo | dineshonjava.com</title>
</head>
<body>
<s:a href="employee.jsp">Add Employee</s:a>
</body>
</html>

Adding Validation Logic
Now we are ready with the basic employee form on which we will add the validation logic. Following will be the validations rules:

  • Name field is mandatory
  • Age field is mandatory. It should be a number between 18 and 65.
  • Email field is mandatory. It should be a valid email address.
  • Telephone is mandatory.

In order to define validation logic for particular form, we first have to create an XML file which will hold this data. Struts2 define a specific naming convention in defining validation xml files. The format is <ActionClassName>-validation.xml. So for our application we will create a file EmployeeAction-validation.xml. Note that this file should be present in the same package as of action class.
 
Create file EmployeeAction-validation.xml in package com.dineshonjava.struts2.action

<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
    "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
    <field name="name">
        <field-validator type="requiredstring">
            <param name="trim">true</param>
            <message key="errors.required" />
        </field-validator>
    </field>
    <field name="age">
        <field-validator type="required">
            <message key="errors.required" />
        </field-validator>
        <field-validator type="int">
            <param name="min">18</param>
            <param name="max">65</param>
            <message key="errors.range"/>
        </field-validator>
    </field>
    <field name="email">
        <field-validator type="requiredstring">
            <message key="errors.required" />
        </field-validator>
        <field-validator type="email">
            <message key="errors.invalid" />
        </field-validator>
    </field>
    <field name="telephone">
        <field-validator type="requiredstring">
            <message key="errors.required" />
        </field-validator>
    </field>
</validators>

Client Side Validation-
It is very easy to add Client Side validation or JavaScript validation to any form in Struts2. All you have to do is to add validate=”true” in form tag in your JSP file. For example open employee.jsp and add validate=”true” in form tag. Struts2 automatically generates the JavaScript code for client side validation of form.

<s:form action="employee" method="post" validate="true">
    ...
</s:form>

Now, right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access

URL http://localhost:8080/doj/index.jsp.
This will give you following screen:
 

Struts2 Validation

click on Add Employee link then you got the following
URL http://localhost:8080/doj/employee.jsp

Struts2 Validation

Employee error page because of validation fails

Struts2 Validation


Employee page on success

Struts2 Validation

Download Source Code
Struts2Validation.zip

<<Previous <<   || Index ||   >>Next >>

Struts 2 Sending Mails

In this chapter we will teach you how to send an email using your Struts 2 application. For this application, you need to download and install the mail.jar from JavaMail API 1.4.7 and place the mail.jar file in your WEB-INFlib folder and then proceed to follow the standard steps of creating action, view and configuration files.

Struts 2 Sending Mails

Create Action:
The next step is to create an Action method that takes care of sending the email. Let us create a new class called MailAction.java with the following contents.

package com.dineshonjava.struts2.mail.action;

import java.util.Properties;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Dinesh Rajput
 *
 */
public class MailAction extends ActionSupport {

 private static final long serialVersionUID = 1L;
 private String from;
    private String password;
    private String to;
    private String subject;
    private String body;

    static Properties properties = new Properties();
    static
    {
       properties.put("mail.smtp.host", "smtp.gmail.com");
       properties.put("mail.smtp.socketFactory.port", "465");
       properties.put("mail.smtp.socketFactory.class",
                      "javax.net.ssl.SSLSocketFactory");
       properties.put("mail.smtp.auth", "true");
       properties.put("mail.smtp.port", "465");
    }

    public String execute() 
    {
       String ret = SUCCESS;
       try
       {
          Session session = Session.getDefaultInstance(properties,  
             new javax.mail.Authenticator() {
              protected PasswordAuthentication 
              getPasswordAuthentication() {
              return new 
              PasswordAuthentication(from, password);
             }});

          Message message = new MimeMessage(session);
          message.setFrom(new InternetAddress(from));
          message.setRecipients(Message.RecipientType.TO, 
             InternetAddress.parse(to));
          message.setSubject(subject);
          message.setText(body);
          Transport.send(message);
       }
       catch(Exception e)
       {
          ret = ERROR;
          e.printStackTrace();
       }
       return ret;
    }

    public String getFrom() {
       return from;
    }

    public void setFrom(String from) {
       this.from = from;
    }

    public String getPassword() {
       return password;
    }

    public void setPassword(String password) {
       this.password = password;
    }

    public String getTo() {
       return to;
    }

    public void setTo(String to) {
       this.to = to;
    }

    public String getSubject() {
       return subject;
    }

    public void setSubject(String subject) {
       this.subject = subject;
    }

    public String getBody() {
       return body;
    }

    public void setBody(String body) {
       this.body = body;
    }

    public static Properties getProperties() {
       return properties;
    }

    public static void setProperties(Properties properties) {
     MailAction.properties = properties;
    }
}

As seen in the source code above, the MailAction.java has properties that correspond to the form attributes in the welcome.jsp page given below. These attributes are

  • from – The email address of the sender. As we are using Google’s SMTP, we need a valid gtalk id
  • password – The password of the above account
  • to – Who to send the email to?
  • Subject – subject of the email
  • body – The actual email message

We have not considered any validations on the above fields, validations will be added in the next chapter. Let us now look at the execute() method. The execute() method uses the javax Mail library to send an email using the supplied parameters. If the mail is sent successfully, action returns SUCCESS, otherwise it returns ERROR.

Create view pages:
Let us write main page JSP file welcome.jsp, which will be used to collect email related information mentioned above:
welcome.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Email Form</title>
</head>
<body>
   <em>The form below uses Google's SMTP server. 
   So you need to enter a gmail username and password
   </em>
   <form action="emailer" method="post">
   <label for="from">From</label><br/>
   <input type="text" name="from"/><br/>
   <label for="password">Password</label><br/>
   <input type="password" name="password"/><br/>
   <label for="to">To</label><br/>
   <input type="text" name="to"/><br/>
   <label for="subject">Subject</label><br/>
   <input type="text" name="subject"/><br/>
   <label for="body">Body</label><br/>
   <input type="text" name="body"/><br/>
   <input type="submit" value="Send Email"/>
   </form>
</body>
</html>

success.jsp
We will use JSP file success.jsp which will be invoked in case action returns SUCCESS, but we will have another view file in case of an ERROR is returned from the action.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Email Success</title>
</head>
<body>
   Your email to <s:property value="to"/> was sent successfully.
</body>
</html>

error.jsp
Following will be the view file error.jsp in case of an ERROR is returned from the action.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Email Error</title>
</head>
<body>
   There is a problem sending your email to <s:property value="to"/>.
</body>
</html>

Configuration Files:
Now let us put everything together using the struts.xml configuration file as follows:

<?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="false" />
    <constant name="struts.custom.i18n.resources" value="myapp" />
 
    <package name="default" extends="struts-default" namespace="/">
        <action name="emailer" class="com.dineshonjava.struts2.mail.action.MailAction" method="execute">
            <result name="success">/success.jsp</result>
          <result name="error">/error.jsp</result>
        </action>
    </package>
   
</struts>

Following is the content of web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Struts2Mail</display-name>
  <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.FilterDispatcher
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>Welcome.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Now, right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access

URL http://localhost:8080/doj/welcome.jsp
This will give you following screen:

Struts 2 Sending Mails

Enter the required information and click Send Email button. If everything goes fine then you should see the following page
http://localhost:8080/doj/emailer

Struts 2 Sending Mails

See the Inbox of admin@dineshonjava.com as following.

Struts 2 Sending Mails


If any error come to sending the mail the following is coming.

Struts 2 Sending Mails

Download Source Code+Libs
Struts2Mail.zip

<<Previous <<   || Index ||   >>Next >>

Struts 2 Database Access

In this chapter we will teach you how to access a database using Struts 2 in simple steps. Struts is a MVC framework and not a database framework but it provides excellent support for JPA/Hibernate integration. We shall look at the hibernate integration in a later chapter, but in this chapter we shall use plain old JDBC to access the database.

The first step in this chapter is to setup and prime our database. I am using MySQL as my database for this example. I have MySQL installed on my machine and I have created a new database called “DOJDB“. I have created a table called “USER“and populated it with some values. Below is the script I used to create and populate the table.

CREATE TABLE users (
  User_ID VARCHAR(10) NOT NULL,
  UserName VARCHAR(10) NOT NULL,
  PASSWORD VARCHAR(10) NOT NULL,
  PRIMARY KEY (User_ID)
  ) 


INSERT INTO `DOJDB`.`users` 
 (`User_ID`, 
 `UserName`, 
 `PASSWORD`
 )
 VALUES
 ('DOJ01', 
 'Dinesh', 
 'Sweety'
 );

Create Action:
The action class has the properties corresponding to the columns in the database table. We have user, password and name as String attributes. In the action method, we use the user and password parameters to check if the user exists, if so , we display the user name in the next screen. If the user has entered wrong information, we send them to the login screen again.
Following is the content of LoginAction.java file:

package com.dineshonjava.struts2.login;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Dinesh Rajput
 *
 */
@SuppressWarnings("serial")
public class LoginAction  extends ActionSupport{
 private String username;
    private String password;
    private String userid;
    
 public String execute() {
  String ret = ERROR;
       Connection conn = null;

       try {
          String URL = "jdbc:mysql://localhost:3306/DOJDB";
          Class.forName("com.mysql.jdbc.Driver");
          conn = DriverManager.getConnection(URL, "root", "root");
          String sql = "SELECT name FROM user WHERE";
          sql+=" userName = ? AND password = ?";
          PreparedStatement ps = conn.prepareStatement(sql);
          ps.setString(1, username);
          ps.setString(2, password);
          ResultSet rs = ps.executeQuery();

          while (rs.next()) {
           username = rs.getString(1);
           ret = SUCCESS;
          }
       } catch (Exception e) {
        addActionError(getText("error.login"));  
          ret = ERROR;
       } finally {
          if (conn != null) {
             try {
                conn.close();
             } catch (Exception e) {
             }
          }
       }
       return ret;
    }

 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;
 }

 public String getUserid() {
  return userid;
 }

 public void setUserid(String userid) {
  this.userid = userid;
 }
 
}

Create main page:
Now, let us create a JSP file Login.jsp to collect the username and password. This username and password will be checked against the database.

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!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=ISO-8859-1">
<title>Struts 2 - Login Application | dineshonjava.com</title>
</head>
<body>
<h2>Struts 2 - Login Application</h2>
<font color="red"><s:actionerror /></font>
<s:form action="login/welcome.action" method="post">
    <s:textfield name="username" key="label.username" size="20" />
    <s:password name="password" key="label.password" size="20" />
    <s:submit method="execute" key="label.login" align="center" />
</s:form>
</body>
</html>

Create Views:
Now let us create success.jsp file which will be invoked in case action returns SUCCESS, but we will have another view file in case of an ERROR is returned from the action.

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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=ISO-8859-1">
<title>Welcome</title>
</head>
 
<body>
    <h2>Hello Welcome , <s:property value="username" />...! Dineshonjava.com</h2>
    
</body>
</html>

Configuration Files:
Finally, let us put everything together using the struts.xml configuration file as follows:

<?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="false" />
    <constant name="struts.custom.i18n.resources" value="myapp" />
 
      <package name="login" extends="struts-default" namespace="/login">
        <action name="welcome" class="com.dineshonjava.struts2.login.LoginAction">
            <result name="success">/Welcome.jsp</result>
            <result name="error">/Login.jsp</result>
        </action>
    </package>
    
   </struts>

myapp.properties

label.username= Username
label.password= Password
label.login= Login
error.login= Invalid Username/Password. Please try again.

Following is the content of web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Struts2MyFirstApp</display-name>
  <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.FilterDispatcher
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>Login.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Now, right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access

URL http://localhost:8080/doj/Login.jsp.

This will give you following screen:

Struts 2 Database Access

Enter a wrong user name and password. You should see the next page-

Struts Database Access

Now enter “Dinesh” as user name and “Sweety” as password. You should see the next page-

Struts 2 Database

Download Source Code+Libs
Struts2Database.zip

<<Previous <<   || Index ||   >>Next >>

Struts 2 File Upload Example

In this example you will learn how to do file upload with the help of the built-in FileUploadInterceptor. To do this first we need to get the file form the user. We use the Struts 2 tags to build our form. The encoding type of the form should be set to multipart/form-data and the HTTP method should be set to post. The index.jsp page contains the following code.

Create two JSP file in WebRoot folder. index.jsp will display a form to user to upload image. On submit, the file will be uploaded and saved on server. User will be sent to success.jsp file where File details will be displayed. Copy following code into it.

index.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Upload User Image</title>
</head>
 
<body>
<h2>Struts2 File Upload & Save Example</h2>
<s:actionerror />
<s:form action="userImage" method="post" enctype="multipart/form-data">
    <s:file name="userImage" label="User Image" size="10"/>
    <s:submit value="Upload" align="center" />
</s:form>
</body>
</html>

There are couple of points worth noting in the above example. First of all, the form’s enctype is set to multipart/form-data. This should be set so that file uploads are handled successfully by the file upload interceptor. The next point noting is the form’s action method upload and the name of the file upload field – which is userImage. We need this information to create the action method and the struts configuration.

Next let us create a simple jsp file success.jsp to display the outcome of our file upload in case it becomes success. 
success.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Success: Upload User Image</title>
</head>
<body>
    <h2>Struts2 File Upload Example</h2>
    User Image: <s:property value="userImage"/>
    <br/>
    Content Type: <s:property value="userImageContentType"/>
    <br/>
    File Name: <s:property value="userImageFileName"/>
    <br/>
    Uploaded Image:
    <br/>
    <img src="<s:property value="userImageFileName"/>"/>
</body>
</html>

Following will be the result file error.jsp in case there is some error in uploading the file:
error.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>File Upload Error</title>
</head>
<body>
There has been an error in uploading the file.
</body>
</html>

Create action class:
Next let us create a Java class called FileUploadAction.java which will take care of uploading file and storing that file at a secure location:

package com.dineshonjava.struts2.action.upload;

import java.io.File;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.apache.struts2.interceptor.ServletRequestAware;

import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Dinesh Rajput
 *
 */
public class FileUploadAction extends ActionSupport implements ServletRequestAware {
 private static final long serialVersionUID = 1L;
 private File userImage;
 private String userImageContentType;
 private String userImageFileName;
 
 private HttpServletRequest servletRequest;
 
 public String execute() {
  try {
      String filePath = servletRequest.getSession().getServletContext().getRealPath("/");
      System.out.println("Server path:" + filePath);
      File fileToCreate = new File(filePath, this.userImageFileName);
  
      FileUtils.copyFile(this.userImage, fileToCreate);
  } catch (Exception e) {
      e.printStackTrace();
      addActionError(e.getMessage());
 
      return INPUT;
  }
  return SUCCESS;
 }
 
 public File getUserImage() {
  return userImage;
 }
 
 public void setUserImage(File userImage) {
  this.userImage = userImage;
 }
 
 public String getUserImageContentType() {
  return userImageContentType;
 }
 
 public void setUserImageContentType(String userImageContentType) {
  this.userImageContentType = userImageContentType;
 }
 
 public String getUserImageFileName() {
  return userImageFileName;
 }
 
 public void setUserImageFileName(String userImageFileName) {
  this.userImageFileName = userImageFileName;
 }
 
 @Override
 public void setServletRequest(HttpServletRequest servletRequest) {
  this.servletRequest = servletRequest;
 }
}

In above class file we have declared few attributes:

  • private File userImage; -> This will store actual uploaded File
  • private String userImageContentType; -> This string will contain the Content Type of uploaded file.
  • private String userImageFileName; -> This string will contain the file name of uploaded file.

The fields userImageContentType and userImageFileName are optional. If setter method of these fields are provided, struts2 will set the data. This is just to get some extra information of uploaded file. Also follow the naming standard if you providing the content type and file name string. The name should be ContentType and FileName. For example if the file attribute in action file is private File uploadedFile, the content type will be uploadedFileContentType and file name uploadedFileFileName.
Also note in above action class, we have implemented interface org.apache.struts2.interceptor.ServletRequestAware. This is to get servletRequest object. We are using this path to save the uploaded file in execute() method. We have used FileUtil.copyFile() method of commons-io package to copy the uploaded file in root folder. This file will be retrieved in JSP page and displayed to user.

Configuration files:
Following are the Struts2 configuration properties that control file uploading process:

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.devMode" value="true" />
   <package name="upload" extends="struts-default">
      <action name="userImage" class="com.dineshonjava.struts2.action.upload.FileUploadAction">
      <interceptor-ref name="fileUpload">
         <param name="maximumSize">2097152</param>
         <param name="allowedTypes">
             image/png,image/gif,image/jpeg,image/pjpeg
         </param>
       </interceptor-ref>
    <interceptor-ref name="defaultStack"></interceptor-ref>
    <result name="success">success.jsp</result>
    <result name="input">index.jsp</result>
     <result name="error">error.jsp</result>
 </action>
   </package>
 </struts>

Note that in above entry we have specified two parameter to fileUpload interceptor, maximumSize and allowedTypes. These are optional parameters that we can specify to interceptor. The maximumSize param will set the maximum file size that can be uploaded. By default this is 2MB. And the allowedTypes param specify the allowed content types of file which can be uploaded. Here we have specified it to be an image file (image/png,image/gif,image/jpeg,image/pjpeg).

The file upload interceptor also does the validation and adds errors, these error messages are stored in the struts-messsages.properties file. The values of the messages can be overridden by providing the text for the following keys:

  1. struts.messages.error.uploading – error when uploading of file fails
  2. struts.messages.error.file.too.large – error occurs when file size is large
  3. struts.messages.error.content.type.not.allowed – when the content type is not allowed

Following is the content of web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Struts2FileUpload</display-name>
  <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.FilterDispatcher
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Now Right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access
URL http://localhost:8080/doj/index.jsp.
This will give you following screen:

Struts 2 File Upload Example

Image Upload Screen in case of error-

Struts 2 File Upload Example

Image Upload Screen on success-

Struts 2 File Upload Example

Another Image Upload Screen on success-

Struts 2 File Upload Example

Download Source Code+Libs
Struts2FileUpload.zip

<<Previous <<   || Index ||   >>Next >>

Struts 2 Result Types

As mentioned previously, the <results> tag plays the role of a view in the Struts2 MVC framework. The action is responsible for executing the business logic. The next step after executing the business logic is to display the view using the <results> tag.

Often there is some navigation rules attached with the results.
 For example, if the action method is to authenticate a user, there are three possible outcomes. 
 (a) Successful Login
 (b) Unsuccessful Login – Incorrect username or password 
 (c) Account Locked.

In this scenario, the action method will be configured with the three possible outcome strings and three different views to render the outcome. We have already seen this in the previous examples.

But, Struts2 does not tie you up with using JSP as the view technology. After all the whole purpose of the MVC paradigm is to keep the layers separate and highly configurable. For example, for a Web2.0 client, you may want to return XML or JSON as the output. In this case, you could create a new result type for XML or JSON and achieve this.

Struts comes with a number of predefined result types and whatever we’ve already seen that was the default result type dispatcher, which is used to dispatch to JSP pages. Struts allow you to use other markup languages for the view technology to present the results and popular choices include Velocity, Freemaker, XSLT and Tiles.

The dispatcher result type:
The dispatcher result type is the default type, and is used if no other result type is specified. It’s used to forward to a servlet, JSP, HTML page, and so on, on the server. It uses the RequestDispatcher.forward() method.

We saw the “shorthand” version in our earlier examples, where we provided a JSP path as the body of the result tag.

<result name="success">
   /success.jsp
</result>

We can also specify the JSP file using a <param name=”location”> tag within the <result…> element as follows:

<result name="success" type="dispatcher">
   <param name="location">
      /success.jsp
   </param >
</result>

We can also supply a parse parameter, which is true by default. The parse parameter determines whether or not the location parameter will be parsed for OGNL expressions.

The FreeMaker result type:
In this example we are going to see how we can use FreeMaker as the view technology. Freemaker is a popular templating engine that is used to generate output using predefined templates. Let us create a Freemaker template file called hello.fm with the following contents:

Hello World ${name}

Here above file is a template where name is a parameter which will be passed from outside using the defined action. You will keep this file in your CLASSPATH. Next, let us modify the struts.xml to specify the result as follows:

<?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.devMode" value="true" />
   <package name="helloworld" extends="struts-default">
       
      <action name="hello" class="com.dineshonjava.struts2.action.HelloWorldAction" method="execute">
        <result name="success" type="freemarker">
            <param name="location">/hello.fm</param>
         </result>
       </action>
   </package>
 </struts>

The redirect result type:
The redirect result type calls the standard response.sendRedirect() method, causing the browser to create a new request to the given location.

We can provide the location either in the body of the <result…> element or as a <param name=”location”> element. Redirect also supports the parse parameter. Here’s an example configured using XML:

<action name="hello" class="com.dineshonjava.struts2.action.HelloWorldAction" method="execute">
   <result name="success" type="redirect">
       <param name="location">
         /NewWorld.jsp
        </param >
   </result>
 </action>

<<Previous <<   || Index ||   >>Next >>

Struts 2 Interceptors

Interceptors are conceptually the same as servlet filters or the JDKs Proxy class. Interceptors allow for crosscutting functionality to be implemented separately from the action as well as the framework. You can achieve the following using interceptors:

  • Providing preprocessing logic before the action is called.
  • Providing postprocessing logic after the action is called.
  • Catching exceptions so that alternate processing can be performed.

Many of the features provided in the Struts2 framework are implemented using interceptors; examples include exception handling, file uploading, lifecycle callbacks and validation etc. In fact, as Struts2 bases much of its functionality on interceptors, it is not unlikely to have 7 or 8 interceptors assigned per action.

Advantage of interceptors

Pluggable If we need to remove any concern such as validation, exception handling, logging etc. from the application, we don’t need to redeploy the application. We only need to remove the entry from the struts.xml file.

Struts 2 default interceptors

There are many interceptors provided by struts 2 framework. We have option to create our own interceptors. The struts 2 default interceptors are as follows:
1) alias It converts similar parameters that have different names between requests.
2) autowiring
3) chain If it is used with chain result type, it makes the properties of previous action available in the current action.
4) checkbox It is used to handle the check boxes in the form. By this, we can detect the unchecked checkboxes.
5) cookie It adds a cookie to the current action.
6) conversionError It adds conversion errors to the action’s field errors.
7) createSession It creates and HttpSession object if it doesn’t exists.
8) clearSession It unbinds the HttpSession object.
9) debugging It provides support of debugging.
10) externalRef
11) execAndWait It sends an intermediate waiting page for the result.
12) exception It maps exception to a result.
13) fileUpload It provides support to file upload in struts 2.
14) i18n It provides support to internationalization and localization.
15) jsonValidation It provides support to asynchronous validation.
16) logger It outputs the action name.
17) store It stores and retrieves action messages, action errors or field errors for action that implements ValidationAware interface.
18) modelDriven It makes other model object as the default object of valuestack.
19) scopedModelDriven It is similar to ModelDriven but works for action that implements ScopedModelDriven.
20) params It populates the action properties with the request parameters.
21) actionMappingParams
22) prepare It performs preparation logic if action implements Preparable interface.
23) profiling It supports action profiling.
24) roles It supports role-based action.
25) scope It is used to store the action state in the session or application scope.
26) servletConfig It provides access to maps representing HttpServletRequest and HttpServletResponse.
27) sessionAutowiring
28) staticParams It maps static properties to action properties.
29) timer It outputs the time needed to execute an action.
30) token It prevents duplication submission of request.
31) tokenSession It prevents duplication submission of request.
32) validation It provides support to input validation.
33) workflow It calls the validate method of action class if action class implements Validate able interface.
34) annotationWorkflow
35) multiselect

How to use Interceptors?
Let us see how to use an already existing interceptor to our “Hello World” program. We will use the timer interceptor whose purpose is to measure how long it took to execute an action method. Same time I’m using params interceptor whose purpose is to send the request parameters to the action. You can try your example without using this interceptor and you will find that name property is not being set because parameter is not able to reach to the action.

We will keep HelloWorldAction.java, web.xml, success.jsp and index.jsp files as they have been created in Examples chapter but let us modify the struts.xml file to add an interceptor as follows

<?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.devMode" value="true" />
   <package name="helloworld" extends="struts-default">
      <action name="hello" class="com.dineshonjava.struts2.action.HelloWorldAction" method="execute">
         <interceptor-ref name="params"/>
         <interceptor-ref name="timer" />
         <result name="success">/success.jsp</result>
         <result name="error">/error.jsp</result>
      </action>
   </package>
 </struts>

Execute the Application-
Right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access
URL http://localhost:8080/doj/. This will give you following screen:

Struts 2 Interceptors

Now enter any word in the given text box and click Say Hello button to execute the defined action. Now if you will check the log generated, you will find following text:

INFO: Server startup in 2135 ms
Jul 27, 2013 6:18:58 PM com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
INFO: Executed action [//hello!execute] took 130 ms.

Here bottom line is being generated because of timer interceptor which is telling that action took total 130ms to be executed.

Create Custom Interceptors
Using custom interceptors in your application is an elegant way to provide cross-cutting application features. Creating a custom interceptor is easy; the interface that needs to be extended is the following Interceptor interface:

public interface Interceptor extends Serializable{
   void destroy();
   void init();
   String intercept(ActionInvocation invocation)
   throws Exception;
}

As the names suggest, the init() method provides a way to initialize the interceptor, and the destroy() method provides a facility for interceptor cleanup. Unlike actions, interceptors are reused across requests and need to be thread-safe, especially the intercept() method.

The ActionInvocation object provides access to the runtime environment. It allows access to the action itself and methods to invoke the action and determine whether the action has already been invoked.

If you have no need for initialization or cleanup code, the AbstractInterceptor class can be extended. This provides a default no-operation implementation of the init() and destroy() methods.

Create Interceptor Class:
Let us create following MyInterceptor.java in Java Resources > src folder:

package com.dineshonjava.struts2.intercept;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

/**
 * @author Dinesh Rajput
 *
 */
public class MyInterceptor extends AbstractInterceptor {

 private static final long serialVersionUID = 1L;

 @Override
 public String intercept(ActionInvocation invocation)throws Exception{

       /* let us do some pre-processing */
       String output = "Pre-Processing"; 
       System.out.println(output);

       /* let us call action or next interceptor */
       String result = invocation.invoke();

       /* let us do some post-processing */
       output = "Post-Processing"; 
       System.out.println(output);

       return result;
    }

}

As you notice, actual action will be executed using the interceptor by invocation.invoke() call. So you can do some pre-processing and some post-processing based on your requirement.

The framework itself starts the process by making the first call to the ActionInvocation object’s invoke(). Each time invoke() is called, ActionInvocation consults its state and executes whichever interceptor comes next. When all of the configured interceptors have been invoked, the invoke() method will cause the action itself to be executed. Following diagram shows the same concept through a request flow:

Struts 2 actioninvocation

Create Action Class:

package com.dineshonjava.struts2.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Dinesh Rajput
 *
 */
public class HelloWorldAction extends ActionSupport {
 private static final long serialVersionUID = 4956157388836635122L;
 private String name;

    public String execute() throws Exception {
    if ("SECRET".equals(name))
       {
          return SUCCESS;
       }else{
          return ERROR;  
       }
    }  

    public String getName() {
       return name;
    }

    public void setName(String name) {
       this.name = name;
    }
}

Create a View-

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
   Hello World, <s:property value="name"/>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello World</title>
</head>
<body>
   <h1>Hello World From Struts2</h1>
   <form action="hello">
      <label for="name">Please enter your name</label><br/>
      <input type="text" name="name"/>
      <input type="submit" value="Say Hello"/>
   </form>
</body>
</html>

Configuration Files-
Now we need to register our interceptor and then call it as we had called default interceptor in previous example. To register a newly defined interceptor, the <interceptors>…</interceptors> tags are placed directly under the <package> tag ins struts.xml file. You can skip this step for a default interceptors as we did in our previous example. But here let us register and use it as follows:

<?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.devMode" value="true" />
   <package name="helloworld" extends="struts-default">
      <interceptors>
         <interceptor name="myinterceptor" class="com.dineshonjava.struts2.intercept.MyInterceptor" />
      </interceptors>
      
      <action name="hello" class="com.dineshonjava.struts2.action.HelloWorldAction" method="execute">
         <interceptor-ref name="params"/>
         <interceptor-ref name="myinterceptor" />
         <result name="success">/success.jsp</result>
         <result name="error">/error.jsp</result>
      </action>
   </package>
 </struts>

web.xml is same as previous example.
Execute the Application-
Right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access
URL http://localhost:8080/doj/. This will give you following screen:

Interceptors

Now enter any word in the given text box and click Say Hello button to execute the defined action. Now if you will check the log generated, you will find following text:

INFO: Overriding property struts.configuration.xml.reload – old value: false new value: true
Pre-Processing
Post-Processing

Stacking multiple Interceptors:
As you can imagine, having to configure multiple interceptor for each action would quickly become extremely unmanageable. For this reason, interceptors are managed with interceptor stacks. Here is an example, directly from the struts-default.xml file:

<interceptor-stack name="basicStack">
   <interceptor-ref name="exception"/>
   <interceptor-ref name="servlet-config"/>
   <interceptor-ref name="prepare"/>
   <interceptor-ref name="checkbox"/>
   <interceptor-ref name="params"/>
   <interceptor-ref name="conversionError"/>
</interceptor-stack>

The above stake is called basicStack and can be used in your configuration as shown below. This configuration node is placed under the <package …/> node. Each <interceptor-ref …/> tag references either an interceptor or an interceptor stack that has been configured before the current interceptor stack. It is therefore very important to ensure that the name is unique across all interceptor and interceptor stack configurations when configuring the initial interceptors and interceptor stacks.

<action name="hello" class="com.dineshonjava.struts2.action.HelloWorldAction" method="execute">
         <interceptor-ref name="basicStack"/>
         <result name="success">/success.jsp</result>
         <result name="error">/error.jsp</result>
      </action>

We have already seen how to apply interceptor to the action, applying interceptor stacks is no different. In fact, we use exactly the same tag:

The above registration of “basicStack” will register complete stake of all the six interceptors with hello action. This should be noted that interceptors are executed in the order, in which they have been configured. For example, in above case, exception will be executed first, second would be servlet-config and so on.

Download Source Code
Struts2Interceptor.zip

<<Previous <<   || Index ||   >>Next >>

Struts 2 Actions

Actions are the core of the Struts2 framework, as they are for any MVC (Model View Controller) framework. Each URL is mapped to a specific action, which provides the processing logic necessary to service the request from the user.

But the action also serves in two other important capacities. First, the action plays an important role in the transfer of data from the request through to the view, whether its a JSP or other type of result. Second, the action must assist the framework in determining which result should render the view that will be returned in the response to the request.

Create Action:
The only requirement for actions in Struts2 is that there must be one no-argument method that returns either a String or Result object and must be a POJO. If the no-argument method is not specified, the default behavior is to use the execute() method.

Optionally you can extend the ActionSupport class which implements six interfaces including Action interface. The Action interface is as follows:

public interface Action {
   public static final String SUCCESS = "success";
   public static final String NONE = "none";
   public static final String ERROR = "error";
   public static final String INPUT = "input";
   public static final String LOGIN = "login";
   public String execute() throws Exception;
}

Let us take a look at the action method in the Hello World example:

package com.dineshonjava.struts2.action;

/**
 * @author Dinesh Rajput
 *
 */
public class HelloWorldAction {
 private static final long serialVersionUID = 4956157388836635122L;
 private String name;

    public String execute() throws Exception {
       return "success";
    }  

    public String getName() {
       return name;
    }

    public void setName(String name) {
       this.name = name;
    }
}

To illustrate the point that the action method controls the view, let us make the following change to the execute method and extend the class ActionSupport as follows:

package com.dineshonjava.struts2.action;

import com.opensymphony.xwork2.ActionSupport;

/**
 * @author Dinesh Rajput
 *
 */
public class HelloWorldAction extends ActionSupport {
 private static final long serialVersionUID = 4956157388836635122L;
 private String name;

   public String execute() throws Exception {
            if ("SECRET".equals(name))
            {
                return SUCCESS;
            }else{
               return ERROR;  
            }
          }

    public String getName() {
       return name;
    }

    public void setName(String name) {
       this.name = name;
    }
}

In this example, we have some logic in the execute method to look at the name attribute. If the attribute equals to the string “SECRET”, we return SUCCESS as the result otherwise we return ERROR as the result. Because we have extended ActionSupport, so we can use String constants SUCCESS and ERROR. Now, let us modify our struts.xml file as follows:

<?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.devMode" value="true" />
   <package name="helloworld" extends="struts-default">
      <action name="hello" class="com.dineshonjava.struts2.action.HelloWorldAction" method="execute">
         <result name="success">/success.jsp</result>
          <result name="error">/error.jsp</result>
      </action>
   </package>
 </struts>

Create a View-
Let us create the below jsp file success.jsp in the WebRoot folder in your eclipse project. To do this, right click on the WebRoot folder in the project explorer and select New >JSP File. This file will be called in case return result is SUCCESS which is a String constant “success” as defined in Action interface

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
   Hello World, <s:property value="name"/>
</body>
</html>

Following is the file which will be invoked by the framework in case action result is ERROR which is equal to String constant “error”. Following is the content of error.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Access Denied</title>
</head>
<body>
   You are not authorized to view this page.
</body>
</html>

We also need to create index.jsp in the WebRoot folder. This file will serve as the initial action URL where the user can click to tell the Struts 2 framework to call the execute method of the HelloWorldAction class and render the success.jsp view.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello World</title>
</head>
<body>
   <h1>Hello World From Struts2</h1>
   <form action="hello">
      <label for="name">Please enter your name</label><br/>
      <input type="text" name="name"/>
      <input type="submit" value="Say Hello"/>
   </form>
</body>
</html>

That’s it, there is no change required web.xml file, so let us use same web.xml which we had created in Examples chapter. Now we are ready to run our Hello World application using Struts 2 framework.

Execute the Application-
Right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access
 URL http://localhost:8080/doj/. This will give you following screen:

Struts 2 Actions

Let us enter a word as “SECRET” and you should see the following page:

Struts Actions

Now enter any word other than “dinesh” and you should see the following page:

Actions

Download Source Code
Struts2Action.zip

<<Previous <<   || Index ||   >>Next >>

Struts 2 OGNL, ActionInvocation, ActionContext

The Object Graph Navigation Language (OGNL) is an expression language. It simplifies the accessibility of data stored in the ActionContext.

The struts framework sets the ValueStack as the root object of OGNL. Notice that action object is pushed into the ValueStack. We can direct access the action property.

<s:property value="username"/>

Here, username is the property key
.
The struts framework places other objects in ActionContext also e.g. map representing the request, session, application scopes.

To get these values i.e. not the action property, we need to use # notation. For example to get the data from session scope, we need to use #session as given in the following example:

<s:property name="#session.username"/>

(or)

<s:property name="#session['username']"/>


Struts 2 ActionInvocation

The ActionInvocation represents the execution state of an action. It holds the action and interceptors objects.

The struts framework provides ActionInvocation interface to deal with ActionInvocation. It provides many methods, some of them can be used to get the instance of ValueStack, ActionProxy, ActionContext, Result etc.

Methods of ActionInvocation Interface

The commonly used methods of ActionInvocation interface are as follows:
1)public ActionContext getInvocationContext() returns the ActionContext object associated with the ActionInvocation.
2)public ActionProxy getProxy() returns the ActionProxy instance holding this ActionInvocation.
3)public ValueStack getStack() returns the instance of ValueStack.
4)public Action getAction() returns the instance of Action associated with this ActionInvocation.
5)public void invoke() invokes the next resource in processing this ActionInvocation.
6)public Result getResult() returns the instance of Result.


Struts 2 ActionContex

The ActionContext is a container of objects in which action is executed. The values stored in the ActionContext are unique per thread (i.e. ThreadLocal). So we don’t need to make our action thread safe. 

We can get the reference of ActionContext by calling the getContext() method of ActionContext class. It is a static factory method. For example: 

ActionContext context = ActionContext.getContext();
<<Previous <<   || Index ||   >>Next >>

The ValueStack in Struts 2

In this tutorial we will discuss about the ValueStack in the Struts2 how its work behind the scene. Fist lets see the high level picture of flow request data to Struts2 framework.

The ValueStack in Struts 2

Step 1. Client send the request to server.
Step 2. Struts configuration file map to specific action class.
Step 3. Action class has business service class to operate business logic and return result data to the action class and action class set this data to self member variables.
Step 4. After setting result to member variable it send to the JSP to view.
Step 5. JSP using the some TAGS to display result.
Step 6. JSP prepare the response as HTML and return to client.

Now we will see the How Servlet work. High Level flow of request to Servlet.

The ValueStack in Struts

Step-
1.  We are given objects to use, but we will need to do the “push” and “pull” of data ourseleves.
2. Servlet places the business data into the session and the JSP accesses it.
3 This has to be done for every servlet-to-JSP flow that data to be communicated.

ValueStack in Struts

Now we move to Struts2 framework how it is work internally.
Step 1. New Action objects are created for each request.

ValueStack Struts

In the above every requests have own Action instances with member variables. Now here there are some complicated to display member variable to JSP. it may be override to each other. So overcome this problem Struts 2 introduce to ValueStack.

ValueStack

ValueStack-
A valueStack is simply a stack that contains application specific objects such as action objects and other model object. At the execution time, action is placed on the top of the stack. We can put objects in the valuestack, query it and delete it.

ValueStack

1. It is not really a stack in the traditional sense.
2. It does stack up objects.
3. Behave like a virtual object.
4. Makes it easy to refer to member variables.

The value stack is a set of several objects which keeps the following objects in the provided order:
SN Objects & Description
1 Temporary Objects
There are various temporary objects which are created during execution of a page. For example the current iteration value for a collection being looped over in a JSP tag.
2 The Model Object
If you are using model objects in your struts application, the current model object is placed before the action on the value stack
3 The Action Object
This will be the current action object which is being executed.
4 Named Objects
These objects include #application, #session, #request, #attr and #parameters and refer to the corresponding servlet scopes
The value stack can be accessed via the tags provided for JSP, Velocity or Freemarker. There are various tags which we will study in separate chapters, are used to get and set struts 2.0 value stack. You can get valueStack object inside your action as follows:
ActionContext.getContext().getValueStack()
Once you have a ValueStack object, you can use following methods to manipulate that object:
SN ValueStack Methods & Description
1 Object findValue(String expr)
Find a value by evaluating the given expression against the stack in the default search order.
2 CompoundRoot getRoot()
Get the CompoundRoot which holds the objects pushed onto the stack.
3 Object peek()
Get the object on the top of the stack without changing the stack.
4 Object pop()
Get the object on the top of the stack and remove it from the stack.
5 void push(Object o)
Put this object onto the top of the stack.
6 void set(String key, Object o)
Sets an object on the stack with the given key so it is retrievable by findValue(key,…)
7 void setDefaultType(Class defaultType)
Sets the default type to convert to if no type is provided when getting a value.
8 void setValue(String expr, Object value)
Attempts to set a property on a bean in the stack with the given expression using the default search order.
9 int size()
Get the number of objects in the stack.

The OGNL:

The Object-Graph Navigation Language (OGNL) is a powerful expression language that is used to reference and manipulate data on the ValueStack. OGNL also helps in data transfer and type conversion.
The OGNL is very similar to the JSP Expression Language. OGNL is based on the idea of having a root or default object within the context. The properties of the default or root object can be referenced using the markup notation, which is the pound symbol.
As mentioned earlier, OGNL is based on a context and Struts builds an ActionContext map for use with OGNL. The ActionContext map consists of the following:
  • application – application scoped variables
  • session – session scoped variables
  • root / value stack – all your action variables are stored here
  • request – request scoped variables
  • parameters – request parameters
  • atributes – the attributes stored in page, request, session and application scope
It is important to understand that the Action object is always available in the value stack. So, therefore if your Action object has properties x and y there are readily available for you to use.
Objects in the ActionContext are referred using the pound symbol, however, the objects in the value stack can be directly referenced, for example if employee is a property of an action class then it can get referenced as follows:
<s:property value="name"/>

instead of

<s:property value="#name"/>

If you have an attribute in session called “login” you can retrieve it as follows:

<s:property value="#session.login"/>

OGNL also supports dealing with collections – namely Map, List and Set. For example to display a dropdown list of colors, you could do:

<s:property name="color" list="{'red','yellow','green'}"/>

ValueStack/OGNL Example:-

CREATE ACTION:
Let us consider following action class where we are accessing valueStack and then setting few keys which we will access using OGNL in our view ie. JSP page.

package com.dineshonjava.struts2.action;

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

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

/**
 * @author Dinesh Rajput
 *
 */
public class HelloWorldAction extends ActionSupport {
 private static final long serialVersionUID = 4956157388836635122L;
 private String name;

    public String execute() throws Exception {
       ValueStack stack = ActionContext.getContext().getValueStack();
       Map<String, Object> context = new HashMap<String, Object>();

       context.put("key1", new String("This is key1")); 
       context.put("key2", new String("This is key2"));
       stack.push(context);

       System.out.println("Size of the valueStack: " + stack.size());
       return "success";
    }  

    public String getName() {
       return name;
    }

    public void setName(String name) {
       this.name = name;
    }
}

Actually, Struts 2 adds your action to the top of the valueStack when executed. So, the usual way to put stuff on the Value Stack is to add getters/setters for the values to your Action class and then use <s:property> tag to access the values. But I’m showing you how exactly ActionContext and ValueStack work in struts.

CREATE VIEWS
Let us create the below jsp files success.jsp in the WebRoot folder in your eclipse project. This view will be displayed in case action returns success:

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Hello World</title>
</head>
<body>
   Entered value : <s:property value="name"/><br/>
   Value of key 1 : <s:property value="key1" /><br/>
   Value of key 2 : <s:property value="key2" /> <br/>
</body>
</html>

We also need to create index.jsp in the WebRoot folder whose content is as follows:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
   pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
   <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello World</title>
</head>
<body>
   <h1>Hello World From Struts2</h1>
   <form action="hello">
      <label for="name">Please enter your name</label><br/>
      <input type="text" name="name"/>
      <input type="submit" value="Say Hello"/>
   </form>
</body>
</html>

CONFIGURATION FILES
Following is the content of struts.xml file:

<?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.devMode" value="true" />
   <package name="helloworld" extends="struts-default">
      <action name="hello" class="com.dineshonjava.struts2.action.HelloWorldAction" method="execute">
         <result name="success">/success.jsp</result>
      </action>
   </package>
 </struts>

Following is the content of web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Struts2ValueStack</display-name>
  <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.FilterDispatcher
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Right click on the project name and click Export > WAR File to create a War file. Then deploy this WAR in the Tomcat’s webapps directory. Finally, start Tomcat server and try to access 
URL http://localhost:8080/doj/. This will give you following screen:

ValueStack

Now enter any word in the given text box and click “Say Hello” button to execute the defined action. Now if you will check the log generated, you will find following text at the bottom:

output on console:
Size of the valueStack: 3

and this will display following screen, which will display whatever value you will enter and value of key1 and key2 which we had put on ValueStack.

ValueStack

Download SourceCode + Libs
Struts2ValueStack.zip

<<Previous <<   || Index ||   >>Next >>

A Tag And A Business Service

In this tutorial we will discuss an example of using a business service in the Action class with a tag in the JSP file. Business Service is the class where we put the business logic on the coming request and return the value to the response. In the following figure we will see that how to flow the request between the Action and Business Service and View.

A Tag And A Business Service

Business service return the data to the action and action return the these data as a response to the client with associated view. 

In the JSP file data return by the business service assigned to variable in the action class this variable assign to the JSP file with using a TAG. <s:property/>.

Look the following example using a simple business service with <s:property/> tag.

A Tag And A Business Service

After creating directory structure add the following code to the files.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Struts2TutorialFinder</display-name>
  <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.FilterDispatcher
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>success.jsp</welcome-file>
    </welcome-file-list>
</web-app>

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.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="false" />
    <constant name="struts.custom.i18n.resources" value="myapp" />
 
    <package name="default" extends="struts-default" namespace="/tutorials">
        <action name="getTutorial" class="com.dineshonjava.struts2.action.TutorialAction">
            <result name="success">/success.jsp</result>
            <result name="error">/error.jsp</result>
        </action>
    </package>
    
</struts>

In the above struts configuration file we are using the package with namespace “/tutorials”. And action name is “getTutorial” with the TutorialAction class. If return success for success.jsp and error with error.jsp.

TutorialAction.java

package com.dineshonjava.struts2.action;

import com.dineshonjava.struts2.service.TutorialFinderService;

/**
 * @author Dinesh Rajput
 *
 */
public class TutorialAction {
 private String bestTutorialSite;
 public String execute() {
  TutorialFinderService finderService = new TutorialFinderService();
  String bestSite = finderService.getBestTutorialSite();
  setBestTutorialSite(bestSite);
  System.out.println(bestSite);
  return "success";
 }
 public String getBestTutorialSite() {
  return bestTutorialSite;
 }
 public void setBestTutorialSite(String bestTutorialSite) {
  this.bestTutorialSite = bestTutorialSite;
 }
 
}

In the above tutorial action class we are using the business service “TutorialFinderService.java” for operating some business logic to the data. Business service has one method “getBestTutorialSite()” which return the name of the best tutorial site to the Action class and this value set to the variable “bestTutorialSite”.

TutorialFinderService.java

package com.dineshonjava.struts2.service;

/**
 * @author Dinesh Rajput
 *
 */
public class TutorialFinderService {
 public String getBestTutorialSite(){
  return "www.dineshonjava.com";
 }
}

The above class is business service class which define the business logic.

success.jsp

<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!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=ISO-8859-1">
<title>Success | dineshonjava.com</title>
</head>
 
<body>
    <h2>Business Service Executed!!! 
    <s:property value="bestTutorialSite"/></h2>
</body>
</html>

In the above JSP file we are using one TAG for display the value of variable which assigned in the Action class using the following TAG name.

<s:property value="bestTutorialSite"/>

A Tag And A Business Service

Download SourceCode + Libs
Struts2TutorialFinder.zip

<<Previous <<   || Index ||   >>Next >>