gwt-rpc delay window refresh - gwt

I have the following code in the onModuleLoad() of my application:
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
event.setMessage("If you choose to close, application will sign out");
}
});
//sign out on close
Window.addCloseHandler(new CloseHandler<Window>() {
#Override
public void onClose(CloseEvent<Window> event) {
sendLogout();
}
});
The sendLogout() function looks like this:
// Set up the callback object.
AsyncCallback<String> callback = new LogoutCallback(this);
// Make the call to the survey service.
SurveySystemService.Util.getInstance().logout(details, callback);
Where 'details' is some object.
It works just fine when the window is closed, but if I try to refresh the page, it doesn't log out. What I figured is that since the call is asynchronous, it doesn't finish getting the message off to the server before the module is restarted.
I've tried:
1. creating and calling the callback inside the onClose method.
2. using a Timer to check if the call was made.
3. Endless loos which check the same as the above (I got desperate).
In all of these solutions, the program would reach the callback creation, but the server never received anything.
any help with this?

Can you just call logout any time the page first loads. Due to the stateless nature of the web the GWT application will not know the difference between someone hitting refresh or just navigating to the page.
You can store an ID variable in session storage which should be maintained until the browser window or tab is closed. If on the application start the ID variable exists in session storage you can use it to trigger the log out.

Related

Handle session time out with Wicket

