PRContext, PRContextFilter, cookies enabled, component creation and Restful urls

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

PRContext, PRContextFilter, cookies enabled, component creation and Restful urls

Nick
Hi,

Today I checked-in a fix which reverts a change I made to try to stop multiple PRContextFilter s being added to the session filter chain. Unfortunately the fix caused unintended side-effects, which I believe contributed to the problems Sergio mentioned. Hopefully the reversion should fix some or all of these problems. 

However there's still an issue with the interaction of PRContext, PRContextFilter, cookies, component creation and Restful urls. To illustrate the issue execute the following:

createSimplestPierPRContextFilterIssue
| app rootPage |

rootPage := (PRPage named: 'rootPage') contents: '+counter+'; yourself.
rootPage localEnvironment: ((PRComponent named: 'contents')
componentClass: PRContentsWidget; yourself).
rootPage addChild: ((PRComponent named: 'counter') componentClass:
WACounter; yourself).

app := PRPierFrame registerAsApplication: 'contexttest' kernel: (PRKernel
named: 'contexttest' root: rootPage).


then browse to http://localhost:8080/contexttest You should see a counter instance. Increment the value of the counter once. Then in a new window/tab of the same browser, browse to same url (http://localhost:8080/contexttest) and decrement the value of the counter once. Now return to the original value and increment again - the counter displays the value "-1" rather than "2".

If I try the same test in Pier 1, (note in Pier 1 you'll have to manually enable cookies through the /config), when I first browse to the second tab, the counter already displays "1".

What's happening? In the Pier 2 case:
* PRPierFrame>>#initialRequest is called for every Restful url. There is no distinction between a call when a new session has been created and a call with an existing session.
* In PRPierFrame>>#initialRequest a new PRContextFilter is added to the session: "self session addFilter: (PRContextFilter on: self)"
* In WASession>>#handleFiltered: aRequestContext, if there is no continuation key, #start is called on the session, which creates a new root component - in this case a new PRPierFrame.
* So every time we browse to a Restful url a new PRPierFrame is created which holds the PRContext. This context is then "held" by the PRContextFilter.

What does this mean in our counter example:

In the first tab a new session is created, a new PRPierFrame, a new PRContextFilter and a new WACounter instance are created. The link to increment the counter contains a continuation key so #initialRequest isn't called and callback is fired incrementing the counter which in turn displays "1".

In the second tab the session already exists, however without a continuation key a new PRPierFrame, a new PRContextFilter and a new WACounter instance are created. Decrementing the counter decrements it on the new WACounter instance.

Now returning to the first tab we again try to increment the counter. The callback on the first component created is called and the counter is incremented. However in the rendering phase, the second component created in the second tab is displayed, with it's counter unincremented and set to "-1". 


What are the problems:

* There is no distinction between #initialRequest called with a newly created session and #initialRequest called from a session recovered via a cookie. Neither is there an obvious way of detecting for which case #initialRequest has been called.
* Within  WASession>>#handleFiltered: if no continuation key exists a new root component is created.
* A new PRContextFilter is added for each Restful call.

Two possible solutions:

* A new PRPierFrame is only created when a new session is created. This should then function as Pier 1. However if the root presenter is exchanged in one open tab e.g. with a #call or #show on the root, then other open tabs will not operate as intended. The implementation would I think require a custom session with a custom #handleFiltered: or alternatively a modified WASession which allows configurable behaviour when there's no continuation key.

* If however we want to allow for multiple components so that state isn't maintained between two identical Restful - that is both counters start at 0. Then we could move PRContext into the session, and remove the PRContextFilter.

I hope this makes sense I've I understood the situation correctly. Any thoughts?

Nick

 



 

_______________________________________________
Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: PRContext, PRContextFilter, cookies enabled, component creation and Restful urls

Lukas Renggli
> What's happening? In the Pier 2 case:
> * PRPierFrame>>#initialRequest is called for every Restful url. There is no
> distinction between a call when a new session has been created and a call
> with an existing session.

Is this the correct behavior? Looks like a bug in Seaside, it should
only call #initialRequest: when the session object is created. Julian
might know more ...

> * In PRPierFrame>>#initialRequest a new PRContextFilter is added to the
> session: "self session addFilter: (PRContextFilter on: self)"

I see, there are countless filters added. Now it would be easy to
detect if a filter is already present, but then the root cause seems
to be somewhere else ...

> * In WASession>>#handleFiltered: aRequestContext, if there is no
> continuation key, #start is called on the session, which creates a new root
> component - in this case a new PRPierFrame.

That's a Seaside bug, no?

> * So every time we browse to a Restful url a new PRPierFrame is created
> which holds the PRContext. This context is then "held" by the
> PRContextFilter.

PRPierFrame should be preserved, because it is stageful. With and
without cookies.

> * A new PRPierFrame is only created when a new session is created. This
> should then function as Pier 1. However if the root presenter is exchanged
> in one open tab e.g. with a #call or #show on the root, then other open tabs
> will not operate as intended.

The root presenter is backtracked, so this should be fine.

> The implementation would I think require a
> custom session with a custom #handleFiltered: or alternatively a modified
> WASession which allows configurable behaviour when there's no continuation
> key.

I think the current behavior of WASession is broken. Does the plain
Seaside counter without Pier work at all if cookies are enabled?

> * If however we want to allow for multiple components so that state isn't
> maintained between two identical Restful - that is both counters start at 0.
> Then we could move PRContext into the session, and remove the
> PRContextFilter.

All components should preserve their state across their session. Also
I would try to avoid depending on a specific WASession, that was a big
problem in Pier 1 because you could not easily use it in your own
application (for example as a help or documentation system).

Lukas

--
Lukas Renggli
www.lukas-renggli.ch

_______________________________________________
Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: PRContext, PRContextFilter, cookies enabled, component creation and Restful urls

Nick
Hi Lukas,

Thanks for the reply. Looking again at the issues they are more Seaside bugs than Pier bugs. Or rather the Seaside bugs should be resolved first, then any outstanding Pier bugs can be addressed. I've posted on the Seaside-dev list - using a cookie enabled WACounter as the example. 

There is one issue that could simplify things in the meantime:


> * If however we want to allow for multiple components so that state isn't
> maintained between two identical Restful - that is both counters start at 0.
> Then we could move PRContext into the session, and remove the
> PRContextFilter.

All components should preserve their state across their session. Also
I would try to avoid depending on a specific WASession, that was a big
problem in Pier 1 because you could not easily use it in your own
application (for example as a help or documentation system).

PRContext could be stored in a WASession property and still allow Pier to be used by Seaside apps. Storing in a session property would prevent two or more Pier instances being used within a Seaside app - although the current PRContextFilter won't work properly in that situation either. By adding PRContext as a session property PRContextFilter wouldn't be necessary and the code simplified.

Nick

_______________________________________________
Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki