Throughout my GWT app there are many different async calls to the server, using many different services. In order to do better error handling I want to wrap all my callbacks so that I can handle exceptions like InvocationExceptions
in one place. A super class implementing AsyncCallback
isn't really an option because that would mean that I would have to modify every async call.
RpcServiceProxy#doCreateRequestCallback()
looks like the method to override. Simple enough. I just can't see how to make GWT use my new class.
Another way to state the question would be
How do I make GWT use my own subclass of
RpcServiceProxy
?
In order to wrap every AsynCallback<T>
that is passed to any RemoteService
you need to override RemoteServiceProxy#doCreateRequestCallback()
because every AsynCallback<T>
is handed in here before an RPC call happens.
As @ChrisLercher alluded, you need to define your own Proxy Generator to step in every time a RemoteService
proxy gets generated. Start by extending ServiceInterfaceProxyGenerator
and overriding #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);
}
}
In your MyModule.gwt.xml
make use of deferred binding to instruct GWT to compile using your Proxy Generator whenever it generates something of the type RemoteService
:
<generate-with
class="com.company.ourapp.rebind.rpc.MyServiceInterfaceProxyGenerator">
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
Extend ProxyCreator
and override #getProxySupertype()
. Use it in MyServiceInterfaceProxyGenerator#createProxyCreator()
so that you can define the base class for all the generated 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;
}
}
Make sure both your MyProxyCreator
and your MyServiceInterfaceProxyGenerator
are located in a package that will not get cross-compiled by GWT into javascript. Otherwise you will see an error like this:
[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?
You are now ready to extend RemoteServiceProxy
and override #doCreateRequestCallback()
! Here you can do anything you like and apply it to every callback that goes to your server. Make sure that you add this class, and any other class you use here, in my case AsyncCallbackProxy
, to your client package to be cross-compiled.
/**
* 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));
}
}
References:
The type you're looking for is probably RemoteServiceProxy
(not RpcServiceProxy
), and I assume, that you should start with overriding the default binding in /com/google/gwt/user/RemoteService.gwt.xml
(just copy the lines to your own .gwt.xml file and adjust):
<generate-with
class="com.google.gwt.user.rebind.rpc.ServiceInterfaceProxyGenerator">
<when-type-assignable class="com.google.gwt.user.client.rpc.RemoteService"/>
</generate-with>
There you'll find protected Class<? extends RemoteServiceProxy> getProxySupertype()
, which you can override to return your own RemoteServiceProxy
class.
Haven't tried it yet, so this may need a few additional steps...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With