voyent
F5 / Refresh problem still occurring for Multi-View servers  XML
Forum Index -> General Help
Author Message
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


Hi all. I'm getting the problem that was previoulsy reported as part of ICE-3691. To be clear, if I set up my Web app to support single views only, it does work fine (pressing F5 refreshes the current view, not just the view that was displayed at the last redirect). However, if I use multiple views (set com.icesoft.icefaces.concurrentDOMViews to true), refreshing sends me back to my initial page (in this case, my logon page).

Details:
ICEfaces version 1.7.2 SP1
Glassfish v2
Windows XP (although this also occurs in Solaris 9)
JVM v 6

I've added some calls to System.out to the source file com.icesoft.faces.webapp.http.core.MultiViewServer:

Code:
    public void service(Request request) throws Exception {
 		System.out.println("MultiViewServer.service");
 		System.out.println("views=" + views);
 		System.out.println("views.size()=" + views.size());
         //extract viewNumber if this request is from a redirect
         View view;
         if (request.containsParameter("rvn")) {
             String redirectViewNumber = request.getParameter("rvn");
 			System.out.println("redirectViewNumber=" + redirectViewNumber);
             //synchronize to atomically test and possibly put new View into the map
             synchronized (views) {
                 view = (View) views.get(redirectViewNumber);
                 System.out.println("view="+view);
                 if (view == null) {
                     view = new View(redirectViewNumber, sessionID, asynchronouslyUpdatedViews, configuration, sessionMonitor, resourceDispatcher, lifecycle);
                     views.put(redirectViewNumber, view);
                     ContextEventRepeater.viewNumberRetrieved(session, sessionID, Integer.parseInt(redirectViewNumber));
                 }
             }
         } else {
             String viewNumber = String.valueOf(++viewCount);
             System.out.println("viewNumber=" + viewNumber);
             view = new View(viewNumber, sessionID, asynchronouslyUpdatedViews, configuration, sessionMonitor, resourceDispatcher, lifecycle);
             views.put(viewNumber, view);
             ContextEventRepeater.viewNumberRetrieved(session, sessionID, Integer.parseInt(viewNumber));
         }
 
         try {
             sessionMonitor.touchSession();
             view.servePage(request);
         } finally {
             view.release();
         }
     }
 


So, when I first display the page, I get my Logon page:

MultiViewServer.service
views={}
views.size()=0
viewNumber=1
updateOnPageRequest
path=/csrwebgui/logon.xhtml
reloded=false
page redirect


Next, I logon which navigates to the next page using JSF navigation without a redirect. Everything works fine, including a URL that includes the correct view number in it

MultiViewServer.service
views={1=View[txieoJmahFbq23Az3vlx-w:1]}
views.size()=1
redirectViewNumber=1
view=View[txieoJmahFbq23Az3vlx-w:1]

Once here, I press F5 to refresh the page. It goes back to my Logon page, with the following messages in System.out

MultiViewServer.service
views={}
views.size()=0
redirectViewNumber=1
view=null
updateOnPageRequest
path=/csrwebgui/logon.xhtml
reloded=false
page redirect


What seems odd is the views seems to have been re-initialised to an empty Map. I couldn't find anywhere in the code where the Map gets cleared out.

Is anyone else getting this? Is it OK to raise an Issue for this? I'll keep digging into this, but any guideance would be greatly appreciated.

Thanks for any help,
Ed
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


Still digging.... added some more system.out calls to com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet....

Code:
    public void service(Request request) throws Exception {
         System.out.println("MainSessionBoundServlet.service");
         System.out.println("request.getURI()=" + request.getURI().toString());
         System.out.println("request.getMethod()=" + request.getMethod());
         System.out.println("sessionID=" + sessionID);
         System.out.println("views=" + views);
         dispatcher.service(request);
     }
 


So, nothing unexpected (by me, anyways... maybe to those who know the code better) until I get to the point where I refresh in the browser.... I see

MainSessionBoundServlet.service
request.getURI()=http://localhost:8080/csrwebgui/block/dispose-views
request.getMethod()=POST
sessionID=O2bpBwwkNOoA0qKAo74p_g
views={1=View[O2bpBwwkNOoA0qKAo74p_g:1]}
MainSessionBoundServlet.service
request.getURI()=http://localhost:8080/csrwebgui/logon.xhtml?rvn=1
request.getMethod()=GET
sessionID=O2bpBwwkNOoA0qKAo74p_g
views={}
MultiViewServer.service
views={}
views.size()=0
redirectViewNumber=1
view=null
updateOnPageRequest
path=/csrwebgui/logon.xhtml
reloded=false
page redirect


