I just checked in a fix to master for
https://bugzilla.redhat.com/show_bug.cgi?id=754521. It was a class of
issue we've seen before, where the user goes to view X and then quickly
goes to view Y, before X has completed rendering. Typically, this
results in NPEs, because the code we added to support Selenium locators
destroys view widgets when it thinks we're done with them. My fix for
754521 was as follows:
1) create a new ViewChangedException runtime exception
2) in places where we detect that the user has switched to a different
view than the one we are still rendering, throw a ViewChangedException,
rather than continuing on rendering. Here's an example from
AbstractTwoLevelTabSetView.updateTabContent():
String currentViewPath = History.getToken();
if (!currentViewPath.startsWith(this.baseViewPath)) {
throw new ViewChangedException(this.baseViewPath + "/" +
getSelectedItemId());
}
Places that are good candidates for such code are in onSuccess() methods
of async callbacks, because while we were waiting for the async call to
return, the user could have navigated away to another view.
3) add code to the uncaught exception handler in CoreGUI that gracefully
handles ViewChangedExceptions by simply logging a DEBUG message to the
gwt log:
GWT.setUncaughtExceptionHandler(new
GWT.UncaughtExceptionHandler() {
public void onUncaughtException(Throwable e) {
if (e instanceof ViewChangedException) {
ViewChangedException viewChangedException =
(ViewChangedException) e;
String obsoleteView =
viewChangedException.getObsoleteView();
Log.debug("User navigated to view [" + currentView
+ "] before view [" + obsoleteView
+ "] was done rendering - rendering of view ["
+ obsoleteView + "] has been aborted.");
} else {
getErrorHandler().handleError(MSG.view_core_uncaught(), e);
}
}
});
If you encounter a similar bug in the future, you should be able to
leverage this new mechanism. Essentially, you would just need to find
the right place in the code to do step 2) from above.