如何在一个地方包装每个回调以改进错误处理

时间:2013-07-01 09:33:55

标签: gwt callback gwt-rpc

在我的GWT应用程序中,使用许多不同的服务对服务器进行了许多不同的异步调用。为了做更好的错误处理,我想包装所有的回调,以便我可以在一个地方处理InvocationExceptions之类的异常。实现AsyncCallback的超类实际上不是一个选项,因为这意味着我必须修改每个异步调用。

RpcServiceProxy#doCreateRequestCallback()看起来像是要覆盖的方法。很简单。我只是看不出如何让GWT使用我的新课程。

陈述问题的另一种方式是

  

如何让GWT使用我自己的RpcServiceProxy的子类?

4 个答案:

答案 0 :(得分:8)

为了包装传递给任何AsynCallback<T>的每个RemoteService,您需要覆盖RemoteServiceProxy#doCreateRequestCallback(),因为在发生RPC调用之前,每个AsynCallback<T>都会被传递。< / p>

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

正如@ChrisLercher所提到的,您需要定义自己的代理生成器,以便在每次生成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;
    }
}

确保您的MyProxyCreatorMyServiceInterfaceProxyGenerator位于不会被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));
    }
}

参考文献:

答案 1 :(得分:2)

您正在寻找的类型可能是RemoteServiceProxy(不是RpcServiceProxy),我认为您应该首先覆盖/com/google/gwt/user/RemoteService.gwt.xml中的默认绑定(只需复制这些行)到您自己的.gwt.xml文件并调整):

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

您会找到protected Class<? extends RemoteServiceProxy> getProxySupertype(),您可以覆盖它以返回自己的RemoteServiceProxy课程。

尚未尝试过,所以这可能还需要一些额外的步骤......

答案 2 :(得分:0)

通常,GWT处理异步进程中发生的异常的方式是UncaughtExceptionHandler s。

我会使用自己的处理程序来管理这些异常:

GWT.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
  public void onUncaughtException(Throwable e) {
    if (e instanceof WhateverException) {
      // handle the exception here
    }        
  }
});

使用它你不需要继承任何东西。

答案 3 :(得分:0)

如果“一个地方”的意思是“我想在一种方法中处理所有错误”,那么我会建议捕捉和扔东西,直到它们在一个地方或创建EventBus你基本上只是发送每个错误。然后你就可以在这条总线上安装一个可以处理所有事情的处理程序。