Monday, January 10, 2011

How to avoid double submit in Struts

How to avoid double submit in Struts

Struts has 3 methods used for the token related activities, saveToken(), isTokenValid() and resetToken().
    saveToken() - generate the token key and save to request/session attribute.
    isTokenValid() - validate submitted token key against the 1 store in request/session.
    resetToken() - reset the token key
------------------------
Step 1:
    You need to save token first and then forward to JSP page for any submission related activity.
    Assuming you wrote "LoadAction" Action class for the same. Call saveToken() in your Action class, 
    It will create and store the token key. Struts will store the generated key in request/session. 
    The key will be: Action.TRANSACTION_TOKEN_KEY. See the below code:
------------------------
public class LoadAction extends Action {
    public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,
                HttpServletResponse response) {   
        ActionForward forward;
        forward=mapping.findForward("FirstPage");    // this is the jsp page where you want to save struts tokens.
        saveToken(request);    
        return forward;
    }
}
------------------------
Step 2:
You can see the token if you do "View Source" on the browser, the token key is stored as a hidden field in 
the jsp page:

//JSP code
<%@ page import="org.apache.struts.action.Action"%>
<%@ page import="org.apache.struts.taglib.html.Constants"%>

<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<html>
    <head> <title> First Page </title> </head>

    <body>
        <form name="MyForm" method="post" action="/dmodi/getForm/submit.do">
            <input type="text" name="name" >
            <input type="hidden" name="<%= Constants.TOKEN_KEY %>"
            value="<%= session.getAttribute(Action.TRANSACTION_TOKEN_KEY) %>" >
            <input type="submit" value="submit">
        </form>
    </body>
</html>
------------------------
Step 3. Your logic
Once the form submitted, invokes isTokenValid() on the action class, it will validate the submitted token 
key(hidden field) with the token key stored previously on request/session. If matches, it will return true.

public class SubmitAction extends Action {
    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, 
            HttpServletResponse response) {

        ActionForward forward=mapping.findForward("submitForm");
        DupSubmitForm frm=(DupSubmitForm)form;
        if(isTokenValid(request)) {
            System.out.println("frm.getName()"+frm.getName());
            resetToken(request);
        }
        else {
            System.out.println("frm.getName()"+frm.getName());
            System.out.println("Duplicate Submission of the form");
        }
        return forward;
    }
} 
------------------------END-------------------------

No comments:

Post a Comment