Inge, Thanks for posting it, I will give it a shot! regards,
Mark -----Original Message----- From: Inge Solvoll [mailto:[EMAIL PROTECTED] Sent: Tue 3/7/2006 3:42 AM To: Tapestry users Subject: Re: "Token" approach to avoiding double submits Of course, I meant JWC-file where it says PAGE-file. The code listed is for a Token-component. On 3/7/06, Inge Solvoll <[EMAIL PROTECTED]> wrote: > > I found a working solution for myself now, that involves the least > possible amount of coding for each page. Now I only have to include my Token > component at the beginning of each form. So far it's working, please tell me > if anyone sees why this shouldn't work. > > Here's my solution, I really think tapestry should have some kind of > native support for this... > > PAGE-file > > <property name="tokenServer" persist="session"/> > <property name="tokenClient"/> > > <component id="token" type="Hidden"> > <binding name="value" value="tokenClient"/> > </component> > > HTML-file > > <input type="hidden" jwcid="token"/> > > JAVA-file > > > public void pageBeginRender(PageEvent event) { > log.debug("Entered pageBeginRender"); > if (!getRequestCycle().isRewinding()) { > String newToken = generateToken(); > setTokenServer(newToken); > setTokenClient(newToken); > } > } > > protected void renderComponent(IMarkupWriter writer, IRequestCycle > cycle) { > super.renderComponent(writer, cycle); > log.debug ("Entered renderComponent"); > if (getRequestCycle().isRewinding()) { > String tokenClient = getTokenClient(); > String tokenServer = getTokenServer(); > log.debug("Token from form: " + tokenClient); > log.debug("Token on server: " + tokenServer); > > if (tokenClient == null || !tokenClient.equals(tokenServer)) { > > log.error("Token for page is not valid, redirect to obtain last > good state"); > throw new PageRedirectException(this.getPage()); > > } > } > } > > > > On 3/3/06, Nick Westgate < [EMAIL PROTECTED]> wrote: > > > > Off the top of my head, I suppose you could put the token in the > > page base class. But then to make it unique you'd have to include > > something (for example the page name) in the token string. > > > > That should work, but perhaps there's a better way in T4. > > Hopefully I'll find out in my next project. ;-) > > > > Cheers, > > Nick. > > > > > > Inge Solvoll wrote: > > > Looks like a good solution! > > > > > > The problem for the future is that getVisit() is deprecated, so from > > 4.1 we > > > have to inject the visit object as state into all pages if we want to > > use > > > this pattern. That qualifies as "unnecessary plumbing" for me, the > > > expression used in the tapestry commercials :) > > > > > > Maybe my code should use the visit object in every page anyway, I > > don't use > > > any ASOs yet, partly because our application has been ported from > > struts, > > > and is still partly struts-implemented, needing quite a few > > integration > > > points. > > > > > > Inge > > > > > > On 3/3/06, Nick Westgate < [EMAIL PROTECTED]> wrote: > > > > > >>Hi Inge. > > >> > > >>I use the FlowSynchronizer pattern that Sohail linked to, > > >>and here's how I avoid code duplication. > > >> > > >>In my T3 apps the FlowSyncronizer is stored in the Visit object. > > >>My border component includes the token in every page: > > >><input jwcid="@Hidden" value="ognl:page.visit.flowSynchronizer.token"/> > > >> > > >>In addition, I didn't like the exceptions, so instead: > > >> private boolean resubmit; > > >> public void setToken(String token) > > >> { > > >> // first compare the token > > >> if (this.token == null || !this.token.equals(token)) > > >> { > > >> resubmit = true; > > >> } > > >> else > > >> { > > >> // reset token on match -> subsequent duplicate > > submission > > >>will fail > > >> this.token = null; > > >> resubmit = false; > > >> } > > >> } > > >> > > >>My BasePage class has: > > >> public boolean isResubmit() > > >> { > > >> // check if this cycle is a resubmit (before doing inserts > > etc) > > >> Visit visit = (Visit)getVisit(); > > >> return visit.flowSynchronizer.isResubmit(); > > >> } > > >> > > >>Then in any page where you need to know, just call isResubmit(). > > >> > > >>Cheers, > > >>Nick. > > >> > > >> > > >>Inge Solvoll wrote: > > >> > > >>>This is one of the cases where it would be really really sweet to be > > >> > > >>able to > > >> > > >>>extend components, including specifications... > > >>> > > >>>On 3/2/06, Geoff Longman < [EMAIL PROTECTED]> wrote: > > >>> > > >>> > > >>>>You could craft your own Form component that handles the hidden and > > >>>>use the tapestry-flash thingy to save the token > > >>>> > > >>>>Geoff > > >>>> > > >>>>On 3/2/06, Inge Solvoll <[EMAIL PROTECTED]> wrote: > > >>>> > > >>>> > > >>>>>I've tried to copy the token-approach from struts into Tapestry, to > > >>>> > > >>>>avoid > > >>>> > > >>>> > > >>>>>crashes when the user hits the "refresh"-button in the browser. > > Using > > >>>> > > >>>>this > > >>>> > > >>>> > > >>>>>approach, the html rendered can only be submitted once. My problem > > is > > >>>> > > >>>>that > > >>>> > > >>>> > > >>>>>the code I've written so far requires too much code copying and > > >>>> > > >>>>repeating, > > >>>> > > >>>> > > >>>>>and I was wondering if someone has ideas on how to make the > > >>>> > > >>>>implementation a > > >>>> > > >>>> > > >>>>>bit less intrusive for my pages. > > >>>>> > > >>>>>I could include this code in my base class that all my page classes > > >>>> > > >>>>inherit > > >>>> > > >>>> > > >>>>>from, but then I would have to inject WebRequest into every single > > page > > >>>> > > >>>>in > > >>>> > > >>>> > > >>>>>my application, and that's not the tapestry way to do page design, > > is > > >>>> > > >>>>it? > > >>>> > > >>>> > > >>>>>I'm pretty sure that this is functionality that I need in all my > > pages > > >>>>>(refresh of a post causes crash most of the times in my tapestry > > code). > > >>>>>Maybe this can be done with a servlet filter, or better, with a > > >> > > >>HiveMind > > >> > > >>>>>service that intercepts the request? > > >>>>> > > >>>>>Here's my code so far: > > >>>>> > > >>>>>public void pageBeginRender(PageEvent event) { > > >>>>> if (getRequestCycle().isRewinding()) { > > >>>>> String token = getRequest().getParameter("token"); > > >>>>> if (token == null || !token.equals(getToken())) { > > >>>>> log.error("Token for page is not valid, redirect to obtain > > last > > >>>> > > >>>>good > > >>>> > > >>>> > > >>>>>state"); > > >>>>> throw new PageRedirectException(this); > > >>>>> } > > >>>>> } > > >>>>> else { > > >>>>> setToken(generateToken()); > > >>>>> } > > >>>>> > > >>>>>} > > >>>>> > > >>>>>.html: > > >>>>><input jwcid="@Any" type="hidden" name="token" value="ognl:token"/> > > > > >>>>> > > >>>>>.page: > > >>>>><property name="token" persist="session"/> > > >>>>> > > >>>>> > > >>>>>An article on the subject: > > >>>>>http://www.javalobby.org/java/forums/m91956568.html > > >>>>> > > >>>>> > > >>>> > > >>>> > > >>>>-- > > >>>>The Spindle guy. http://spindle.sf.net > > >>>>Get help with Spindle: > > >>>> http://lists.sourceforge.net/mailman/listinfo/spindle-user > > >>>>Blog: http://jroller.com/page/glongman > > >>>>Feature Updates: http://spindle.sf.net/updates > > >>>> > > > > >>>>--------------------------------------------------------------------- > > >>>>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] > > > > >
