Eliminating subsequent UI requests before the current one is handled

I have following question about Browser<->Server interaction in Vaadin:

Is there any way to ignore/eliminate UI requests from browser while the
current one is being handled?

Scenario is like this:

  • there are several buttons on the screen, some of them open subwindows, some do DB changes etc.
  • if button is pressed to open some subwindow which takes some time (a lot of data loading) than
    I can manage during those several seconds to press some more buttons before modal subwindow appears.
  • this way many different button click listeners are invoked which leads to serious unwanted side effects

Is there a way to tell Vaadin to always ignore on browser side all the UI actions before the current
request is handled?

Or should I do this on server side? Is there any known practices for doing this?

This is the first Web application for me. Before this I’ve done a lot of Swing programming.

Hi, I know from where you’re coming from. :V

One of possible methods to prevent user from messing with UI during server roundtrip is to customize CSS of .v-loading-indicator (that’s the animated gimmick displayed on top right corner in pristine Reindeer stylesheet) to behave like a visual sem-transparent layer that blocks all window content.

For example, this one fits my needs well, much better than default Reindeer handler imo.

/* Server transaction indicator */
.v-loading-indicator, .v-loading-indicator-delay, .v-loading-indicator-wait {
	position: absolute;
	top: 0;
	left: 0;
 	width: 100%;
    height: 100%;

    margin: 0;
    padding: 0;

	opacity: 0.5;
	filter: alpha(opacity=50); 
	z-index: 30000;

	background-color: #999999;
	background-repeat: no-repeat;
	background-position: 50%;

	cursor: wait;
}

.v-loading-indicator {
  	background-image: url(icons/animations/loading-indicator.gif);
}

.v-loading-indicator-delay {
	background-image: url(icons/animations/loading-indicator-delay.gif);
}

.v-loading-indicator-wait {
	background-image: url(icons/animations/loading-indicator-wait.gif);
}

Be warned that this method won’t be 100% effective, but easily filter out 99% of click-happy users from doing undesirable things. The rest 1% requires server side handling and occures if initial super rapid clicks translate to multiple handler events yet before v-loading-indicator kicks in.

For modal popup-windows the following handler would serve the purpose. Otherwise an attempt to add the same child window >1 times to main window would trigger Vaadin exception.

class SomeButtonListener implements ClickListener {
	@Override
	public void buttonClick(final ClickEvent event) {
		if(popupWindow.getParent() == null) {
			popupWindow.doSomeInit();
			getApplication().getMainWindow().addWindow(popupWindow);
		}
	}
}

my 2c

How does the loading-indicator CSS work in Vaadin? That is, who is setting and clearing it?

I have one Form in particular that is obnoxious with 53 NativeSelect boxes. It’s not a common configuration screen, but is used to setup document styles. I found that if I put a breakpoint in my Table row selection code, I’d see the loading-indicators, so it was occurring automatically by Vaadin. But without the breakpoint, it appears to happen so quickly I never see the loading indicator.

But the Form takes a long time (~4 seconds) to render. I have a log statement that frames the onRequestStart and onRequestEnd and these execute quickly, while the UI in my browser is still building out the DOM (perhaps 3 out of the 4 seconds), I guess.

So, it seems that perhaps the loading-indicator is set and then cleared when the servlet is done, even if the UI in the browser is still busy. Is there any way to frame this better so that the loading-indicator is not turned off until the browser has completed whatever DOM manipulations are needed to handle the response from Vaadin?

Well my observation is quite different to yours. I use some quite complex form layouts, but don’t have scene any close to 53 NativeSelect boxes -_-

Some comments:

  1. Have never went deep enough to analyze details on how is loading-indicator started/stoped under the hood of Vaadin. It just works well for me as it is for given user-case.
  2. According to my experience loading-indicator stays on until all of the stages below are finished:
    a) browser sends request and waits for server response (during that animation is shown)

    b) browser receives complete servlet response (at that point animated gif stops animation - browser is busy)


    c) browser makes DOM changes and redraws the page (at that point indiciator disappears)