So, from what I can tell, something as part of the refresh has called the block/dispose-views request. As part of that service, the views are there. So the dispose-views request is just doing its thing and disposing the views. Problem is, I still want them. :)

So, I guess I need to look at the Javascript and see what's going on in there. Bother. :)
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


Sorry... this post shows the console being unloaded. It does show the POST being called, but not why the dispose_views is being called.... this post is not useful

More digging... I've been using IE for this (although it still happens in FF). If I display the Javascript console when I refresh the page, I see

Code:
 [window] : Interup pressed
 [window.dispose] : [4237101] : send synchronous POST
 [window.dispose] : [4237101] : receive [200] OK
 [window.dispose] : [4237101] : connection closed
 [window] : page unloaded!


So, pressing F5 forces a page unload?

Sorry, this thread has devolved to me thinking out loud. :)
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


I've found the line that is causing me grief. In application.js a handler is being assigned to the window.onBeforeUnload event that calls the disposeViews request. If I remove this line, my refresh works as expected (I stay at the page, I don't go back to my logon page).

OK, from what I can tell, this change was for ICE-3229 affected this. So, I'll assume that simply removing the line isn't in play, as it will screw up portlets.

Previous to these changes, the redirect command would cancel any call to dispose the views. I don't know the details, but I'll infer from the name of the method that it removed any attempt by the client to dispose of the view (so it would be found). And, there was no onBeforeUnload handler, so the dispose never happens. So, here's the Javascript before the change

Code:
              commandDispatcher.register('reload', function(element) {
                  logger.info('Reloading');
                  var url = window.location.href;
                  connection.cancelDisposeViews();
                  if (url.contains('rvn=')) {
                      window.location.reload();
                  } else {
                      var view = element.getAttribute('view');
                      var queryPrefix = url.contains('?') ? '&' : '?';
                      window.location.href = url + queryPrefix + 'rvn=' + view;
                  }
              });
 


So, comparing that with the 1.7.2 SP1 version...

Code:
     var sendDisposeViews = function(parameters) {
         if (parameters.isEmpty()) return;
         try {
             var query = parameters.inject(new Ice.Parameter.Query(), function(query, parameter) {
                 return query.addParameter(parameter);
             });
 
             channel.postSynchronously(window.disposeViewsURI, query.asURIEncodedString(), function(request) {
                 Ice.Connection.FormPost(request);
                 request.on(Ice.Connection.OK, Ice.Connection.Close);
             });
         } catch (e) {
             logger.warn('Failed to notify view disposal', e);
         }
     };
 
     var disposeWindowViews = function() {
         sendDisposeViews(views);
         views.clear();
     };
 
     window.onBeforeUnload(disposeWindowViews);
 
 <SNIP>
             commandDispatcher.register('reload', function(element) {
                 logger.info('Reloading');
                 var url = window.location.href;
                 deregisterAllViews();
                 if (url.contains('rvn=')) {
                     window.location.reload();
                 } else {
                     var view = element.getAttribute('view');
                     var queryPrefix = url.contains('?') ? '&' : '?';
                     window.location.href = url + queryPrefix + 'rvn=' + view;
                 }
             });
 


It looks like it should be working. The reload command should be clearing out the views array. By the time it gets to sendDisposeViews, it should return when it comes up against empty parameters. But it seems to insist on calling the disposeViews request.

I'm sure I'm missing something. I'll have a play with the javascript and see if I can find anything out.
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


Ok, the best I can come up with is that the commandDispatcher (where it's registering a "reload" command) is used to handle commands coming to the browser from the WebApp via the Ajax bridge. So, this doesn't have anything to do with the user pressing F5 in the browser.

I only say this because I used Firebug to see if it goes into the "reload" command when I press refresh, and it doesn't. It goes straight to the sendDisposeViews method for all the views.

So, I can't think of a good alternative (my skills in Javascript aren't that hot, and I'm I certainly don't know all the moving pieces in the ajax bridge).
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


OK, I know I'm dominating this thread, but I'm trying to walk through in my head what the disposeViews request will do for a servlet application that wants to have concurrentDOMViews enabled.

It was originally written to support portlets that contained multiple views in a single browser. If you close the browser, you want to close all the views that were being displayed within the single browser. I think, that's how I've interpreted it.

However, for the scenario:

1) Not a portlet app, but a servlet app
2) concurrentDOMViews is set to true, because the user should be able to have different browsers associated with the same session displaying different views.

So, I open browserA and get viewA. Then I click on a link in browserA so it displays the data in a new Window (call it browserB, displaying browserB). This is a good thing that I want. And, it should work because I have concurrentDOMViews enabled.

