And where exactly does the "user experience" fit in to all of this cool
server side trickery? I mean, even in a basic swing application I would
disable input on things people aren't allowed to use when I'm doing
something that will potentially take a long time to complete.

The browser is your friend, not a place where scary hacks happen. It's your
UI, embrace it. ;)

On 11/15/06, Nick Westgate <[EMAIL PROTECTED]> wrote:

IMO, disabling a submit with javascript is a hack. The problem is common,
and a natural consequence of using Tapestry to develop a web application.
Tapestry should be taking care of it for us.

In any case, this can be solved in the same way that the old "locked after
a commit()" errors in T3 were. I think T4 (via hivemind?) has fixed that
particular incarnation. (It happened with all kinds of requests, and when
using frames etc.)

Use a filter to queue requests from the same client, or discard new ones:
http://www.onjava.com/pub/a/onjava/2004/03/24/loadcontrol.html

Use a Flow Synchronizer to handle form reposts:
http://www.junlu.com/msg/85270.html

I find the Flow Synchronizer particularly useful, as I put the bean in my
border component and add handling methods to my base page class. Methods
such as a simple isRepost() allow special casing the request - to avoid
repeating a delete, for instance, but allowing other reposts to proceed.

You'll find plenty of posts on the above topics in the list archives.

Cheers,
Nick.


John Menke wrote:
> The filter solution does use a unique token on the form and you can
disable
> the filter by not including the token on a form.  I did have to add
> logic to
> the posted solution to handle errors but even with that code included
the
> code seems to be non-invasive -- all it does is check for form variable
and
> continues normal processing or blocks duplicate requests while "caching"
> the
> response (sounds more complicated than it is)
>
> i do see what you mean about the security concern and someone being able
to
> manipulate a post to get past the filter, trying to think of solutions
to
> this problem
>
> maybe something where the form included a secure key in a hidden
variable
> and having some sort of check which could determine if a key had been
used
> already
>
> if form is secure
> -- check for valid and unique key
> -- if key is valid then process the form and expire the key
> -- don't let another request pass through after key is expired or absent
>
> above solution does require the ability to mark certain forms as secure
on
> the server side.
>
> with security in place i think the filter solution could be a complete
> server side solution.  I know you mentioned possible side effects did
you
> have anything specific in mind?
>
> Bottom line is that there should be a server side solution to this
problem
> in tapestry that is secure and non-invasive.  I encourage others to post
> their ideas in an effort to come to some sort of agreement on best way
to
> accomplish this.
>
> -john
>
>
>
> On 11/15/06, Sam Gendler <[EMAIL PROTECTED]> wrote:
>>
>> 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]
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




--
Jesse Kuhnert
Tapestry/Dojo/(and a dash of TestNG), team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

Reply via email to