OK, good. If you do end up trying it out, let me know if it works the
way you expect.
Thanks,
Rich
Karr, David wrote:
To elaborate, the goal of "ignoring" the double submit is simply to make
the user experience seem as if nothing unusual happened. The result of
a double submit should be the same as a single submit.
Towards that goal, both of the strategies you describe here seem
reasonable.
-----Original Message-----
From: Richard Feit [mailto:[EMAIL PROTECTED]
Sent: Tuesday, January 04, 2005 3:52 PM
To: Beehive Developers
Subject: Re: svn commit: r124028 - in
incubator/beehive/trunk/netui:
src/compiler/org/apache/beehive/netui/compiler
src/compiler/org/apache/beehive/netui/compiler/genmodel
src/compiler/org/apache/beehive/netui/compiler/grammar
src/compiler/org/apache/beehive/netui
I think the feature does allow for the second option, but can you
describe what you mean by "ignoring" the second request?
Currently, I
think that there are a few things that can be done to handle this:
1) Go to the original results page, by specifying the path
explicitly in
a @Jpf.Catch for DoubleSubmitException:
@Jpf.Action(
preventDoubleSubmit=true,
forwards={
@Jpf.Forward(name="success", path="results.jsp")
},
catches={
@Jpf.Catch(type=DoubleSubmitException.class,
path="results.jsp")
}
)
public Forward placeOrder(OrderForm form)
{
...
}
2) If the results page has request-scoped inputs that were
sent from the
action using @Jpf.ActionOutput annotations, you can use the
'navigateTo'
attribute, which lets the framework remember the most recent page as
well as the inputs that were passed to it:
@Jpf.Action(
preventDoubleSubmit=true,
forwards={
@Jpf.Forward(name="success", path="results.jsp")
},
catches={
@Jpf.Catch(type=DoubleSubmitException.class,
navigateTo=Jpf.NavigateTo.currentPage)
}
)
public Forward placeOrder(OrderForm form)
{
...
}
Note that this won't work if the results page is expecting some
other request-(or otherwise-)scoped input that we don't keep track of.
3) Go to an error page. You can either specify a custom one (using
@Jpf.Catch as in #1) or let the DoubleSubmitException bleed
out, to be
handled with a generic error page like other exceptions.
Wherever appropriate, the @Jpf.Catch annotations can be put in more
general places -- at the class level in the @Jpf.Controller
annotation,
or even in a shared flow (referenced in the 'sharedFlows'
attribute on
@Jpf.Controller). Also, I was going to look into some client-side
options, like disabling a button as soon as it's clicked. This might
improve the experience for users who have client-side script enabled.
Let me know what you think...
Thanks,
Rich
Karr, David wrote:
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/submitte
d.jsp?view
=auto&rev=124028
=============================================================
=================
--- (empty file)
+++
incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/miniTes
ts/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>
+
+
+