I have the following JSNI code in my GWT app that makes an HTTP request to detect a URL redirect -
private native void checkSession(String url)
/*-{
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(e) {
if (xhr.readyState == 4) {
if (url != xhr.responseURL) {
$wnd.alert("Your session has timed out.");
$wnd.location.assign(url);
}
}
}
xhr.open("GET", url, true);
xhr.send();
}-*/;
If the URL requested is not the same as the response URL, the session is deemed to be timed out; upon which I want to display an alert box letting the user know that the session has timed out, and initiate a redirect when they click on OK.
I have a custom class that implements AsyncCallback
. Using this technique, I was able to globally enforce onFailure()
to call checkSession()
whenever a StatusCodeException
occurs.
The problem is that the alert box pops up several times before $wnd.location.assign(url)
can initiate the redirect. I realize that several onFailure()
methods are being executed here causing the alert to pop up several times, but my question is, why is $wnd.location.assign(url)
not being executed until the last onFailure()
method is executed, while $wnd.alert()
which is right above it, being executed every single time?
How can I force a redirect in this situation? Ideally, I want the alert to pop up once, and redirect immediately upon OK being clicked.
According to this answer, the browser will try to execute the remaining JavaScript code until the page is redirected; which explains the occurrence of multiple alerts before the page redirects.
To get around this, I declared private static boolean redirect = false;
.
When a URL redirect is detected within the JSNI code, I check if redirect
is false
, and if it is, I display the alert and set redirect = true
-
if (@fully.qualified.name::redirect == false) {
@fully.qualified.name::redirect = true;
$wnd.alert("Your session has timed out.");
}
$wnd.location.assign(url);
That way, I was able to show the alert only once before initiating a redirect.