Glad to see I have been using best practices... I am in complete 
agreement about form field names, and I like the added benefit that 
they're obscured.

One area where the continuations are very useful is in multipage forms. 
I like the idea of being able to, for example, stop halfway through a 
multipage survey and come back to it later. But for this, the 
continuation has to be a little more permanent. Is there any facility 
built into Lift for this?

I played around with Seaside briefly until I couldn't stand the Squeak 
IDE anymore (one seriously ugly application -- looks like it was 
designed by Mickey Mouse). But I thought that the continuations were 
persistent. Years and years ago I used to work with Apache Cocoon, which 
was my first exposure to continuations (I'm such a newbie), and again, 
you could stop and restart a process at any time.

Chas.

David Pollak wrote:
> 
> 
> On Tue, Mar 24, 2009 at 11:02 AM, Charles F. Munat <[email protected] 
> <mailto:[email protected]>> wrote:
> 
> 
>     I remain confused by a lot of this stuff.
> 
>     Here is an example:
> 
>     I have a site that creates pages dynamically based on information in a
>     database. A good example is bio pages. Users add their bios, and then
>     the bios are available through a URL.
> 
>     Now if I use, for example, the user's ID in the URL, thus:
> 
>     members/666
> 
>     Then it is a simple matter of a lookup in the database and spit out the
>     code. The page is easily bookmarked and returned to. It's even
>     reasonably human readable (members/beelzebub would be even better). I
>     can do some simple things to prevent scripting attacks. I've used this
>     system for many years and have never had a problem.
> 
>     If I use a closure instead I end up with something like this:
> 
>     members/?F92019795619530=_
> 
>     Can't be bookmarked. Not easily human readable. Expires. For me, this is
>     essentially unworkable.
> 
>     I see the benefit to continuations, but they don't seem like the best
>     solution in every instance. Even in a simple CRUD app, I like being able
>     to bookmark the edit page for an item and come back to it. Where I tend
>     to use continuations is for deletes, or for pages I specifically want to
>     expire.
> 
>     So what is the best practice here, and why? How can I create my dynamic
>     member pages and make them bookmarkable and non-expiring? Is there a
>     Lift way that I'm missing?
> 
> 
> No.  You got the balance just right.  For stuff that you bookmark and 
> things that are stable, use stable identifiers.  That's totally cool. 
>  But when you're building a page with a form, you should worry about the 
> name of the fields on the form.  You should only have to worry about 
> what happens when the form is submitted. But the user never bookmarks 
> the form field.  The user never looks at the form (unless they're a 
> hyper-geek).
> 
> Bright line: for stuff that's intended for bookmarking or for stuff that 
> conveys meaning to a human, generate the stable identifier yourself and 
> deal with the HTTP request appropriately (e.g., a rewrite rule.)  For 
> the plumbing and stuff that's related to sessions, let Lift generate 
> GUIDs and associate them with functions.
> 
> Cool?
>  
> 
> 
> 
>     Chas.
> 
>     marius d. wrote:
>      >
>      >
>      > On Mar 24, 6:53 pm, Alex <[email protected]
>     <mailto:[email protected]>> wrote:
>      >> Perhaps this debate has been had before but I didn't see it.  I
>     have a
>      >> feeling this might be contentious.
>      >>
>      >> Doesn't this violate the basic tenet that you should not use server
>      >> side state when you don't have to?
>      >
>      > No. As long as you are binding a function we are talking about state.
>      >
>      >>  There is no reason for instance
>      >> when someone is submitting a news group posting to bind an empty
>      >> posting in a closure and store it on the server, thereby
>     breaking the
>      >> application in any number of cases:
>      >>
>      >> 1) The session times out because the user got distracted or lost
>     their
>      >> connection temporarily
>      >> 2) The user abuses the back button
>      >> 3) The server fails over (assuming there is no memory replication)
>      >> 4) There is a temporary connection failure and the user reloads
>      >> 5) The server is restarted
>      >
>      > I don't see how that would break the application. The function
>     mapping
>      > is cleared is the session times out or it is terminated. Furthermore
>      > Lift has a garbage collection mechanism that removes the functions
>      > that are not utilized.
>      > None of the above cases breaks a Lift application ... if the
>      > application itself is correctly designed and implemented. If we are
>      > talking about clustered applications Lift currently uses sticky
>      > sessions mechanism meaning that all requests pertaining to a given
>      > session are processed by the same node. This can be easily ensured by
>      > load balancing rules. If a node breaks part of the conversation state
>      > can be ensured by application design when processed by a different
>      > node ...of course in the context of a different HttpSession.
>      >
>      >> All of the above cases are recoverable with what, IMO, are properly
>      >> designed frameworks that minimize server-side state.  Those are the
>      >> things that taught us state should be stored in the client whenever
>      >> possible.
>      >
>      > Yes and no. I agree with state minimization but adding burden to
>      > client side doesn't solve much in many cases. With Lift and Scala we
>      > are leveraging functions and partial functions to process
>     requests. If
>      > you want that bad purely stateless handling you can also do that with
>      > Lift. Please see LiftRules.statelessDispatchTable.
>      >
>      >> I saw a bit of a discussion distinguishing REST from human
>      >> interaction, saying human interactions are not stateless, but that
>      >> does not excuse the application being so vulnerable to breakage.
>      >
>      > I still don't get where your vulnerability comes from.
>      >
>      >> This reminds me of why I dislike many ASP applications I've used -
>      >> they always break when users don't behave well or when some kicks a
>      >> server - and users, myself included, always misbehave.  I use
>     the back
>      >> button when I shouldn't, I leave forms half filled out when I answer
>      >> the phone, and as a frequent traveler I tend to use web applications
>      >> from places with shoddy internet.  I also don't like to lose my work
>      >> when a server fails over or is restarted.
>      >
>      > With a bit of care for design this can be taken care. For instance if
>      > you have an Ajax form and the request fails, Lift will try to resend
>      > that ... if the retry request qoes to a new node then we are talking
>      > about the application design if the application has enough contextual
>      > information to handle that or not. Such as in forms that do not
>      > require logged in users (i.e. posting a comment on a blog or forum as
>      > anonymous) the application can safely process the form request in the
>      > context of a new HttpSession/LiftSession.
>      >
>      >> There may be a few gains from designing things the lift way -
>      >> simplicity, security, etc - but they seem to come at too great a
>     cost.
>      >
>      > What is this "great cost" ... one can write poor designed
>     applications
>      > in any language or framework on this Earth (dunno about other
>      > planets). A framework can only do so much but it does not guarantee
>      > flawless applications.
>      >
>      >> There maybe some solutions to this, such as serialization of
>     this data
>      >> to the client, but I'm not sure I like any of them.
>      >
>      > That would be a performance killer.
>      >
>      >> -Alex
>      >>
>      >> On Mar 24, 2:46 am, "marius d." <[email protected]
>     <mailto:[email protected]>> wrote:
>      >>
>      >>> The foo reference is captured in checkAndSave which is saved on
>      >>> LiftSession in function mapping.
>      >>> Br's,
>      >>> Marius
>      >>> On Mar 24, 10:23 am, Alex <[email protected]
>     <mailto:[email protected]>> wrote:
>      >>>> If I have this in a (not Stateful) Snippet, is the checkAndSave
>      >>>> closure saving state on the server?  Where is the reference to foo
>      >>>> saved?
>      >>>>   def add(form: NodeSeq) : NodeSeq = {
>      >>>>     val foo = Foo.create
>      >>>>     def checkAndSave(): Unit = foo.validate match {
>      >>>>       case Nil => foo.save ; S.notice("Started foo: " + foo.body)
>      >>>>       case xs => S.error(xs) ; S.mapSnippet("Foo.add", doBind)
>      >>>>     }
>      >>>>     def doBind(form: NodeSeq) =
>      >>>>       bind("foo", form,
>      >>>>         "body" -> foo.body.toForm,
>      >>>>         "submit" -> submit("Submit", checkAndSave))
>      >>>>     doBind(form)
>      >>>>   }
>      > >
> 
> 
> 
> 
> 
> -- 
> Lift, the simply functional web framework http://liftweb.net
> Beginning Scala http://www.apress.com/book/view/1430219890
> Follow me: http://twitter.com/dpp
> Git some: http://github.com/dpp
> 
> > 

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to