2

私のアプリには多くの RPC 呼び出しがあり、それらすべてに .onFailure(Throwable catch) メソッドがあります。クライアントとサーバー コード NotLoggedInException の間で共有されるクラスがあります。これは、ユーザーがセッション/Cookie/権限などに基づいて関連する権限を持っていない場合に、サーバーによってスローされます。

理想的には、この例外が .onFailure() コードに渡される前に、この例外を 1 つの場所で処理したいと考えています。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) ;
}

}

public class WrapDeferredBinding implements RpcInterfaceAsync { RpcInterfaceAsync service = 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 ....

}

4

2 に答える 2

9

AsynCallback<T>any に渡されたeveryをラップするにはRemoteService、オーバーライドする必要があります。RemoteServiceProxy#doCreateRequestCallback()AsynCallback<T>

これを行う手順は次のとおりです。

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

参考文献:

于 2013-07-04T15:58:21.423 に答える
1

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非同期メソッドに送信します。

于 2013-01-15T04:44:28.337 に答える