B and C are strongly browser dependant. Easily visible in IE/FF and almost non perceivable in Chrome and Opera as JS execution is damn fast in those.

  1. There was/is issue with loading-indicator on older IE versions where it appears UNDER(!) child/popup windows, thus won’t block access to UI above (http://dev.vaadin.com/ticket/5122). It a non-issue with newer IEs, FF, Opera, Chrome.

  2. Loading-indicator proved to be rather CPU intensive task (core load up to 100% in certain browsers) - even occures if browser should be in idle state waiting for server. It may be due to gif animation or the way RPC/AJAX is implemented. Not sure though.

Yeah, even that monstrous view loads in about 1 second on Chrome and Opera and even Safari, while IE and FF were slow. Oddly, I even saw Safair show the loading indicator as expected on the first load that did take a bit, but when I switched to other views and then returned, it was too fast to see any such loading.

Using Firebug, I can see that when I click on the row in the Table that triggers the Form to be populated, the POST UIDL took 182ms with 45.3KB of data. I can see all of those select box data in there (sadly, there are only about 5 different types of select boxes, just 10 usage scenarios where they repeated, so they all have the same “choices” in the drop downs, but there’s no way to define just one and use it in 5 places).

That seems to match up with my servlet trace since onRequestStart() is called at 48.774 (time is seconds.msec) and onRequestEnds() is called 48.953 for an elapsed time of 179ms (since I’m testing on my PC there’s no real network time). This is then followed by 4 GETs for PNGs all in the 1-4 ms range, with the total time being 3.29 seconds.

Firebug must interfere, too, since when I do it again, the POST UIDL takes on 61ms.

But I simply do not see the busy indicator. But if I put my code into debug, then the busy comes on, turns yellow, then turns red. And when I release it then, it seems that the red indicator stops spinning but does appear to stay on the screen until FF draws the view. But without debug, I don’t the indicators at all (or very briefly), yet the view takes 3 seconds to appear and the servlet communications is done fairly quickly.

Got me!

Trying to clear this up a bit.

You got it mostly right, but one crucial aspect of browsers’ inner workings was not mentioned: the browser runs everything in one thread, including JS computation, DOM manipulation and rendering.

So when the browser is doing JS computation / manipulating the DOM, it won’t do any rendering, and hence the view does not update. That includes updating animated GIF’s as well as every other pixel on the screen. The browsers usually optimize the rendering so that it happens only after all JS computation and DOM manipulation is done.

So the flow of things after a click on a button is more like this:


1.
Click


2.
The Vaadin client sends a request to the servlet, and triggers a timeout for the loading indicator to show (300ms, so it won’t flicker for each quick update, only for longer requests).


3 a.
If the request ends before the timeout, the Vaadin client hides the loading indicator (clears the timeout), and begins to render the changes. If the changes are huge, the rendering will take many seconds, and the view will remain static during the rendering and nothing else is done during that time (no events prosessed, since the event loop also runs within the same thread). You can break up that one thread with some JS commands (alert window etc. / setTimeout, anything that is asynchronous), but usually just ends up slowing the rendering since the browser can’t do all the possible optimizations (batching DOM updates etc.).


3 b.
If the request takes more time to end (long operation on the server), the client only waits and is free to update the view, and hence you see the spinning loading indicator. And triggering a debug breakpoint during development from your IDE is the same thing as a long request from the browsers point of view.


3 b cont.
When the request finishes, the loading indicator is hidden right away, but since there are other updates to the view right after that (the UIDL response, which might be huge) the view won’t update before all the changes have been made to the DOM/view. So the spinner is visible for the whole rendering time, but won’t spin.

Hope this clears things up a bit.

Thanks for the info on the details. I wonder why in my case I don’t see the loading indicator at all, though, spinning or not spinning. It’s as if FF is able to cancel the spinning right away and remove it from view while it does the lengthier DOM build. Anyway, Chrome makes my app look all the better with its speed of rendering. No doubt it will all be easier to see once I’m testing over the Internet instead of on my PC.

Hmm, that’s strange. There might be something done differently in Firefox internally that could allow it to hide the spinner first and then process the UI changes.

the solution:

getUI().access( new Runnable() {
@Override
public void run() {
// you code
}
} );