I'm going to chime in on this for a moment. I've always thought the best strategy for handling double submits (assuming you can detect them) is to essentially ignore them. If possible, if you detect a double submit, then bypass the processing logic and either ignore the request, or forward to the page that would have resulted from the original submit (I'm not sure which sub-strategy is better).
Will this functionality you're adding allow this detection and processing? > -----Original Message----- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] > > Author: rich > Date: Mon Jan 3 13:42:54 2005 > New Revision: 124028 > > URL: http://svn.apache.org/viewcvs?view=rev&rev=124028 > Log: > First cut at annotation/tag support for double-submit > prevention. Currently, the feature is simply this: > > ��� @Jpf.Action(preventDoubleSubmit=true,...) > ������������� -or- > ��� @Jpf.SimpleAction(preventDoubleSubmit=true,...) > > If you use netui:form, netui:button (with an 'action'), > netui:anchor, or netui:imageAnchor in conjunction with a > 'preventDoubleSubmit=true' action, you will get a > DoubleSubmitException if you click two or more times on the > same link/button. > > DRT: netui (WinXP) > BB: self (linux) > > > Added: > > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/DoubleSubmitException.java > - copied, changed from r124020, > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/DoubleFormPostException.java > > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/ > > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/Controller.jpf (contents, props changed) > > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/caughtit.jsp (contents, props changed) > > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/index.jsp (contents, props changed) > > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/submitted.jsp (contents, props changed) > Removed: > > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/DoubleFormPostException.java > Modified: > > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/JpfLanguageConstants.java > > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/genmodel/GenActionModel.java > > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/ActionGrammar.java > > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/SimpleActionGrammar.java > > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/model/ActionModel.java > > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/PageFlowRequestProcessor.java > > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/annotations/Jpf.java > > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/config/PageFlowActionMapping.java > > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/AnchorBase.java > > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Button.java > > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Form.java > > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/internal/PageFlowTagUtils.java > > incubator/beehive/trunk/netui/src/util/org/apache/beehive/netu > i/util/netui.properties > > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/WEB-INF > /tiles-defs.xml > > Modified: > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/JpfLanguageConstants.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/compiler/org/apache/beehive/netui/compiler/JpfLanguageConsta > nts.java?view=diff&rev=124028&p1=incubator/beehive/trunk/netui > /src/compiler/org/apache/beehive/netui/compiler/JpfLanguageCon > stants.java&r1=124027&p2=incubator/beehive/trunk/netui/src/com > piler/org/apache/beehive/netui/compiler/JpfLanguageConstants.j > ava&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/JpfLanguageConstants.java (original) > +++ > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/JpfLanguageConstants.java Mon Jan 3 13:42:54 2005 > @@ -161,6 +161,7 @@ > public static final String RAISE_ACTIONS_ATTR = "raiseActions"; > public static final String MULTIPART_HANDLER_ATTR = > "multipartHandler"; > public static final String SHARED_FLOW_REFS_ATTR = > "sharedFlowRefs"; > + public static final String PREVENT_DOUBLE_SUBMIT_ATTR = > + "preventDoubleSubmit"; > > public static final String MIN_INT_ATTR = "minInt"; > public static final String MAX_INT_ATTR = "maxInt"; > > Modified: > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/genmodel/GenActionModel.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/compiler/org/apache/beehive/netui/compiler/genmodel/GenActio > nModel.java?view=diff&rev=124028&p1=incubator/beehive/trunk/ne > tui/src/compiler/org/apache/beehive/netui/compiler/genmodel/Ge > nActionModel.java&r1=124027&p2=incubator/beehive/trunk/netui/s > rc/compiler/org/apache/beehive/netui/compiler/genmodel/GenActi > onModel.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/genmodel/GenActionModel.java (original) > +++ > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/genmodel/GenActionModel.java Mon Jan 3 13:42:54 2005 > @@ -72,6 +72,12 @@ > setLoginRequired( loginRequired ); > > // > + // prevent-double-submit > + // > + Boolean preventDoubleSubmit = > CompilerUtils.getBoolean( annotation, > PREVENT_DOUBLE_SUBMIT_ATTR, false ); > + setPreventDoubleSubmit( preventDoubleSubmit ); > + > + // > // readOnly > // > Boolean readOnly = CompilerUtils.getBoolean( > annotation, READONLY_ATTR, true ); > > Modified: > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/ActionGrammar.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/compiler/org/apache/beehive/netui/compiler/grammar/ActionGra > mmar.java?view=diff&rev=124028&p1=incubator/beehive/trunk/netu > i/src/compiler/org/apache/beehive/netui/compiler/grammar/Actio > nGrammar.java&r1=124027&p2=incubator/beehive/trunk/netui/src/c > ompiler/org/apache/beehive/netui/compiler/grammar/ActionGramma > r.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/ActionGrammar.java (original) > +++ > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/ActionGrammar.java Mon Jan 3 13:42:54 2005 > @@ -17,7 +17,6 @@ > */ > package org.apache.beehive.netui.compiler.grammar; > > -import org.apache.beehive.netui.compiler.AnnotationGrammar; > import org.apache.beehive.netui.compiler.RuntimeVersionChecker; > import org.apache.beehive.netui.compiler.AnnotationMemberType; > import org.apache.beehive.netui.compiler.FlowControllerInfo; > @@ -40,6 +39,7 @@ > addMemberType( READONLY_ATTR, new > AnnotationMemberType( VERSION_8_SP2_STRING, this ) ); > addMemberType( USE_FORM_BEAN_ATTR, > new WritableFieldType( > OBJECT_CLASS_NAME, USE_FORM_BEAN_ATTR, VERSION_8_SP2_STRING, this ) ); > + addMemberType( PREVENT_DOUBLE_SUBMIT_ATTR, new > + AnnotationMemberType( null, this ) ); > > addMemberArrayGrammar( FORWARDS_ATTR, new > ForwardGrammar( env, diags, null, rvc, fcInfo ) ); > addMemberArrayGrammar( CATCHES_ATTR, new > CatchGrammar( env, diags, null, rvc, ACTION_TAG_NAME, fcInfo ) ); > > Modified: > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/SimpleActionGrammar.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/compiler/org/apache/beehive/netui/compiler/grammar/SimpleAct > ionGrammar.java?view=diff&rev=124028&p1=incubator/beehive/trun > k/netui/src/compiler/org/apache/beehive/netui/compiler/grammar > /SimpleActionGrammar.java&r1=124027&p2=incubator/beehive/trunk > /netui/src/compiler/org/apache/beehive/netui/compiler/grammar/ > SimpleActionGrammar.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/SimpleActionGrammar.java (original) > +++ > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/grammar/SimpleActionGrammar.java Mon Jan > 3 13:42:54 2005 > @@ -58,6 +58,7 @@ > addMemberType( TILES_DEFINITION_ATTR, new > AnnotationMemberType( null, this ) ); > addMemberType( REDIRECT_ATTR, new > AnnotationMemberType( null , this ) ); > addMemberType( EXTERNAL_REDIRECT_ATTR, new > AbsolutePathType( null , this ) ); > + addMemberType( PREVENT_DOUBLE_SUBMIT_ATTR, new > + AnnotationMemberType( null, this ) ); > > addMemberArrayGrammar( CONDITIONAL_FORWARDS_ATTR, > new > SimpleActionForwardGrammar( env, diags, null, rvc, fcInfo ) ); > > Modified: > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/model/ActionModel.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/compiler/org/apache/beehive/netui/compiler/model/ActionModel > .java?view=diff&rev=124028&p1=incubator/beehive/trunk/netui/sr > c/compiler/org/apache/beehive/netui/compiler/model/ActionModel > .java&r1=124027&p2=incubator/beehive/trunk/netui/src/compiler/ > org/apache/beehive/netui/compiler/model/ActionModel.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/model/ActionModel.java (original) > +++ > incubator/beehive/trunk/netui/src/compiler/org/apache/beehive/ > netui/compiler/model/ActionModel.java Mon Jan 3 13:42:54 2005 > @@ -67,6 +67,7 @@ > private boolean _isOverloaded; > private boolean _readonly; > private boolean _isSimpleAction = false; > + private boolean _preventDoubleSubmit = false; > private String _formMember; // pageflow-scoped form > private String _formClass; // applicable for > non-ActionForm-derived types > private Map< String, String > _conditionalForwards; > @@ -115,6 +116,7 @@ > _formClass = src._formClass; > _roles = src._roles; > _loginRequired = src._loginRequired; > + _preventDoubleSubmit = src._preventDoubleSubmit; > _isSimpleAction = src._isSimpleAction; > _isOverloaded = src._isOverloaded; > _readonly = src._readonly; > @@ -222,6 +224,7 @@ > if ( _formMember != null ) addSetProperty( xb, > "formMember", _formMember ); > if ( _formClass != null ) addSetProperty( xb, > "formClass", _formClass ); > if ( _loginRequired ) addSetProperty( xb, > "loginRequired", _loginRequired ); > + if ( _preventDoubleSubmit ) addSetProperty( xb, > + "preventDoubleSubmit", _preventDoubleSubmit ); > if ( _isOverloaded ) addSetProperty( xb, > "overloaded", _isOverloaded ); > if ( _readonly ) addSetProperty( xb, "readonly", _readonly ); > if ( _isSimpleAction ) addSetProperty( xb, > "simpleAction", _isSimpleAction ); @@ -464,14 +467,14 @@ > _roles = roles; > } > > - public boolean isLoginRequired() > - { > - return _loginRequired; > - } > - > public void setLoginRequired( boolean loginRequired ) > { > _loginRequired = loginRequired; > + } > + > + public void setPreventDoubleSubmit( boolean preventDoubleSubmit ) > + { > + _preventDoubleSubmit = preventDoubleSubmit; > } > > public boolean isSimpleAction() > > Deleted: > /incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive > /netui/pageflow/DoubleFormPostException.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/pageflow/org/apache/beehive/netui/pageflow/DoubleFormPostExc > eption.java?view=auto&rev=124027 > ============================================================== > ================ > > Copied: > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/DoubleSubmitException.java (from r124020, > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/DoubleFormPostException.java) > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/pageflow/org/apache/beehive/netui/pageflow/DoubleSubmitExcep > tion.java?view=diff&rev=124028&p1=incubator/beehive/trunk/netu > i/src/pageflow/org/apache/beehive/netui/pageflow/DoubleFormPos > tException.java&r1=124020&p2=incubator/beehive/trunk/netui/src > /pageflow/org/apache/beehive/netui/pageflow/DoubleSubmitExcept > ion.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/DoubleFormPostException.java (original) > +++ > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/DoubleSubmitException.java Mon Jan 3 13:42:54 2005 > @@ -20,11 +20,11 @@ > import javax.servlet.http.HttpServletResponse; > import java.io.IOException; > > -public class DoubleFormPostException > +public class DoubleSubmitException > extends PageFlowException > implements ResponseErrorCodeSender > { > - DoubleFormPostException( String actionName, FlowController fc ) > + DoubleSubmitException( String actionName, FlowController fc ) > { > super( actionName, fc ); > } > @@ -36,7 +36,7 @@ > > protected String[] getMessageParts() > { > - return new String[]{ "A double-post occurred for > action ", " in page flow ", "." }; > + return new String[]{ "A double-submit occurred for > action ", " > + in page flow ", "." }; > } > > public void sendResponseErrorCode( HttpServletResponse > response ) throws IOException > > Modified: > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/PageFlowRequestProcessor.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestPr > ocessor.java?view=diff&rev=124028&p1=incubator/beehive/trunk/n > etui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRe > questProcessor.java&r1=124027&p2=incubator/beehive/trunk/netui > /src/pageflow/org/apache/beehive/netui/pageflow/PageFlowReques > tProcessor.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/PageFlowRequestProcessor.java (original) > +++ > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/PageFlowRequestProcessor.java Mon Jan 3 13:42:54 2005 > @@ -930,16 +930,13 @@ > ActionMapping > mapping, String actionPath ) > throws IOException > { > - // > - // TODO: We haven't yet hooked up the support for > marking an action as preventDoublePost=true. > - // > - if ( false ) > + if ( mapping instanceof PageFlowActionMapping && ( ( > + PageFlowActionMapping ) mapping ).isPreventDoubleSubmit() ) > { > if ( ! > TokenProcessor.getInstance().isTokenValid( request, true ) ) > { > FlowController currentFC = > RequestValues.getCurrentFlowController( request ); > String actionName = > InternalUtils.getActionName( mapping ); > - DoubleFormPostException ex = new > DoubleFormPostException( actionName, currentFC ); > + DoubleSubmitException ex = new > DoubleSubmitException( > + actionName, currentFC ); > > if ( currentFC != null ) > { > > Modified: > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/annotations/Jpf.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/pageflow/org/apache/beehive/netui/pageflow/annotations/Jpf.j > ava?view=diff&rev=124028&p1=incubator/beehive/trunk/netui/src/ > pageflow/org/apache/beehive/netui/pageflow/annotations/Jpf.jav > a&r1=124027&p2=incubator/beehive/trunk/netui/src/pageflow/org/ > apache/beehive/netui/pageflow/annotations/Jpf.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/annotations/Jpf.java (original) > +++ > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/annotations/Jpf.java Mon Jan 3 13:42:54 2005 > @@ -186,7 +186,7 @@ > * was jpf:action > */ > @Target( METHOD ) > - @Retention( RUNTIME ) > + @Retention( RUNTIME ) > public @interface Action > { > /** > @@ -228,6 +228,12 @@ > * forward used when validation fails > */ > Forward validationErrorForward() default > @Jpf.Forward( name="" ); > + > + /** > + * Prevent multiple submits to this action. If > multiple submits occur, a > + * [EMAIL PROTECTED] > org.apache.beehive.netui.pageflow.DoubleSubmitException} is thrown. > + */ > + boolean preventDoubleSubmit() default false; > } > > @Target( ANNOTATION_TYPE ) > @@ -314,6 +320,12 @@ > String outputFormBean() default ""; > boolean redirect() default false; // optional > boolean externalRedirect() default false; // optional > + > + /** > + * Prevent multiple submits to this action. If > multiple submits occur, a > + * [EMAIL PROTECTED] > org.apache.beehive.netui.pageflow.DoubleSubmitException} is thrown. > + */ > + boolean preventDoubleSubmit() default false; > } > > /** > > Modified: > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/config/PageFlowActionMapping.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/pageflow/org/apache/beehive/netui/pageflow/config/PageFlowAc > tionMapping.java?view=diff&rev=124028&p1=incubator/beehive/tru > nk/netui/src/pageflow/org/apache/beehive/netui/pageflow/config > /PageFlowActionMapping.java&r1=124027&p2=incubator/beehive/tru > nk/netui/src/pageflow/org/apache/beehive/netui/pageflow/config > /PageFlowActionMapping.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/config/PageFlowActionMapping.java (original) > +++ > incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/ > netui/pageflow/config/PageFlowActionMapping.java Mon Jan > 3 13:42:54 2005 > @@ -31,6 +31,7 @@ > { > private String _unqualifiedActionPath; > private boolean _loginRequired = false; > + private boolean _preventDoubleSubmit = false; > private boolean _simpleAction = false; > private boolean _isOverloaded = false; > private String _formMember; > @@ -70,6 +71,16 @@ > public void setLoginRequired( boolean loginRequired ) > { > _loginRequired = loginRequired; > + } > + > + public boolean isPreventDoubleSubmit() > + { > + return _preventDoubleSubmit; > + } > + > + public void setPreventDoubleSubmit( boolean preventDoubleSubmit ) > + { > + _preventDoubleSubmit = preventDoubleSubmit; > } > > public boolean isSimpleAction() > > Modified: > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/AnchorBase.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/tags-html/org/apache/beehive/netui/tags/html/AnchorBase.java > ?view=diff&rev=124028&p1=incubator/beehive/trunk/netui/src/tag > s-html/org/apache/beehive/netui/tags/html/AnchorBase.java&r1=1 > 24027&p2=incubator/beehive/trunk/netui/src/tags-html/org/apach > e/beehive/netui/tags/html/AnchorBase.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/AnchorBase.java (original) > +++ > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/AnchorBase.java Mon Jan 3 13:42:54 2005 > @@ -10,6 +10,7 @@ > import org.apache.beehive.netui.util.Bundle; > import org.apache.beehive.netui.util.ParamHelper; > import org.apache.beehive.netui.util.logging.Logger; > +import org.apache.struts.taglib.html.Constants; > > import javax.servlet.ServletContext; > import javax.servlet.ServletRequest; > @@ -327,18 +328,33 @@ > return createPageAnchor(request, trb); > } > > - // report that action is not an action > - if ((_action != null) && > (!PageFlowTagUtils.isAction(request, _action))) { > - String s = null; > - if (_action.equals("")) { > - s = Bundle.getString("Tags_NullBadAction", null); > + if (_action != null) { > + // report that action is not an action > + if (!PageFlowTagUtils.isAction(request, _action)) { > + String s = null; > + if (_action.equals("")) { > + s = Bundle.getString("Tags_NullBadAction", null); > + } > + else { > + s = Bundle.getString("Tags_BadAction", _action); > + } > + registerTagError(s, null); > } > else { > - s = Bundle.getString("Tags_BadAction", _action); > + // > + // If the action we're submitting to is > checking for double-submits, save a token in the session. > + // This will be written out as a param > (below), and will be checked in PageFlowRequestProcessor. > + // > + String token = > PageFlowTagUtils.getToken(request, _action); > + if (token != null) { > + if (_params == null) { > + _params = new HashMap(); > + } > + _params.put(Constants.TOKEN_KEY, token); > + } > } > - registerTagError(s, null); > } > - > + > // we assume that tagId will over have override id if both > // are defined. > if (tagId != null) { > > Modified: > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Button.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/tags-html/org/apache/beehive/netui/tags/html/Button.java?vie > w=diff&rev=124028&p1=incubator/beehive/trunk/netui/src/tags-ht ml/org/apache/beehive/netui/tags/html/Button.jav> a&r1=124027&p2=incubator/beehive/trunk/netui/src/tags-html/org /apache/beehive/netui/tags/html/Button.java&r2=> 124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Button.java (original) > +++ > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Button.java Mon Jan 3 13:42:54 2005 > @@ -28,6 +28,7 @@ > import org.apache.beehive.netui.tags.rendering.WriteRenderAppender; > import org.apache.beehive.netui.util.Bundle; > import org.apache.beehive.netui.util.ParamHelper; > +import org.apache.struts.taglib.html.Constants; > > import javax.servlet.http.HttpServletRequest; > import javax.servlet.http.HttpServletResponse; > @@ -233,6 +234,18 @@ > if (_action != null) { > boolean isAction = > PageFlowTagUtils.isAction(request, _action); > if (isAction) { > + // > + // If the action we're submitting to is > checking for double-submits, save a token in the session. > + // This will be written out as a param > (below), and will be checked in PageFlowRequestProcessor. > + // > + String token = > PageFlowTagUtils.getToken(request, _action); > + if (token != null) { > + if (_params == null) { > + _params = new HashMap(); > + } > + _params.put(Constants.TOKEN_KEY, token); > + } > + > String overrideAction = ACTION_OVERRIDE + _action; > overrideAction = > HtmlUtils.addParams(overrideAction, _params, > response.getCharacterEncoding()); > String buttonOutput = > URLRewriterService.rewriteName(pageContext.getServletContext(), > > Modified: > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Form.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/tags-html/org/apache/beehive/netui/tags/html/Form.java?view= > diff&rev=124028&p1=incubator/beehive/trunk/netui/src/tags-html /org/apache/beehive/netui/tags/html/Form.java&r1> =124027&p2=incubator/beehive/trunk/netui/src/tags-html/org/apa > che/beehive/netui/tags/html/Form.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Form.java (original) > +++ > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/html/Form.java Mon Jan 3 13:42:54 2005 > @@ -20,6 +20,7 @@ > import org.apache.beehive.netui.core.urls.MutableURI; > import org.apache.beehive.netui.core.urls.URLRewriterService; > import org.apache.beehive.netui.pageflow.*; > +import > org.apache.beehive.netui.pageflow.config.PageFlowActionMapping; > import org.apache.beehive.netui.pageflow.internal.ContextCache; > import org.apache.beehive.netui.pageflow.internal.InternalUtils; > import org.apache.beehive.netui.pageflow.internal.InternalConstants; > @@ -30,6 +31,7 @@ > import org.apache.beehive.netui.util.ParamHelper; > import org.apache.beehive.netui.util.logging.Logger; > import org.apache.struts.Globals; > +import org.apache.struts.util.TokenProcessor; > import org.apache.struts.action.ActionForm; > import org.apache.struts.action.ActionMapping; > import org.apache.struts.action.ActionServlet; > @@ -723,11 +725,18 @@ > TagRenderingBase br = > TagRenderingBase.Factory.getRendering(TagRenderingBase.FORM_TA > G, request); > br.doStartTag(writer, _state); > > + // > + // If the action we're submitting to is checking for > double-submits, save a token in the session. > + // This will be written out as a hidden param > (below), and will be checked in PageFlowRequestProcessor. > + // > + String token = PageFlowTagUtils.getToken(request, _mapping); > + > // Add a transaction token (if present in our session) > HttpSession session = pageContext.getSession(); > if (session != null) { > - String token = > - (String) > session.getAttribute(Globals.TRANSACTION_TOKEN_KEY); > + if (token != null) { > + token = (String) > session.getAttribute(Globals.TRANSACTION_TOKEN_KEY); > + } > if (token != null) { > writeHiddenParam(Constants.TOKEN_KEY, token, > writer, request, true); > } > > Modified: > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/internal/PageFlowTagUtils.java > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/tags-html/org/apache/beehive/netui/tags/internal/PageFlowTag > Utils.java?view=diff&rev=124028&p1=incubator/beehive/trunk/net > ui/src/tags-html/org/apache/beehive/netui/tags/internal/PageFl > owTagUtils.java&r1=124027&p2=incubator/beehive/trunk/netui/src > /tags-html/org/apache/beehive/netui/tags/internal/PageFlowTagU > tils.java&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/internal/PageFlowTagUtils.java (original) > +++ > incubator/beehive/trunk/netui/src/tags-html/org/apache/beehive > /netui/tags/internal/PageFlowTagUtils.java Mon Jan 3 13:42:54 2005 > @@ -26,10 +26,13 @@ > import org.apache.beehive.netui.pageflow.PageFlowUtils; > import org.apache.beehive.netui.pageflow.SecurityProtocol; > import org.apache.beehive.netui.pageflow.SharedFlowController; > +import > org.apache.beehive.netui.pageflow.config.PageFlowActionMapping; > import org.apache.beehive.netui.pageflow.internal.InternalUtils; > import org.apache.beehive.netui.pageflow.internal.InternalConstants; > import org.apache.struts.action.ActionMapping; > import org.apache.struts.config.ActionConfig; > +import org.apache.struts.util.TokenProcessor; > +import org.apache.struts.Globals; > > import java.net.URISyntaxException; > import java.util.Map; > @@ -38,6 +41,7 @@ > import javax.servlet.ServletRequest; > import javax.servlet.http.HttpServletResponse; > import javax.servlet.http.HttpServletRequest; > +import javax.servlet.http.HttpSession; > > /** > * This is a utility class for the beehive tags with > routines for helping with URL rewriting. @@ -178,6 +182,44 @@ > return true; > } > > + /** > + * Get or generate a token used to prevent double > submits to an action. The token is stored in the session, > + * and checked (and removed) when processing an action > with the <code>preventDoubleSubmit</code> attribute > + * set to <code>true</code>. > + */ > + public static String getToken( HttpServletRequest > request, String action ) > + { > + FlowController flowController = > + InternalUtils.getCurrentPageFlow( request, false ); > + > + if ( flowController != null ) > + { > + MappingAndController mac = getActionMapping( > request, flowController, action ); > + if ( mac != null ) return getToken( request, > mac.mapping ); > + } > + > + return null; > + } > + > + /** > + * Get or generate a token used to prevent double > submits to an action. The token is stored in the session, > + * and checked (and removed) when processing an action > with the <code>preventDoubleSubmit</code> attribute > + * set to <code>true</code>. > + */ > + public static String getToken( HttpServletRequest > request, ActionMapping mapping ) > + { > + if ( mapping instanceof PageFlowActionMapping && ( ( > PageFlowActionMapping ) mapping ).isPreventDoubleSubmit() ) > + { > + HttpSession session = request.getSession(); > + String token = ( String ) session.getAttribute( > Globals.TRANSACTION_TOKEN_KEY ); > + if ( token != null ) return token; > + token = > TokenProcessor.getInstance().generateToken( request ); > + request.getSession().setAttribute( > Globals.TRANSACTION_TOKEN_KEY, token ); > + return token; > + } > + > + return null; > + } > + > public static class MappingAndController > { > public ActionMapping mapping; > @@ -198,12 +240,32 @@ > > if ( dot == -1 ) > { > + // > + // It's an action in the current page flow, > or in the (deprecated) Global.app. > + // > if ( action.charAt( 0 ) != '/' ) action = > '/' + action; > mapping = > flowController.getModuleConfig().findActionConfig( action ); > fc = flowController; > + > + // > + // If we don't find it in the current page > flow, look in Global.app. > + // > + if ( mapping == null ) > + { > + FlowController globalApp = > + PageFlowUtils.getSharedFlow( > InternalConstants.GLOBALAPP_CLASSNAME, request ); > + if ( globalApp != null ) > + { > + mapping = > globalApp.getModuleConfig().findActionConfig( action ); > + fc = globalApp; > + } > + } > } > else if ( dot < action.length() - 1 ) > { > + // > + // It's an action in a shared flow. > + // > String sharedFlowName = action.substring( 0, dot ); > if ( sharedFlowName.length() > 0 && > sharedFlowName.charAt( 0 ) == '/' ) > { > > Modified: > incubator/beehive/trunk/netui/src/util/org/apache/beehive/netu > i/util/netui.properties > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/sr > c/util/org/apache/beehive/netui/util/netui.properties?view=dif > f&rev=124028&p1=incubator/beehive/trunk/netui/src/util/org/apa > che/beehive/netui/util/netui.properties&r1=124027&p2=incubator /beehive/trunk/netui/src/util/org/apache/beehive> /netui/util/netui.properties&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/src/util/org/apache/beehive/netu > i/util/netui.properties (original) > +++ > incubator/beehive/trunk/netui/src/util/org/apache/beehive/netu > i/util/netui.properties Mon Jan 3 13:42:54 2005 > @@ -452,19 +452,19 @@ > PageFlow_ActionNotFoundException_Message= \ > Unable to find matching action {0} in page flow {1}. > > -PageFlow_DoubleFormPostException_Page= \ > -<html><head><title>Page Flow Error - Double Form > Post</title></head>\n \ > +PageFlow_DoubleSubmitException_Page= \ > +<html><head><title>Page Flow Error - Double Submit</title></head>\n \ > <body>\n \ > -<h1>Page Flow Error - Double Form Post</h1>\n \ > +<h1>Page Flow Error - Submit</h1>\n \ > <table border="1" cellspacing="0">\n \ > <tr><td><b>Page Flow:</b></td><td>{1}</td></tr>\n \ > <tr><td><b>Action:</b></td><td>{0}</td></tr>\n \ </table><br > />\n \ -<span style="color:red">A double-post occurred for > action <b>{0}</b>.</span>\n \ > +<span style="color:red">A double-submit occurred for action > +<b>{0}</b>.</span>\n \ > </body></html>\n > > -PageFlow_DoubleFormPostException_Message= \ > -A double-post occurred for action <b>{0}</b> in page flow {1}. > +PageFlow_DoubleSubmitException_Message= \ > +A double-submit occurred for action <b>{0}</b> in page flow {1}. > > PageFlow_UnhandledException_Page = \ > <html><head><title>Page Flow Unhandled Exception</title></head>\n \ > > Modified: > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/WEB-INF > /tiles-defs.xml > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/te > st/webapps/drt/coreWeb/WEB-INF/tiles-defs.xml?view=diff&rev=12 > 4028&p1=incubator/beehive/trunk/netui/test/webapps/drt/coreWeb > /WEB-INF/tiles-defs.xml&r1=124027&p2=incubator/beehive/trunk/n > etui/test/webapps/drt/coreWeb/WEB-INF/tiles-defs.xml&r2=124028 > ============================================================== > ================ > --- > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/WEB-INF > /tiles-defs.xml (original) > +++ > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/WEB-INF > /tiles-defs.xml Mon Jan 3 13:42:54 2005 > @@ -2,7 +2,7 @@ > > <!DOCTYPE tiles-definitions PUBLIC > "-//Apache Software Foundation//DTD Tiles Configuration//EN" > - "http://jakarta.apache.org/struts/dtds/tiles-config.dtd"> > + "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd"> > > > <!-- > > Added: > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/Controller.jpf > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/te > st/webapps/drt/coreWeb/miniTests/preventDoubleSubmit/Controlle > r.jpf?view=auto&rev=124028 > ============================================================== > ================ > --- (empty file) > +++ > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/Controller.jpf Mon Jan 3 13:42:54 2005 > @@ -0,0 +1,27 @@ > +package miniTests.preventDoubleSubmit; > + > +import org.apache.beehive.netui.pageflow.*; > +import org.apache.beehive.netui.pageflow.annotations.*; > + > [EMAIL PROTECTED]( > + simpleActions={ > + @Jpf.SimpleAction(name="begin", path="index.jsp"), > + @Jpf.SimpleAction(name="anchorSubmit", > preventDoubleSubmit=true, path="submitted.jsp") > + }, > + catches={ > + @Jpf.Catch(type=DoubleSubmitException.class, > path="caughtit.jsp") > + } > +) > +public class Controller extends PageFlowController > +{ > + @Jpf.Action( > + preventDoubleSubmit=true, > + forwards={ > + @Jpf.Forward(name="submitted", path="submitted.jsp") > + } > + ) > + public Forward formSubmit() > + { > + return new Forward("submitted"); > + } > +} > > Added: > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/caughtit.jsp > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/te > st/webapps/drt/coreWeb/miniTests/preventDoubleSubmit/caughtit. > jsp?view=auto&rev=124028 > ============================================================== > ================ > --- (empty file) > +++ > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/caughtit.jsp Mon Jan 3 13:42:54 2005 > @@ -0,0 +1,19 @@ > +<%@ page language="java" contentType="text/html;charset=UTF-8"%> > +<%@ taglib prefix="netui" > +uri="http://beehive.apache.org/netui/tags-html-1.0"%> > +<%@ taglib prefix="netui-data" > uri="http://beehive.apache.org/netui/tags-databinding-1.0"%> > +<%@ taglib prefix="netui-template" > uri="http://beehive.apache.org/netui/tags-template-1.0"%> > + > + > +<netui:html> > + <head> > + <netui:base/> > + </head> > + <netui:body> > + OK -- caught DoubleSubmitException > + <br/> > + <netui:anchor action="begin">start over</netui:anchor> > + </netui:body> > +</netui:html> > + > + > + > > Added: > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/index.jsp > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/te > st/webapps/drt/coreWeb/miniTests/preventDoubleSubmit/index.jsp > ?view=auto&rev=124028 > ============================================================== > ================ > --- (empty file) > +++ > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/index.jsp Mon Jan 3 13:42:54 2005 > @@ -0,0 +1,27 @@ > +<%@ page language="java" contentType="text/html;charset=UTF-8"%> > +<%@ taglib prefix="netui" > +uri="http://beehive.apache.org/netui/tags-html-1.0"%> > +<%@ taglib prefix="netui-data" > uri="http://beehive.apache.org/netui/tags-databinding-1.0"%> > +<%@ taglib prefix="netui-template" > uri="http://beehive.apache.org/netui/tags-template-1.0"%> > + > + > +<netui:html> > + <head> > + <netui:base/> > + </head> > + <netui:body> > + <netui:form action="formSubmit"> > + <netui:button value="netui:form (prevent double post)"/> > + </netui:form> > + <netui:form action="begin"> > + <netui:button action="formSubmit" > value="netui:button (prevent double post)"/> > + </netui:form> > + <netui:anchor action="anchorSubmit">netui:anchor > (prevent double post)</netui:anchor> > + <br/> > + <br/> > + <netui:imageAnchor action="anchorSubmit" > src="../../resources/images/goButton.jpg">netui:imageAnchor > (prevent double post)</netui:imageAnchor> > + <br/> > + </netui:body> > +</netui:html> > + > + > + > > Added: > incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes > ts/preventDoubleSubmit/submitted.jsp > Url: > http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/te st/webapps/drt/coreWeb/miniTests/preventDoubleSubmit/submitted.jsp?view=auto&rev=124028 ============================================================================== --- (empty file) +++ incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTests/preventDoubleSubmit/submitted.jsp Mon Jan 3 13:42:54 2005 @@ -0,0 +1,17 @@ +<%@ page language="java" contentType="text/html;charset=UTF-8"%> +<%@ taglib prefix="netui" +uri="http://beehive.apache.org/netui/tags-html-1.0"%> +<%@ taglib prefix="netui-data" uri="http://beehive.apache.org/netui/tags-databinding-1.0"%> +<%@ taglib prefix="netui-template" uri="http://beehive.apache.org/netui/tags-template-1.0"%> + + +<netui:html> + <head> + <netui:base/> + </head> + <netui:body> + OK -- submitted once. Use the back button and submit again. + </netui:body> +</netui:html> + + +
