How to redirect to login page after session expire in GWT RPC call

后端 未结 8 1255
死守一世寂寞
死守一世寂寞 2020-12-13 07:44

I am using GWT and RPC in my app. after session expires when I do a RPC call, because of my login-filter the request redirect to login.jsp, but my problem is client doen\'t

相关标签:
8条回答
  • 2020-12-13 08:15

    Why don't you you have a GWT timer (http://google-web-toolkit.googlecode.com/svn/javadoc/2.4/com/google/gwt/user/client/Timer.html) running instead that checks if the session is active/expired and then either prompt the user to extend the session or proceed to logout page. Why are you doing this only on RPC calls?

    0 讨论(0)
  • 2020-12-13 08:15

    @Vielinko's update was useful with MyProxyCreator's @Piotr's solution.

    For variety, this is an alternative solution to the one provided by @Piotr but it's also quite similar. I found this also worked after implementing with @Piotr's solution to begin with:

    Note: update the package name as required.

    package com.google.gwt.sample.stockwatcher.server;
    
    import com.google.gwt.core.ext.typeinfo.JClassType;
    import com.google.gwt.sample.stockwatcher.client.MyRemoteServiceProxy;
    import com.google.gwt.user.client.rpc.impl.RemoteServiceProxy;
    import com.google.gwt.user.rebind.rpc.ProxyCreator;
    
    
    public class MyProxyCreator extends ProxyCreator {
    
        public MyProxyCreator(JClassType serviceIntf) {
            super(serviceIntf);
        }
    
        /**
         * This proxy creator extends the default GWT {@link ProxyCreator} and replaces {@link RemoteServiceProxy} as base class
         * of proxies with {@link MyRemoteServiceProxy}.
         */
        @Override
        protected Class<? extends RemoteServiceProxy> getProxySupertype() {
            return MyRemoteServiceProxy.class;
        }
    
    }
    

    Create a MyRemoteServiceProxy.java class in your client package:

    package com.google.gwt.sample.stockwatcher.client;
    
    import com.google.gwt.user.client.rpc.impl.Serializer;
    
    import com.google.gwt.http.client.RequestCallback;
    import com.google.gwt.user.client.rpc.AsyncCallback;
    import com.google.gwt.user.client.rpc.impl.RemoteServiceProxy;
    import com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter;
    import com.google.gwt.user.client.rpc.impl.RpcStatsContext;
    
    /**
     * The remote service proxy extends default GWT {@link RemoteServiceProxy} and
     * proxies the {@link AsyncCallback} with the {@link AsyncCallbackProxy}.
     */
    public class MyRemoteServiceProxy extends RemoteServiceProxy {
    
        public MyRemoteServiceProxy(String moduleBaseURL, String remoteServiceRelativePath, String serializationPolicyName,
                Serializer serializer) {
            super(moduleBaseURL, remoteServiceRelativePath, serializationPolicyName, serializer);
        }
    
        @Override
        protected <T> RequestCallback doCreateRequestCallback(RequestCallbackAdapter.ResponseReader responseReader,
                String methodName, RpcStatsContext statsContext, AsyncCallback<T> callback) {
            return super.doCreateRequestCallback(responseReader, methodName, statsContext,
                    new MyAsyncCallback<T>(callback));
        }
    }
    

    This is an alternate solution to having the MyProxyCreator and MyRpcRemoteProxyGenerator in @Piotr's solution. I've tested that it works. RPC calls reroute to this function first before they are called. Keep the MyAsyncCallback for handling the session time out. :)

    0 讨论(0)
  • 2020-12-13 08:22

    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);
      }
    }
    
    0 讨论(0)
  • 2020-12-13 08:23

    Yes you should handle session timeout in a onFailure(in my opinion). But there are simple ways to do that.

    1. Implement your own async callback.

      public abstract class MyAsyncCallback<T> implements AsyncCallback<T> {
      
      @Override
      public void onFailure(Throwable arg0) {
          if arg0 is SessionTimeout
              redirect to loginpage
          else
              failure(Throwable ar0)
      }
      
      @Override
      public void onSuccess(T arg0) {
          success(arg0);
      }
      
      public abstract void success(T arg0);
      
      public abstract void failure(Throwable arg0);
      

      }

    2. Use some library like gwt-dispatcher where all rpc-calls go through the same serviceasync and gives u one place to handle onFailures.

    0 讨论(0)
  • 2020-12-13 08:23

    I put a little fix to MyProxyCreator's @Piotr version, adpated to GWT 2.5

    package my.package.server;
    
    import java.util.Map;
    
    import com.google.gwt.core.ext.typeinfo.JClassType;
    import com.google.gwt.core.ext.typeinfo.JMethod;
    import com.google.gwt.core.ext.typeinfo.TypeOracle;
    import com.google.gwt.user.rebind.SourceWriter;
    import com.google.gwt.user.rebind.rpc.ProxyCreator;
    import com.google.gwt.user.rebind.rpc.SerializableTypeOracle;
    
    
    public class MyProxyCreator extends ProxyCreator {
    
        private final String methodStrTemplate = "@Override\n"
                + "protected <T> com.google.gwt.http.client.Request doInvoke(ResponseReader responseReader, "
                + "String methodName, RpcStatsContext statsContext, String requestData, "
                + "com.google.gwt.user.client.rpc.AsyncCallback<T> callback) {\n"
                + "${method-body}" + "}\n";
    
        public MyProxyCreator(JClassType serviceIntf) {
            super(serviceIntf);
        }
    
        @Override
        protected void generateProxyMethods(SourceWriter w, SerializableTypeOracle serializableTypeOracle, TypeOracle typeOracle, Map<JMethod, JMethod> syncMethToAsyncMethMap) {
            // generate standard proxy methods
            super.generateProxyMethods(w, serializableTypeOracle, typeOracle, syncMethToAsyncMethMap);
    
            // generate additional method
            overrideDoInvokeMethod(w);
        }
    
        private void overrideDoInvokeMethod(SourceWriter w) {
            StringBuilder methodBody = new StringBuilder();
            methodBody.append("final com.google.gwt.user.client.rpc.AsyncCallback newAsyncCallback = new my.package.client.MyAsyncCallback(callback);\n");
            methodBody.append("return super.doInvoke(responseReader, methodName, statsContext, requestData, newAsyncCallback);\n");
    
            String methodStr = methodStrTemplate.replace("${method-body}",methodBody);
            w.print(methodStr);
        }
    
    }
    

    It changed the methods signs for generateProxyMethods and doInvoke.

    Best Regards.

    iVieL

    0 讨论(0)
  • 2020-12-13 08:24

    I used the following with GWT 2.2 to handle the new doInvoke method:

    public class MyProxyCreator extends ProxyCreator {
    
        private final String methodStrTemplate = "@Override\n"
                + "protected <T> com.google.gwt.http.client.Request doInvoke(ResponseReader responseReader, "
                + "String methodName, com.google.gwt.user.client.rpc.impl.RpcStatsContext statsContext, String requestData, "
                + "com.google.gwt.user.client.rpc.AsyncCallback<T> callback) {\n"
                + "${method-body}" + "}\n";
    
        public MyProxyCreator(JClassType serviceIntf) {
            super(serviceIntf);
        }
    
        @Override
        protected void generateProxyMethods(SourceWriter w, 
                SerializableTypeOracle serializableTypeOracle,
                TypeOracle typeOracle,
                Map<JMethod, JMethod> syncMethToAsyncMethMap) {
            // generate standard proxy methods
            super.generateProxyMethods(w, serializableTypeOracle, typeOracle, syncMethToAsyncMethMap);
    
            // generate additional method
            overrideDoInvokeMethod(w);
        }
    
        private void overrideDoInvokeMethod(SourceWriter w) {
            StringBuilder methodBody = new StringBuilder();
            methodBody
                    .append("final com.google.gwt.user.client.rpc.AsyncCallback newAsyncCallback = new com.mydomain.client.MyAsyncCallback(callback);\n");
            methodBody
                    .append("return super.doInvoke(responseReader, methodName, statsContext, requestData, newAsyncCallback);\n");
    
            String methodStr = methodStrTemplate.replace("${method-body}", methodBody);
            w.print(methodStr);
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题