I'm working on a wicket legacy-project and i'm trying to fix a bug with the session time-out.
Basically I'd like to have a redirect to a customed error page after session times out.
This is what I did:
web.xml :
<session-config>
<session-timeout>1</session-timeout>
</session-config>
in the application class:
#Override
public void init() {
super.init();
getApplicationSettings().setPageExpiredErrorPage(ErrorMessagePage.class);
This is not working. I mean after session time out, nothing happens.
What am I doing wrong?
EDIT 04.05.20
Based on the feedback from Martin I tried to implement a session validaty checker:
public class SessionValidityChecker implements IRequestCycleListener {
#Override
public void onBeginRequest(RequestCycle cycle) {
HttpServletRequest request = (HttpServletRequest) cycle.getRequest().getContainerRequest();
boolean sessionValid = request.isRequestedSessionIdValid();
if (!sessionValid) {
cycle.setResponsePage(SessionExpiredPage.class);
}
}
}
and in Application.class
public void init() {
super.init();
getRequestCycleListeners().add(new SessionValidityChecker());
}
Also what I may should have specified in my first post is that I use the wicket SignInPanel for authentification. After timeout, I'd like the user to be logged out and redirected to a specific page.
This is what I've tried with the above code, but after session time out, no redirect happens. Even worst, the user is still signed in. What am I missing?
You are mistaking page expiration with session expiration.
Stateful pages are stored in a PageStore (disk) and the store may grow up to some predefined size. Once this size is reached the oldest page is removed to make room for the newest one.
If your user uses the browser Back button many times at some point Wicket will throw PageExpiredException for the deleted page.
In your case when the session expires usually the web server (e.g. Tomcat) will just create a new one. If your application has authentication enabled then it will detect that there is no authenticated user in the new http session and most probably will redirect the user to the login page.
If there is no authentication in place then Wicket will create a new instance of the requested page and render it. You can change this by changing PageSettings#recreateBookmarkablePagesAfterExpiry to false
(see https://github.com/apache/wicket/blob/79f63f66eb588a5d69e9feff7066f1244f61f387/wicket-core/src/main/java/org/apache/wicket/settings/PageSettings.java#L46)
You may use javax/servlet/http/HttpServletRequest.html#isRequestedSessionIdValid() method to find whether the the request came with an expired JSESSIONID cookie/url. If it is false then the web server just created a new HttpSession. You can do the check in Wicket's IRequestCycleListener#onBeginRequest()

Send trigger to onModule that RPC succeded

I have a Class that contain all the RPC.
One of them is :
public void authenticateUserCall(String username,String password ,DBConnectionAsync rpcService)
{
AsyncCallback<UserIdent> callback = new AsyncCallback<UserIdent>() {
public void onFailure(Throwable caught) {
Window.alert("Wrong Username or Password");
}
public void onSuccess(UserIdent result) {
Window.alert(result.getUserName());
}
};
rpcService.authenticateUser(username, password, callback);
}
If the RPC succeeds, I want to change the layout of the page to the main page for the user.
So how can I send to the onModule that the RPC succeeded ?
I don't want to build the layout in the onSuccess, and I can't clear the login layout because I don't have it on the onSuccess method.
What is the right way to do it ?
Option 1:
A couple of suggestions would be to pass in the AsyncCallback as an argument to the authenticateUserCall. This way the caller could handle on success.
Option 2: Recommended
Another option, which will give you much more flexibility is to use the EventBus to fire a custom AuthenticationEvent. I use this for handling things like roles. So for instance when the user is authenticated successfully it will return me some information about the user, like their username, password and role. I then use the EventBus to fire an AuthenticationEvent which contains this information about the user. Any of my views and activities can register for this event on the event bus and handle accordingly. So for example many of my views will disable functionality if the user is not an admin. When one of my activities handles this event it will grey out action buttons that require admin access.

GWT: session invalidate on window close works in development mode but not on actual server

I am using this code to invalidate user session on browser close .
Window.addCloseHandler(new CloseHandler<Window>() {
#Override
public void onClose(CloseEvent<Window> event) {
logOut();
}
});
logOut method is just calling the RPC and making session invalidate ..
as soon i close the browser , it closes and after that the call made to server and reaches to server which invalidate the session successfully.
But when i put my application on Tomcat or any web hosting .. This functionality stops working ..
any idea ..what could be the solution
I think, your problem is, that the browser is closed before the rcp call had a chance to send the underlying XMLHTTPRequest to the server.
I would give the WindowClosingHandler a chance:
Window.addWindowClosingHandler(new ClosingHandler() {
#Override
public void onWindowClosing(ClosingEvent event) {
logOut();
}
});
If this does not work, try to add a native javascript function that is called by the onBeforeUnload event and use JSNI to call your logOut() method.

Cancel form submission

How can I cancel a form submission using GWT?
I need to validate the form and process some of the data before actually submitting it.
So far I did the following, the problem is that the form is submitted even if the SubmitEvent is cancelled.
form.addSubmitHandler( new SubmitHandler() {
#Override
public void onSubmit(SubmitEvent event) {
if(validate()) {
// i do some processing here
form.submit();
}
else event.cancel(); // submits anyway
}
});
Is this a GWT issue? How should I do?
edit: I just found out that if it was a Button that uses form.submit() on click, the submit event is cancelled. However if a SubmitButton is clicked, the event is not cancelled.
So I guess this is a browser behavior. Still, I need to find way...
edit: just found out that it does only happen in development mode, I feel silly not to have tried outside development mode before.
It's an issue that only happen in development mode
I have reported the issue: http://code.google.com/p/google-web-toolkit/issues/detail?id=5067

GXT: How to bring the login page when session expires

I am developing a web application using GXT, Hibernate, mysql etc. There is a login page for the application. Actually I am getting problem to set the login page when the session expires. We can set the timeout in the web.xml file but in that case we can't redirect to login page.Can you tell me how to achieve that.
You can not do a server side redirect because the application is entirely AJAX. What you can do is use the GWT Timer class and for every one of your RPC calls check/reset the timer. If the "session" expires then you do a redirect to the login page via a History token. This was the easiest way for me
Some other reading:
http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/b9eab8daaa993c83/d0192d356045e061?pli=1
http://gwt-ext.com/forum/viewtopic.php?f=9&t=1682
I have used the concept of throwing an exception in the server side when the session expires and then tried to catch the exception in the client side. I don't know whether there is any better way to do that.
On the server side, you can check if the session is expired and if so, throw a custom exception.
On the client side, on every async call you do a check for this known situation and react to it. You can create an abstract class for AsyncCallback that you will subclass for each GWT RPC call:
public abstract class SessionExpiredAwareAsyncCallback<T> implements AsyncCallback<T> {
#Override
public void onSuccess(T returnObject) {
doOnSuccess(returnObject);
}
#Override
public void onFailure(Throwable exception) {
if (exception instanceof SessionExpiredException) {
goToLoginPage();
} else {
doOnFailure(exception);
}
}
public abstract doOnSuccess(T returnObject);
public abstract doOnFailure(Throwable exception);
}
You can use gwteventservice to fire an event from the server to the client.