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.1we
> > 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]
>
>