Question

I am using GWT for my client side application. However, I am not sure how I can handle session management. The GWT application resides on one page, all server calls are done via AJAX. If a session expires on the server. let's assume the user didn't close the browser, and sending some request to server using RPC, how could my server notify the application that the session has expired and that the client side portion should show the login screen again?My sample code :

ContactDataServiceAsync contactDataService = GWT
                .create(ContactDataService.class);
        ((ServiceDefTarget) contactDataService).setServiceEntryPoint(GWT
                .getModuleBaseURL()
                + "contactDatas");

        contactDataService.getContact(2,
                new AsyncCallback<ContactData>() {
                    public void onFailure(Throwable caught) {
                                      //code to show error if problem in connection or redirect  to login page

                    }

                    public void onSuccess(ContactData result) {
                        displayContact(result);
                    }
                });

If session expires only it has to show login screen, otherwise it wants to show some error using Window.alert().

How to do this and what are all the codes needed in server side and client side?

Was it helpful?

Solution

You could have the server throw an AuthenticationException to the client in case the user has been logged out.
This will be catched in the callbacks onFailure method, which then can redirect the user to the login-page.

Edit:
AuthenticationException is not a standard exception of course, i was just making an example. It might be best to stick with the standard exceptions.

To try if you caught an specific exception you could use the instanceof operator

    public void onFailure(Throwable e) {
                  if(e instanceof AuthenticationException) {
                        redirecttoLogin();
                  }
                  else {
                    showError(),
               }
            }

OTHER TIPS

This does not directly apply to those using RPC, but for those of you who are not using RPC, you should send a HTTP 401 from the server. Then you can check that status code in your RequestBuilder callback.

Client: All Callbacks extend a Abstract Callback where you implement the onFailur()

public abstract class AbstrCallback<T> implements AsyncCallback<T> {

  @Override
  public void onFailure(Throwable caught) {
    //SessionData Expired Redirect
    if (caught.getMessage().equals("500 " + YourConfig.ERROR_MESSAGE_NOT_LOGGED_IN)) {
      Window.Location.assign(ConfigStatic.LOGIN_PAGE);
    }
    // else{}: Other Error, if you want you could log it on the client
  }
}

Server: All your ServiceImplementations extend AbstractServicesImpl where you have access to your SessionData. Override onBeforeRequestDeserialized(String serializedRequest) and check the SessionData there. If the SessionData has expire then write a spacific error message to the client. This error message is getting checkt in your AbstrCallback and redirect to the Login Page.

public abstract class AbstractServicesImpl extends RemoteServiceServlet {

  protected ServerSessionData sessionData;

  @Override
  protected void onBeforeRequestDeserialized(String serializedRequest) {

    sessionData = getYourSessionDataHere()

    if (this.sessionData == null){ 
      // Write error to the client, just copy paste
      this.getThreadLocalResponse().reset();
      ServletContext servletContext = this.getServletContext();
      HttpServletResponse response = this.getThreadLocalResponse();
      try {
        response.setContentType("text/plain");
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        try {
          response.getOutputStream().write(
            ConfigStatic.ERROR_MESSAGE_NOT_LOGGED_IN.getBytes("UTF-8"));
          response.flushBuffer();
        } catch (IllegalStateException e) {
          // Handle the (unexpected) case where getWriter() was previously used
          response.getWriter().write(YourConfig.ERROR_MESSAGE_NOT_LOGGED_IN);
          response.flushBuffer();
        }
      } catch (IOException ex) {
        servletContext.log(
          "respondWithUnexpectedFailure failed while sending the previous failure to the client",
          ex);
      }
      //Throw Exception to stop the execution of the Servlet
      throw new NullPointerException();
    }
  }

}

In Addition you can also Override doUnexpectedFailure(Throwable t) to avoid logging the thrown NullPointerException.

@Override
protected void doUnexpectedFailure(Throwable t) {
  if (this.sessionData != null) {
    super.doUnexpectedFailure(t);
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top