2010-09-07 18 views
12

Estoy usando GWT y RPC en mi aplicación. después de que la sesión caduque cuando realizo una llamada RPC, debido a mi filtro de inicio de sesión la solicitud se redirecciona a login.jsp, pero mi problema es que el cliente no me muestra login.jsp sino que aparece el RPC onFailure.Cómo redirigir a la página de inicio de sesión después de que la sesión caduque en GWT Llamada RPC

Significa que debo manejar todos mis eventos de rpc onFailure para redireccionar a la página de inicio de sesión? !!!!

Gracias

Respuesta

21

Estoy de acuerdo con pathed que debe hacer en la reorientación de sus AsyncCallback s. Sin embargo, no necesita utilizar explícitamente sus devoluciones de llamada MyAsyncCallback personalizadas en lugar de GWT estándar AsyncCallback. Esto es importante, por ejemplo, cuando ya tienes un montón de código que utiliza devoluciones de llamadas estándar.

Al invocar GWT.create(MyService.class), GWT genera un proxy para su interfaz de servicio MyServiceAsync. Este proxy es responsable de comunicarse con el servidor y invocando sus callbacks cuando obtiene datos del servidor. Los proxies se generan usando GWT code generators mechanism y de forma predeterminada GWT usa la clase ServiceInterfaceProxyGenerator para generar estos proxies.

Se puede extender este generador por defecto (ServiceInterfaceProxyGenerator clase) utilizar automáticamente sus MyAsyncCallbacks personalizados en todas las invocaciones devoluciones de llamada. Recientemente hicimos exactamente eso en un proyecto. Debajo hay un código fuente que usamos.

Código de MyAsyncCallback, es idéntica a la presentada por pathed:

package my.package.client; 

import com.google.gwt.user.client.rpc.AsyncCallback; 

public class MyAsyncCallback<T> implements AsyncCallback<T> { 

    private final AsyncCallback<T> asyncCallback; 

    public MyAsyncCallback(AsyncCallback<T> asyncCallback) { 
     this.asyncCallback = asyncCallback; 
    } 

    @Override 
    public void onFailure(Throwable caught) { 
     if (caught instanceof SessionTimeoutException) { 
      // redirect 
      return; 
     } 

     asyncCallback.onFailure(caught); 
    } 

    @Override 
    public void onSuccess(T result) { 
     asyncCallback.onSuccess(result); 
    } 

} 

Código para el generador de código de GWT (MyRpcRemoteProxyGenerator):

package my.package.server; 

import com.google.gwt.core.ext.typeinfo.JClassType; 
import com.google.gwt.user.rebind.rpc.ProxyCreator; 
import com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator; 

public class MyRpcRemoteProxyGenerator extends ServiceInterfaceProxyGenerator { 

    @Override 
    protected ProxyCreator createProxyCreator(JClassType remoteService) { 
     return new MyProxyCreator(remoteService); 
    } 
} 

Y generador de clase auxiliar (MyProxyCreator):

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.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, int invocationCount, 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, 
      Map<JMethod, JMethod> syncMethToAsyncMethMap) { 
     // generate standard proxy methods 
     super.generateProxyMethods(w, serializableTypeOracle, 
       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, invocationCount, requestData, newAsyncCallback);\n"); 

     String methodStr = methodStrTemplate.replace("${method-body}", 
       methodBody); 
     w.print(methodStr); 
    } 

} 

Finalmente, debe registrar el nuevo generador de códigos que se utilizará para generar proxies para servicios asíncronos. Esto se hace agregando esto a su archivo de configuración de GWT (gwt.archivo XML):

<generate-with 
    class="my.package.server.MyRpcRemoteProxyGenerator"> 
    <when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService" /> 
</generate-with> 

Al principio puede parecer ser una solución muy complicada :) pero tiene sus puntos fuertes:

  • Puede seguir utilizando estándar GWT AsyncCallback s
  • Puede imponer el redireccionamiento cuando la sesión agota el tiempo de su aplicación
  • Puede activar y desactivar fácilmente (agregando o eliminando generate-with en sus archivos de configuración de GWT)
+0

Esto es diabólicamente inteligente. Creo que confundiría a un nuevo desarrollador en un proyecto, ya que no habría referencias hard navegables a través del IDE para descubrir cómo se llama a MyAsyncCallback en lugar de AsyncCallback. Sin embargo, me gusta mucho que sea un único punto de corte para aplicar la corrección en lugar de tener que usar siempre la devolución de llamada personalizada para que no vuelva a aparecer un error. –

+0

@Piotr ¿Es 'SessionTimeoutException' una clase de excepción personalizada que usted escribió? Si es así, ¿te importaría compartirlo? –

+0

@AnishSana Lo siento, fue hace bastante tiempo. No tengo acceso a este código en este momento. – Piotr

5

Si usted debe manejar el tiempo de espera de sesión en un onFailure (en mi opinión). Pero hay formas simples de hacer eso.

  1. Implemente su propia devolución de llamada asíncrona.

    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. usan alguna biblioteca como GWT-despachador donde todas las llamadas RPC-pasan por el mismo serviceasync yu da un lugar para manejar onFailures.

+0

Estoy usando el patrón de MVP, así que encontré que es mejor heredar de DefaultDispatchAsync y anular la ejecución y comprobar el tiempo de última ejecución, gracias por su respuesta. – Nav

0

I utilizó la siguiente con GWT 2.2 para manejar el nuevo método doInvoke:

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); 
    } 

} 
2

pongo un poco arreglo a la versión @Piotr de MyProxyCreator, adpated a 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); 
    } 

} 

Se cambió el signos de métodos para generateProxyMethods y doInvoke.

Atentamente.

iVieL

1

Cliente: todas las rellamadas extienden una devolución de llamada abstracta donde se implementa el 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 
    } 
} 

Servidor: Todos sus ServiceImplementations extender AbstractServicesImpl donde se tiene acceso a su SessionData. Reemplazar onBeforeRequestDeserialized (String serializedRequest) y comprobar los datos de sesión allí. Si el SessionData ha caducado, escriba un mensaje de error específico al cliente. Este mensaje de error está recibiendo Checkt en su AbstrCallback y lo redirige a la página de inicio de sesión.

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(); 
    } 
    } 

} 

Además también se puede anular doUnexpectedFailure (t Throwable) para evitar el registro de la NullPointerException tirado.

@Override 
protected void doUnexpectedFailure(Throwable t) { 
    if (this.sessionData != null) { 
    super.doUnexpectedFailure(t); 
    } 
} 
+0

Es una solución, lejos de ser elegante, por varias razones: uso incorrecto de códigos HTTP, generación incorrecta de excepciones, no usa GWT RPC, etc.Sin embargo, teniendo en cuenta que GWT oculta cualquier posibilidad de implementar un filtro que responda utilizando mensajes de falla a través de RPC, es una solución aceptable. ¡Salvó mi día! Gracias. –

Cuestiones relacionadas