【问题标题】:Intercepting Async Proxy Service exceptions for GWT RPC拦截 GWT RPC 的异步代理服务异常
【发布时间】:2013-01-14 19:47:25
【问题描述】:

我的应用程序有很多 RPC 调用,它们都有一个 .onFailure(Throwable catch) 方法。我有一个在客户端和服务器代码 NotLoggedInException 之间共享的类。如果用户没有基于会话/cookies/权限等的相关权限,则由服务器抛出。

理想情况下,我希望在将其他异常传递给 .onFailure() 代码之前在一个地方处理此异常,因为这种处理无处不在,并且需要确保安全。有一个 GWT.setUncaughtExceptionHandler() 但这似乎是在不理想的处理之后调用的(以防 .onFailure 意外消耗太多)。

有人对此有一个优雅的解决方案吗?一个丑陋的解决方案是将延迟绑定的 .create() 代理包装在实现异步接口的同一个聚合类中。

旁注:服务器之前发出了重定向,但我不喜欢这种范例,并且希望它由应用程序的事件总线处理。

更新:上面提到的丑陋答案

public abstract class CustomAsyncCallback implements AsyncCallback{

@Override
public CustomAsyncCallback(AsyncCallback<T> callback)
{
    this.wrap = callback ;
}

AsyncCallback<T> wrap ;


@Override
public void onFailure(Throwable caught) {
    if (!handleException())
{
    wrap.onFailure(caught) ;
}
}

@Override
public void onSuccess(T t) {
    wrap.onSuccess(t) ;
}

}

公共类 WrapDeferredBinding 实现 RpcInterfaceAsync { RpcInterfaceAsync 服务 = GWT.create(RpcInterface.class);

public void method1(int arg1, AsyncCallback<Boolean> callback)
{
    service.method1(arg1, new CustomAsyncCallback<Boolean>(callback)) ;
}

public void method2 ....
public void method3 ....

}

【问题讨论】:

    标签: gwt exception-handling gwt-rpc


    【解决方案1】:

    为了包装传递给任何RemoteService 的每个AsynCallback&lt;T&gt;,您需要覆盖RemoteServiceProxy#doCreateRequestCallback(),因为在发生RPC 调用之前,每个AsynCallback&lt;T&gt; 都会在此处提交。

    以下是执行此操作的步骤:

    首先,您需要定义自己的代理生成器,以便在每次生成RemoteService 代理时介入。首先扩展 ServiceInterfaceProxyGenerator 并覆盖 #createProxyCreator()。

    /**
     * This Generator extends the default GWT {@link ServiceInterfaceProxyGenerator} and replaces it in the
     * co.company.MyModule GWT module for all types that are assignable to
     * {@link com.google.gwt.user.client.rpc.RemoteService}. Instead of the default GWT {@link ProxyCreator} it provides the
     * {@link MyProxyCreator}.
     */
    public class MyServiceInterfaceProxyGenerator extends ServiceInterfaceProxyGenerator {
        @Override
        protected ProxyCreator createProxyCreator(JClassType remoteService) {
            return new MyProxyCreator(remoteService);
        }
    }
    

    在您的 MyModule.gwt.xml 中,使用延迟绑定来指示 GWT 在生成 RemoteService 类型的内容时使用您的代理生成器进行编译:

    <generate-with 
       class="com.company.ourapp.rebind.rpc.MyServiceInterfaceProxyGenerator">
        <when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
    </generate-with>
    

    扩展ProxyCreator 并覆盖#getProxySupertype()。在MyServiceInterfaceProxyGenerator#createProxyCreator() 中使用它,这样您就可以为所有生成的RemoteServiceProxies 定义基类。

    /**
     * This proxy creator extends the default GWT {@link ProxyCreator} and replaces {@link RemoteServiceProxy} as base class
     * of proxies with {@link MyRemoteServiceProxy}.
     */
    public class MyProxyCreator extends ProxyCreator {
        public MyProxyCreator(JClassType serviceIntf) {
            super(serviceIntf);
        }
    
        @Override
        protected Class<? extends RemoteServiceProxy> getProxySupertype() {
            return MyRemoteServiceProxy.class;
        }
    }
    

    确保您的MyProxyCreator 和MyServiceInterfaceProxyGenerator 都位于不会被GWT 交叉编译成javascript 的包中。否则你会看到这样的错误:

    [ERROR] Line XX: No source code is available for type com.google.gwt.user.rebind.rpc.ProxyCreator; did you forget to inherit a required module?
    

    您现在可以扩展RemoteServiceProxy 并覆盖#doCreateRequestCallback()!在这里,您可以做任何您喜欢的事情,并将其应用于发送到您服务器的每个回调。确保将此类以及您在此处使用的任何其他类(在我的情况下为 AsyncCallbackProxy)添加到要交叉编译的客户端包中。

    /**
     * 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 AsyncCallbackProxy<T>(callback));
        }
    }
    

    现在,您的 AsyncCallbackProxy 可能看起来像这样:

    public class AsyncCallbackProxy<T> implements AsyncCallback<T> {
        private AsyncCallback<T> delegate;
    
        public AsyncCallbackProxy(AsyncCallback<T> delegate) {
            this.delegate = delegate;
        }
    
        @Override
        public final void onFailure(Throwable caught) {
            GWT.log("AsyncCallbackProxy#onFailure() : " + caught.getMessage(), caught);
    
            if (caught instanceof NotLoggedInException) {
                // Handle it here
            }
    
            delegate.onFailure(proxy);
        }
    
        @Override
        public final void onSuccess(T result) {
            delegate.onSuccess(result);
        }
    }
    

    参考资料:

    【讨论】:

    • 是的,这就是我要找的。如何为此目的使用生成器的一个例子是我认为需要回答这个问题。非常感谢。
    • 不适合我。我没有收到任何错误,但调用没有被拦截:/
    • 我 gwt 再次编译了项目,现在可以工作了。
    【解决方案2】:

    你可以用抽象类包装AsyncCallback类:

    public abstract class CustomAsyncCallback<T> implements AsyncCallback<T>{
    
        @Override
        public void onFailure(Throwable caught) {
            GWT.log(caught.getMessage());
            handleException();
    
            this.customOnFailure(yourDesireParam);
        }
    
        /**
         * this method is optional
         */
        public abstract void customOnFailure(Param yourDesireParam);
    }
    

    然后将CustomAsyncCallback 对象发送到您的 RPC 异步方法。

    【讨论】:

    • 感谢。在问题中,我确实提到了包装延迟绑定类。它看起来与您的方法相似,并且需要 CustomAsyncCallback,但对于使用 AsyncCallback 的所有情况(见上文),它都是透明的。您的方法更有效,因为您不需要创建虚拟包装器实例,但它需要在任何地方更改代码,如果我的团队意外覆盖 onFailure 它将使 CustomAsyncCallback 黯然失色(尽管可以最终确定)。理想情况下,我希望对 com.google.gwt.user.rebind.rpc.ProxyCreator 进行更改,但如果不熟悉,它看起来很麻烦。 :-)
    猜你喜欢
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 2022-11-30
    • 2022-08-04
    • 1970-01-01
    • 2011-05-13
    • 2019-02-15
    • 2012-04-18
    相关资源
    最近更新 更多