That seems like a complex solution to the problem which does things in
a filter, where it might be difficult to predict side effects or
override the behaviour in certain circumstances. I'd be more inclined
to implement a unique token solution in a base page class so that I
could overload it in certain pages, if necessary. Simplest solution,
but not entirely error proof, would be to stick a unique token in the
form (I'm not use you can use a session persistent property in the
page, as I don't know when those get written into the session -
possibly only after the page is finished processing). Then, when
processing any form, check the session location for a token, if it
matches, just send back a page saying "don't do that." If it isn't
found, assume that this is the first time you've seen the form and go
ahead and process it. You can add increasing complexity to such a
solution depending on what kind of user experience you want and how
error-proof you want it. The filter trick is cute, since you can
actually serve the same response to multiple requests, but that is
often not necessary and sometimes not even desired and it takes too
much logic out of the core application for my own comfort level.
But disabling a button can be pretty effective against all but an
actually malicious user (does anyone build javascript-free web apps
these days, especially in tapestry?), and a malicious user can
override a unique token all too easily, anyway. If there is a true
security or data integrity concern, you'll have to do something that
is entirely on the server side in order to prevent manipulation by
someone with the smarts to interpret an html file and manually send a
post.
--sam
On 11/15/06, John Menke <[EMAIL PROTECTED]> wrote:
> Is there a non-javascript solution to this problem? I have been
> experimenting with code based on the forum post below. Has anyone
developed
> a solution for Tapestry? I propose some sort of consensus should
> be reached as to what the best method is to handle double submits and a
> patch should be made for Tapestry. Any comments? Ideas?
>
> <quote from Forum Post>
> There is a server-side solution for this problem. Here is the concept:
> Build a way to identify each form from which a request (or multiple
> requests, if the form button is clicked several times) arrives. This
can
be
> done by having a hidden input element included in the form, whose value
is a
> unique number (typically using the time in milliseconds).
>
> Write a filter implementing the javax.servlet.Filter interface, with
the
> following logic in the doFilter() method:
> Synchronize a code block on a session-scoped object. Inside this block,
> check if the form-id received through the current request is same as
the
one
> received previously.
> If different, this is the first request received from the form (i.e.
the
> request originated as a result of the first click). If same, this is a
> subsequent request, generated as a result of multiple clicks.
>
> In the first case, invoke FilterChain.doFilter() by passing a
> ResponseWrapper object instead of the original response object. This
> ResponseWrapper object should be built with a ByteArrayOutputStream
object,
> so that the response content can be extracted as a String. When the
> FilterChain.doFilter() method returns, save the response content and
the
> current form-id in session-scope, for subsequent requests and leave the
> synchronized block.
>
> Then outside the synchronized block, forward all the requests
(including
the
> first one) to a "LoopBackServlet" with the original "request" and
"response"
> objects. The whole purpose of this "LoopBackServlet" is to write the
saved
> response content into the response object.
>
> In this way, when multiple requests arrive from the same form as a
result of
> multiple clicks, we let the first request thread proceed, with a
> response-wrapper and block all the other threads. When the first thread
> returns with the response ready, the response content is stored in
session
> and the same is written to all the blocked threads when they become
> unblocked.
>
> If anybody wants more details, please email me at
[EMAIL PROTECTED], I
can
> send the working code.
>
>
> </quote from Forum Post>
>
> http://forum.java.sun.com/thread.jspa?threadID=665472&start=15&tstart=0
>
>
>
> On 11/15/06, Denis McCarthy <[EMAIL PROTECTED]> wrote:
> >
> > I was looking for a sledgehammer to crack a nut. That's how I
ended up
> > doing it (after spending the day looking for an enterprisey
solution!)
> > Thanks
> > Denis
> >
> > Jesse Kuhnert wrote:
> > > Why don't you just disable the submit buttons in question when they
> > submit?
> > > (set the disabled attribute to true)
> > >
> > > On 11/15/06, Denis McCarthy <[EMAIL PROTECTED]> wrote:
> > >>
> > >> Hi,
> > >> I'm encountering a problem in my app where users are double
submitting
> > a
> > >> form, creating a hibernate exception in the back end where two
> > >> sessions are attempting to update the same collection. I've read
some
> > >> posts about preventing form resubmission by using a unique
token in
the
> > >> form to detect a double submit.
> > >>
> > >> If a double submit is detected, the second and subsequent submits
wait
> > >> until the original one returns and then report the outcome of that
> > >> transaction (if I understand correctly, it's the last submit that
> > issues
> > >> the response to the user, and the first one does the updating).
> > >>
> > >> I'm wondering
> > >> a) is this indeed the right approach to stop users who are
> > >> over-enthusiastic in their button clicking from encountering
errors,
> > and
> > >> b) does anyone have an actual example of code that implements this
> > >> pattern?
> > >> Thanks very much
> > >> Denis Mc.
> > >>
> > >>
---------------------------------------------------------------------
> > >> To unsubscribe, e-mail: [EMAIL PROTECTED]
> > >> For additional commands, e-mail: [EMAIL PROTECTED]
> > >>
> > >>
> > >
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]