Struts2 Token Interceptor to handle double form submission problem

Struts 2 provides token interceptor that we can use to handle multiple form submission problem. While designing web application, sometimes we need to make sure that double form submission is treated as duplicate request and not be processed otherwise it can cause serious implications. For example, if user reloads the online payment form and there are not enough checks in place to identify it as duplicate request, customer will be charged twice.

Double form submission problem handling needs to be done both at client side and server side. In client side, we can disable the submit button, disable back button but there will always be options through which user can send the form data again. Struts2 provides token interceptors that are designed to deal with this particular problem.

There are two interceptors defined in struts-default package as:

            <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
            <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>

These interceptors are not part of any predefined interceptor stack because if we add it for any action, the form submitted should have a token parameter else it will throw exception. We will look it’s usage with a simple project. Final project structure will look like below image.


Configuration Files

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="" xmlns="" xsi:schemaLocation="" id="WebApp_ID" version="3.0">




Deployment descriptor is configured to use Struts 2 framework.

<project xmlns="" xmlns:xsi=""

The web application is configured as maven project where we have added struts2-core dependency.

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

	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	<!-- constant to define result path locations to project root directory -->
	<constant name="struts.convention.result.path" value="/"></constant>

	<package name="user" namespace="/" extends="struts-default">
		<action name="update">
		<action name="UpdateUser" class="com.journaldev.struts2.actions.UpdateUserAction">
			<interceptor-ref name="token"></interceptor-ref>
			OR <interceptor-ref name="tokenSession"></interceptor-ref>
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<result name="success">/update_success.jsp</result>
			<result name="input">/update.jsp</result>
			<result name="invalid.token">/invalid_token.jsp</result>

  • We can use either token interceptor or tokenSession interceptor with any action.
  • If token interceptor identifies the request as duplicate, then it returns the result invalid.token, that’s why we have a result configured for this.
  • If form field validation fails then input result is returned where we are returning the same page from where we get the request.

We will look into the complete flow once we have seen the implementation and application behavior with duplicate request.

Action Class

package com.journaldev.struts2.actions;

import java.util.Date;

import com.opensymphony.xwork2.ActionSupport;

public class UpdateUserAction extends ActionSupport {

	public String execute() {
		System.out.println("Update Request Arrived to Action Class");
		//setting update time in action class
		setUpdateTime(new Date());
		return SUCCESS;

	public void validate(){
			addActionError("Name can't be empty");
			addActionError("Address can't be empty");

	//java bean variables
	private String name;
	private String address;
	private Date updateTime;
	public String getName() {
		return name;

	public void setName(String name) { = name;

	public String getAddress() {
		return address;

	public void setAddress(String address) {
		this.address = address;

	public Date getUpdateTime() {
		return updateTime;

	public void setUpdateTime(Date updateTime) {
		this.updateTime = updateTime;

	private boolean isEmpty(String str) {

		return str == null ? true:(str.equals("") ? true:false);


A simple action class with basic form fields validation and some java bean properties. Notice that update time is set by action class, it has been added to show the application behavior when we use tokenSession interceptor.

JSP Pages

<%@ page language="java" contentType="text/html; charset=US-ASCII"
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Update User Request Page</title>
<s:if test="hasActionErrors()">
<s:form action="UpdateUser">
<s:textfield name="name" label="User Name"></s:textfield>
<s:textfield name="address" label="Address"></s:textfield>
<s:submit name="submit" value="Update"></s:submit>
<%-- add token to JSP to be used by Token interceptor --%>
<s:token />

The entry point of the application from where user will submit form to update some information. We are using actionerror tag to show any validation errors added by the application. The most important point to note is s:token tag that will be used by token interceptors in making sure duplicate requests are not getting processed.

<%@ page language="java" contentType="text/html; charset=US-ASCII"
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Update User Success Page</title>
<h3>User information updated successfully.</h3>

Name: <s:property value="name"/><br>
Address: <s:property value="address"/><br>
Update Time: <s:date name="updateTime"/><br>

<h4>Thank You!</h4>

Simple JSP page showing action class java bean properties.

<%@ page language="java" contentType="text/html; charset=US-ASCII"
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Update Duplicate Request Page</title>
<h3>User information is not updated, duplicate request detected.</h3>
<h4>Possible Reasons are:</h4>
	<li>Back button usage to submit form again</li>
	<li>Double click on Submit button</li>
	<li>Using "Reload" Option in browser</li>
<s:if test="hasActionErrors()">

Simple JSP page showing different methods that can cause multiple form submissions, notice the actionerror tag usage.

Now when we will run our application, we will see following pages as response in the same order.





If you will look into the source of input page, you will see that Struts2 API has converted token tag to following HTML snippet.

<input type="hidden" name="" value="token" />
<input type="hidden" name="token" value="HGWQI7ZGP7KFGJLDPNTSFHLUX5RF26IK" />

Also you will notice following logs snippet.

Update Request Arrived to Action Class
WARNING: Form token HGWQI7ZGP7KFGJLDPNTSFHLUX5RF26IK does not match the session token null.

Notice that duplicate request doesn’t even reach to action class and token interceptor returns the invalid.token page as response.

If you will use tokenSession interceptor, you will notice that it returns the same response as the first request. You can confirm this by going back and edit form fields and then submitting form again. The response update time and field values will be old values as sent in the first request.

Now let’s see how token interceptor works to handle multiple form submissions.

  1. When a request is made to the update action, Struts2 tags API generates a unique token and set it to the session. The same token is sent in the HTML response as hidden field.
  2. When the form is submitted with token, it is intercepted by token interceptor where it tries to fetch the token from the session and validate that it’s same as the token received in the request form. If token is found in session and validated then the request is forwarded to the next interceptor in the chain. Token interceptor also removes the token from the session.
  3. When the same form is submitted again, token interceptor will not find it in the session. So it will add an action error message and return invalid.token result as response. You can see this message in above image for invalid_token.jsp response. This way token interceptor make sure that a form with token is processed only once by the action.
  4. If we use tokenSession interceptor, rather than returning invalid token response, it tries to return the same response as the returned by the first action with same token. This implementation is done in the TokenSessionStoreInterceptor class that saves the response for each token in the session.
  5. We can override the action error message sent by token interceptor through i18n support with key as “struts.messages.invalid.token”.

Thats all for the usage of token interceptor to handle multiple form submission problem in web application. Download the application from below link and play around with it for better understanding.

About Pankaj

If you have come this far, it means that you liked what you are reading. Why not reach little more and connect with me directly on Google Plus, Facebook or Twitter. I would love to hear your thoughts and opinions on my articles directly.

Recently I started creating video tutorials too, so do check out my videos on Youtube.

Some of the video tutorials on Udemy I would recommend are;

Join our email newsletter to get promo codes for almost 90% discount on these courses, and yes you will get a lot of free eBooks too, absolutely Free.

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe to JournalDev Newsletter
Get the FREE access to JournalDev Newsletter and Free PDF eBooks
*No Spam Guaranteed. By entering your email address, you agree also subscribing to our newsletter.
Oops! - Something went wrong.