I am trying to implement session timeout with help of a GWT Timer which will make a RPC call to server to check whether the session is valid or expired by using lastaccessedtime. but every time i make a RPC call it updates the lastaccessedtime (understandable as i am making a RPC call), any way i can prevent my Timer RPC call from updating the lastaccessedtime?
wrote some server side logic to get the lastaccessedtime and try to find out session is valid or not
com.google.gwt.user.client.Timer elapsedTimer;
public void onModuleLoad() {
elapsedTimer = new Timer () {
public void run() {
validateSession();
}};
//giving time delay of 1sec to call the batches
elapsedTimer.scheduleRepeating(60000);
}
public void validateSession(){
//Problem code every time i make this call it updates the last accessed time
viewService.validateSessionGWT(new AsyncCallback<ModuleData>() {
#Override
public void onFailure(Throwable e) {
//do something
}
#Override
public void onSuccess(ModuleData data) {
if(data.getSessionExpired()){
//redirect to login page
}
}
});
}
any idea how to overcome this problem or any other idea to implement Session management in GWT
NOTE: already gone through this which is similar to my approach
https://itsecrets.wordpress.com/2011/07/20/session-timeouts-with-gwt-rpc-calls/
Your GWT servlets extend the RemoteServiceServlet. So you can override processPost and add a custom last call timestamp in you http session. Every request updates this field.
I suggest to implement an abstract servlet that is extended by all your gwt servlets. Additionally you should not only set the custom last access field, but check it just before and only call the super method if everything is fine.
Then your timer and the servlet request you already have should only check this Session field.
Perhaps not the best solution but this should work.
Related
What is best way to attempt multiple time same RPC call while failing RPC call?
just example: Here one case like if RPC get failed due to network connection, it will catch in onFailure(Throwable caught).
Now here it should recall same RPC again for check network connection. The maximum attempt should be 3 times only then show message to user like "Network is not established"
How can I achieve it?
Some couple of thoughts like call same rpc call in onFailure but here request become different.but I want same request have a three request and it is not good approach and I don't know if any good solution for it.
Thanks In Advance.
Use a counter in your AsynCallBack implementation. I recommend as well to use a timer before requesting the server again.
This code should work:
final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
final String textToServer = "foo";
greetingService.greetServer(textToServer, new AsyncCallback<String>() {
int tries = 0;
public void onSuccess(String result) {
// Do something
}
public void onFailure(Throwable caught) {
if (tries ++ < 3) {
// Optional Enclose the new call in a timer to wait sometime before requesting the server again
new Timer() {
public void run() {
greetingService.greetServer(textToServer, this);
}
}.schedule(4000);
}
}
});
#Jens given this answer from Google Groups.
You could transparently handle this for all your requests of a given GWT-RPC interface by using a custom RpcRequestBuilder. This custom RpcRequestBuilder would make 3 request attempts and if all 3 fail, calls the onFailure() method.
MyRemoteServiceAsync service = GWT.create(MyRemoteService.class);
((ServiceDefTarget) service).setRpcRequestBuilder(new RetryThreeTimesRequestBuilder());
The custom RequestBuilder could also fire a "NetworkFailureEvent" on the eventBus if multiple application components may be interested in that information. For example you could overlay the whole app with a dark screen and periodically try sending Ping requests to your server until network comes back online. There is also the onLine HTML 5 property you can check, but its not 100% reliable (https://developer.mozilla.org/en-US/docs/Web/API/window.navigator.onLine)
I have a project that does 2 RPC calls and then saves the data that the user provided in tha datastore. The first RPC call works ok, but from the second I always recieve the onFailure() message. How can I determine why the onFailure() is triggered? I tried caught.getCause() but it doesn't return anything.
feedbackService.saveFeedback(email,studentName,usedTemplates,
new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
caught.getCause();
Window.alert("Failure!");
}
public void onSuccess(String result) {
Window.alert("Saved!");
}
});
Throwable instance is instance of an Exception. You can check if it is a custom Exception like this:
if (caught instanceOf CustomException){
or if you want to show the message of exception you can use the getMessage():
Window.alert("Failure: " + caught.getMessage());
GWT-rpc is not not easy to ebug if an error occurs.
The easiest part is th check if the Exception is part of StatusCodeException.
A Statuscode of 404 means, you are pointing to a wrong endpoint
0 means, that
The searver is unreachable
You don't have permissions to check, if the server is available (X-domain-request)
You can use the Chrome-Web-Inspector to bedug GWT-RPC
You should be able to see all calls from the browser to you backend.
The most common failures are because of serialization of object. You have to ensure, that all dtransferred object implement java.io.Serializable
Most of the time it will just be a server side exception being raised which fires the onFailure() method.
Try putting breakpoints on your server side. That should help you pinpoint what's going wrong.
We are trying to handle a scenario that when a user in quitting a room ,we send a message using MetaBroadcaster to all room .We implemented this feature by override broadcast method of AtmosphereGwtHandler .
The feature is good when we testing in development mode, but when we test it in Jetty8 production mode, telling by log, the override method is void which never get called.
So anybody know what's wrong with it, or do we have a better solution to this feature.
here is our code snippet:
public class ChatHandler extends AtmosphereGwtHandler {
...
#Override
public void broadcast(Object message, GwtAtmosphereResource resource) {
MsgType msgtype=((ChatMessage)message).getMsgtype();
if(msgtype==MsgType.Broad){
MetaBroadcaster.getDefault().broadcastTo(((ChatMessage)message).getChanel(), message);
System.out.println("Doing to all room);
}else{
super.broadcast(message, resource);
System.out.println("Doing to myself);
}
}
}
Can't really give an answer on the info provided.
Where have you configured your handler?
web.xml or atmosphere.xml
What servlet are you using Meteor/Atmosphere?
What version of Atmosphere?
I've been implementing a GWT application that calls a REST-service (which we're also developing). When the REST-service returns anything with a HTTP-status other than 200 I would expect the onFailure method of AsyncCallback to be called. However I can't get this to happen.
To test it further I created a test GWT app and a test servlet. The part of the GWT app that calls the service looks like this:
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.setCallbackParam("_jsonp");
jsonp.setFailureCallbackParam("_jsonp_failure");
jsonp.requestObject(url, new AsyncCallback<JavaScriptObject>()
{
#Override
public void onFailure(Throwable caught)
{
Window.alert("Failure: " + caught.getMessage());
}
#Override
public void onSuccess(JavaScriptObject result)
{
Window.alert("Success");
}
});
The servlet-code looks like this:
public class MyRestServlet extends HttpServlet
{
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
String padding = httpServletRequest.getParameter("_jsonp_failure");
httpServletResponse.setContentType("application/x+javascript");
httpServletResponse.setStatus(500);
PrintWriter out = httpServletResponse.getWriter();
out.println(padding + "({\"some\":\"json\"});");
out.close();
}
}
OnFailure eventually gets called when the request times out, but I would expect it to be called as soon as the http response arrives(if it's a failure). I guess there is something I haven't understood and I would really appreciate to get some help with this.
Thanks
According to HTML5, if there's an error loading the script, an error event should be dispatched, and GWT doesn't listen for it (because almost no browser actually fires it AFAICT).
For best browser compatibility, you'd better always send a 200 status, but then call the failure callback (or in other words, return an error state/condition, rather than throw an exception).
Also, the argument to the failure callback is expected to be a string (will be the message of the exception).
From the server code where you call the REST service, throw an exception yourself if the response is something other than 200 (by writing code to check the response yourself). This way it will persist to the client side as an error and onFailure will be called in client side.
In GWT's mind currently nothing went wrong. It sent a request, got some result did not matter what, the call was successful. It does call the onFailure on a timeout because something did go wrong with the request "physically", and GWT persisted the exception to the client side as a failure.
I have a GWT application and I want to run some code when the user leaves the application to force a logout and remove any data etc.
To do this I am using a CloseHandler and registering it using Window.addCloseHandler.
I have noticed that when the refresh button is clicked the onClose method is run but I have been unable to differentiate this event from a close where the user has closed the browser. If it is a refresh I do not want to do the logout etc, I only want to do this when the user closes the browser/tab or navigates away from the site.
Does anybody know how I can do this?
There is no way to differentiate the 'close' from 'refresh'. But, you can set a cookie that holds the last CloseHandler call time and check, when loading the module, if this time is old enough to clean the information before showing the page.
You can do that with the folowing utility class (BrowserCloseDetector). Here is an example using it on the onModuleLoad.
The test lines:
#Override
public void onModuleLoad() {
if (BrowserCloseDetector.get().wasClosed()) {
GWT.log("Browser was closed.");
}
else {
GWT.log("Refreshing or returning from another page.");
}
}
The utility class:
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
public class BrowserCloseDetector {
private static final String COOKIE = "detector";
private static BrowserCloseDetector instance;
private BrowserCloseDetector() {
Window.addWindowClosingHandler(new Window.ClosingHandler() {
public void onWindowClosing(Window.ClosingEvent closingEvent) {
Cookies.setCookie(COOKIE, "");
}
});
}
public static BrowserCloseDetector get() {
return (instance == null) ? instance = new BrowserCloseDetector() : instance;
}
public boolean wasClosed() {
return Cookies.getCookie(COOKIE) == null;
}
}
Have you tried
<BODY onUnload = "scriptname">
in your gwt hosting/launching html file?
I am thinking that if you defined a map "hash" (i.e. a javascript pseudo hash) in the hosting file and then accessed the "hash" in GWT through Dictionary class, you could update values in that hash as the user progresses through the gwt app. Which means, your programming style would require you to log milestones on the user's progress onto this map.
When the user closes the browser page, the onunload script of the launching html page would be triggered. That script would access the map to figure out what needs to be updated to the server, or what other url to launch.
I am intereted too if someone got a solution (GWT/java side only).
Maybe we can do it with HistoryListerner ?
1-set a flag for your current viewing page.
2-when ClosingHandler event, launch a "timeout" on server-side (for example 10s)
3-if during this time your got a massage from HistoryListerner with the same last flag so it was just a refresh.
of disconnect if timer is over...
Is not a good solution but I think it is easy to do... If someone have a better one...