Hi,
In RESTful applications which also generate continuation key (_k) links a
problem can arise if you open multiple tabs all sharing the same session.
To illustrate:
1) Enable cookies for http://localhost:8080/examples/counter.
2) Open the counter and increment the value.
3) Open http://localhost:8080/examples/counter in a new tab and decrement
the counter.
4) Return to the first counter and increment the value - you will see "-1"
rather then "2" !
What I think is happening:
If Seaside finds a session but there is no continuation key (_k) then
WASession>>#handleFiltered: calls WARenderLoopMain>>#start which in turn
creates a new root presenter and calls #initialRequest on the
presenter. When the second tab is opened a new WACounter is created and
stored in the session's #presenter property. When you return to the first
tab, the callback is executed on the first counter, but the second counter
is rendered.
Ideas for possible fixes:
* I thought that #presenter was backtracked so don't understand why the
original counter #presenter isn't restored for the callback. If the
presenter was backtracked correctly then the counter example should work as
anticipated.... however:
* in Pier (and potentially other RESTful apps) you don't want to create a
new presenter for every RESTful call within an active session. If you don't
create a new presenter then #initialRequest currently won't be called,
which then won't allow your RESTful app to derive state from the url. If
Seaside is modified to call #initialRequest do you need to differentiate
between a call on a newly created session and one on an existing session?
You could differentiate with a call to a new method on WAPresenter, pass in
a flag to #initialRequest, or set a WARequestContext property to indicate a
new session had been created. What to do with backtracked state. Do you nil
all state before handling the request, restore state from a stored "initial
value" snapshot or just use the state of the components from their last
handled state?
I bought this issue up before [1], but didn't pursue it as I was struggling
to understand the issues and ran out of time. Julian responded to my
previous email when I was proposing a problematic fix with:
I'm not sure it's a good fix in the general case. If you don't have a
> continuation key, you shouldn't (by definition) have any existing
> (backtracked) state. Relying on the root presenter currently in the
> Session is problematic since that value is backtracked for each
> request; you'll simply get whichever root happened to be used by
> whatever request was last handled by that session. If you don't happen
> to be ever changing the root, then it may well be what you want, but
> it's not right in the general case.
> Incidentally, this also touches on the flaw I was discussing the other
> week with our snapshots: because we have no continuation key, we
> really ought to nil out any backtracked data before processing the
> request (at least that way we have a consistent state while handling
> the request). We don't run into the problem with the root presenter
> because #start reinitializes it, but for other backtracked state,
> you'd just get random stuff in there based on the last-handled
> request.
> A more appropriate general fix (at least in this case) could be to
> take the last-used continuation and apply its state before handling a
> request with no _k. However, we don't always know the last-used
> (depending on the caching mechanism in place) and I'm not convinced
> that is actually always what people want. I still feel pretty
> confident that the "right" semantics of an Application/Session request
> with no _k is to start a new main/render-loop.
Certainly for Pier as it is currently designed I don't think that creating
a new render-loop for session requests with the _k is the right thing to
do, as it created a new root #presenter. I think ideally Seaside would for
existing session with no _k
1) Keep the existing #presenter
2) call #initialRequest with a flag to indicate that a new session hadn't
been created.
3) restore the state to an "initial render state" which is snapshotted (?)
when the initial render occurs on a new session.
Thoughts
Nick
[1]
http://forum.world.st/sessions-continuation-keys-restful-urls-and-component…
If each tabs starts with a RESTful url then a new presenter will be
created.
Hi
I want to move Seaside-REST from Addons to the "Core" repository in Seaside 3.1:
The reasons are the following:
- the code base has stabilized and has been jürgenized by Lukas
- we have documentation in the book [1]
- several people use it
I'm aware this will probably cause problems for some people but I
don't think leaving it in addons or having it in both places are good
alternatives either. Is this absolutely terrible or somebody (Dale?)?
Personally I think of the addons repository as something similar to
Apache Incubator. A place where we can experiment. If things turn out
well we can graduate them to the core repository.
[1] http://book.seaside.st/book/advanced/restful
Cheers
Philippe
I was reviewing the Seaside book while refreshing my skills, and I
noticed this very strange, trivial, but fundamental bug/inconsistency:
http://www.youtube.com/watch?v=2RyREN00Nok (less than 2 minute demo).
The issue is hardly worth mentioning, except for totally new users, but
I DO wonder what is going on that changes the behavior from the first
right-click on the category pane to the second.
L
--
Squeak from the very start (introduction to Squeak and Pharo Smalltalk for the (almost) complete and compleate beginner).
https://www.youtube.com/playlist?list=PL6601A198DF14788D&feature=view_all
Hi
To fix issue 733 I had to introduce yet another stream wrapper (we
would be so dead without Cog). And now our stream hierarchy is about
to share the same fate as it's brethren. Here's what I did:
We already had GRCodec stream which had about several responsibilities:
- It defined "our" stream protocol and was an "anchor" for several
packages (JavaScript, Comet, …) to add their class extensions
- It was sort of a stream decorator base class that delegated to a
concrete stream implementation
- It was sort of abstract, #nextPutAll: and other methods had to be
implemented and did not delegate (!). But
#greaseNext:putAll:startingAt: did delegate.
- It was the base class for codec streams although nothing codec
related was there
What I did I create a superclass named GRDelegatingStream, moved all
the behavior there. GRCodecStream is now an (empty) abstract base
class for coded stream. GRCountingStream and GRSwitchableStream are
subclasses of GRDelegatingStream instead of GRCodecStream. I did no
further clean up.
All is not well in the state of Denmark tough. I outlined several
smells in Issue 734 [1]. I would welcome it if somebody could review
the current hierarchy and suggest improvements before it becomes big
pile of mud.
[1] http://code.google.com/p/seaside/issues/detail?id=734
Cheers
Philippe