myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Kitching <skitch...@apache.org>
Subject Re: JSF: Multiple browser windows sharing Same session
Date Thu, 02 Oct 2008 14:39:36 GMT
simon.kitching@chello.at schrieb:
> Eelco Hillenius schrieb:
>>  
>>> Again, I don't see this as being particularly a JSF problem. I can't
>>> imagine that struts or wicket or rails would be able to deal with this
>>> problem any easier.
>>>     
>>
>> Actually, Wicket has an out-of-the-box solution for this. Wicket 
>> works with
>> 'page maps', which roughly represent the same thing as browser 
>> windows, and
>> we have some magic going for detecting new browser windows. It's a best
>> effort that works for most of the cases out there, but while we never 
>> get
>> complaints about it, there are probably a few corner cases that fall
>> through.
>>
>> For anyone interested, take a look at INewBrowserWindowListener and
>> WebPage#renderHead for the source code. Not the easiest code to follow
>> (after all, it's a bit of a nasty problem to solve), but it might 
>> give you
>> ideas on how to solve it for JSF.
>>
>> I saw someone else suggesting that keeping all your state on the client
>> would solve this. This is true, but it may open up a bunch of security
>> holes. Certainly when you assumed your state to be safe before. Also,
>> depending on 'how much' state is concerned, it might mean a considerable
>> efficiency hit. The most extreme example I've seen was an ASP.NET 
>> page with
>> over a megabyte of serialized state. That should be avoidable, but 
>> things
>> can add up quickly, so you should at least keep an eye on it.
>>   
>
> Thanks very much for the info! I will have a look at the Wicket 
> solution..

I have (finally) had a look at the wicket code, and it is indeed 
interesting. It's not a perfect solution, but is useful. Thanks for 
pointing it out, Eelco!

The core insight is that when open-in-new-tab is used, or a bookmark is 
activated, or a url is pasted into a window, the browser always creates 
a new javascript Window object. This object will have fresh values for 
the built-in properties (window.name etc) and will not have any custom 
javascript properties at all.

So *after* a page has been loaded by the new window, javascript in the 
page can check window.name or look for custom javascript properties to 
find out whether the window is a new one. If the page being rendered did 
not expect to be rendered into a new window then it can use javascript 
to set window.location to tell the server about it. In particular, it 
can ask the server to allocate a new "window context" and then render a 
new page (or the same page again).

When server processing of a request has triggered allocation of a new 
"window context", then it should simply render javascript into the page 
head that sets the appropriate window property (window.name or custom 
javascript property); it expects to be rendered into a "new" window. 
When server processing of a request has reused an existing "window 
context" then it should render script that checks for the magic state 
and redirects if the window is new. Typically the url redirected to 
tells the server to allocate a new "window context" then re-render the 
same page. The javascript to achieve this is pretty trivial.

There are the following issues:

(1) This approach does require javascript to be activated on the 
browser; when javascript is not activated then the new-window-detection 
simply has no effect.

(2) It only detects the problem *after* a request has been rendered on 
the server and streamed back to the browser. If the request has 
side-effects then the original window is now out-of-sync. However all of 
the use-cases (open-in-new-window, activate-bookmark, copy-paste-url) 
result in GET operations, and according to the principles of REST, no 
GET operation should affect server state.

Note in particular that for JSF server-side-state-saving a new 
view-state will have been pushed into the cache before the problem is 
detected. This state will never be used again (but is "newer" than the 
state for the original window).

(3) The new window may flicker a bit, as it shows the first page then 
immediately redirects. Or does putting the javascript check in the page 
head prevent this? I would guess that the bad page is present in the 
history anyway...

(4) It does require script to be rendered into every page (preferably 
into the head section). In most webapps that's not too hard to arrange, 
but a lib like Orchestra cannot automatically set that up.


Of course there is also the issue that simply *detecting* new windows is 
not enough; there needs to be some kind of per-window-storage too. 
Wicket takes care of that, and so can Orchestra. But Orchestra does not 
(yet) have an easy way to render the appropriate javascript checks.

Regards,
Simon


Mime
View raw message