However, if I refresh browserA, it doesn't display viewA anymore... it's gone back to the initial page. On top of that, because the fresh of browserA called disposeViews, browserB will also be changed to go back to the beginning. Is this correct? If so, I think this is a larger problem than just browserA not being displayed correctly.

Thanks for any help
scarsix06d

Joined: 28/Sep/2008 00:00:00
Messages: 74
Offline


Hi Why you need handled multi view?

[Email]
mircea.toma

Joined: 10/Feb/2005 00:00:00
Messages: 323
Offline


hildo wrote:
........
However, if I refresh browserA, it doesn't display viewA anymore... it's gone back to the initial page. On top of that, because the fresh of browserA called disposeViews, browserB will also be changed to go back to the beginning. Is this correct? If so, I think this is a larger problem than just browserA not being displayed correctly.
 


Well, with concurrentDOMViews enabled the main limitation is that views are not reused on page reload. Up until 1.7.1 release there used to be the "rvn" parameter that helped identifying the views for GET requests. I'll create a JIRA case for this issue and let you know its identifier.
[Email]
mircea.toma

Joined: 10/Feb/2005 00:00:00
Messages: 323
Offline


This issue is now tracked by http://jira.icefaces.org/browse/ICE-3907 .
[Email]
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


Thanks for raising the issue. I had thought that the page reload would work as long as the URL contained the view number. I'm not claiming to be an expert in this area, though. I'm planning the app out now, so I haven't quite got my hands dirty with the implementation of it.

We want to use concurrent DOMs because we would like our application to span multiple browser. For example, if we run a search that lists some data, we'd like the user to have the option to display the details for one of the rows in a new window/tab, leaving the search result in the original browser.

It's my understanding that, without concurrentDOMViews=true, displaying the object details in the second browser would also change the current view for the first browser (hitting refresh in there would no longer display the search result, or attempts to postback to it would fail because the UIViewRoot is no longer the same as what the browser thinks). This is what I have seen if I display, for example, the Component Showcase across multiple browsers.

If I've got this wrong, I'm cool with that. If there's a better way to achive supporting multiple browsers/tabs within the same session, I'm all ears. I'm not trying to get argumentative about this, I'd be happy to hear. :)

Thanks again
mircea.toma

Joined: 10/Feb/2005 00:00:00
Messages: 323
Offline


hildo wrote:
....
We want to use concurrent DOMs because we would like our application to span multiple browser. For example, if we run a search that lists some data, we'd like the user to have the option to display the details for one of the rows in a new window/tab, leaving the search result in the original browser.
 

Yes, you will need to enable concurrent DOM views.

hildo wrote:

It's my understanding that, without concurrentDOMViews=true, displaying the object details in the second browser would also change the current view for the first browser (hitting refresh in there would no longer display the search result, or attempts to postback to it would fail because the UIViewRoot is no longer the same as what the browser thinks). This is what I have seen if I display, for example, the Component Showcase across multiple browsers.
 

Yes, that's right.

hildo wrote:

If I've got this wrong, I'm cool with that. If there's a better way to achive supporting multiple browsers/tabs within the same session, I'm all ears.
 

Concurrent DOM views setup was introduced specifically for supporting multiple windows/tabs rendering. There are some complications when pages have multiple includes or in a portal environment, in order to reasonably support these setups the current behavior is a bit limiting.
Some of the problems related to this behavior can be solved by moving some of the application state out of the request beans into session scoped beans.
[Email]
hildo


Joined: 14/Nov/2007 00:00:00
Messages: 111
Offline


Thanks for that. Given that we're still designing, I imagine that we'll do what ICEfaces allows us to do. It sounds like I'm on the right path, though. We're not in a portal environment, and if we have to control the number of includes we can. So hopefully we should be able to exists happily with the existing limitations.

Do any of the samples provide examples of the types of behaviour that should reside in session-scoped beans? I'd be grateful for any doco/example that shows a preferred way of organising the code. Anything that can save me time. :) If not, I'm sure we'll nut it out.

Thanks,
Ed
mircea.toma

Joined: 10/Feb/2005 00:00:00
Messages: 323
Offline


hildo wrote:
.....
Do any of the samples provide examples of the types of behaviour that should reside in session-scoped beans? 


Well, the best example would be component-showcase/facelets version. On page reload or theme change it will reset the panel selected previously because the application is setup with concurrentDOMViews=true. If you change org.icefaces.application.showcase.jsp.navigation.NavigationBean's scope to "session" then the selected panel would not be changed on reload.
[Email]
 
Forum Index -> General Help
Go to:   
Powered by JForum 2.1.7ice © JForum Team