While developing GWT Remote Procedure Calls(RPC), many of you have experienced the limitations of the default GWT exception handling model. I will demonstrate this with a sample application. If you create the default GWT hello world application you will notice three RPC service classes being created for you:
interface GreetingServiceAsync {
void greetServer(String input, AsyncCallback<String> callback)
throws IllegalArgumentException;
}
@RemoteServiceRelativePath("greet")
interface GreetingService extends RemoteService {
String greetServer(String name) throws IllegalArgumentException;
}
class GreetingServiceImpl extends RemoteServiceServlet
implements GreetingService {
public String greetServer(String input) throws IllegalArgumentException {
{ // let's just throw an error for demonstration
throw new IllegalArgumentException ("Bad arguments passed");
}
}
}
So, the error handling works this way. GreetingServiceImpl captures an error and throws a runtime failure, in our case IllegalArgumentException. So far so good. But, what if we need to throw a different error. Let’s say MyIllegalArgumentException? Well by design (GWT design), we need to declare it on each three RPC methods:
interface GreetingServiceAsync {
void greetServer(String input, AsyncCallback<String> callback)
throws MyIllegalArgumentException;
}
@RemoteServiceRelativePath("greet")
interface GreetingService extends RemoteService {
String greetServer(String name) throws MyIllegalArgumentException;
}
class GreetingServiceImpl extends RemoteServiceServlet
implements GreetingService {
public String greetServer(String input) throws MyIllegalArgumentException{
{ // let's just throw an error for demonstration
throw new MyIllegalArgumentException("Bad arguments passed");
}
}
}
Which is not fun. It’s quite cumbersome. You need to declare the exception on each RPC method in 3 places – the Service, ServiceAsync and ServiceImp classes. To make the matter even worse as long as you have multiple methods and variety of exception types you end up into the “exception over-declaring hell” with methods looking this way myMethod() throws Exception1, Exception2, Exception3, Exception4 (and don’t forget, you need to declare this in three places – 3 RPC classes).
Being curious (and lazy) you may wonder what will happen if:
/* no exception being declared*/
greetServer(String input, AsyncCallback<String> callback)
class AnotherBusinessException extends IllegalArgumentException {
..
}
class GreetingServiceImpl extends RemoteServiceServlet
implements GreetingService {
public String greetServer(String input) throws IllegalArgumentException{
{ // let's just throw an error for demonstration
throw new AnotherBusinessException("Bad arguments passed");
}
}
- A. HTTP/1.1 500 Internal Error
[WARN] Exception while dispatching incoming RPC call com.google.gwt.user.server.rpc.UnexpectedException: Service method ‘public abstract java.lang.String GreetingService.greetServer(java.lang.String)’ threw an unexpected exception: java.lang.IllegalArgumentException.. - B. HTTP/1.1 500 Internal Error
[WARN] Exception while dispatching incoming RPC call com.google.gwt.user.client.rpc.SerializationException: Type ‘org.roussev.hello.client.AnotherBusinessException’ was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized…
All said, GWT exception handling forces us to declare all those business errors as part of the method signatures in all three RPC classes. And this is a tedious, error prone and repetitive process. Instead we (the lazy developers) are looking for more dynamic approach. We are looking for an approach where:
- An RPC Service method should not have to declare any runtime business failures.
- The server should handle the runtime business failures gracefully with 200 OK, instead of 500 Error
- And lastly, UI should receive the exact error type (not some gwt StatusCodeException or an UnexpectedException) directly into the consuming callback void onFailure(Throwable e).


3 Comments until now
Hello,
in fact, it is possible to make work case B. I have this exact mechanism used successfully in one GWT app. The exception you got for this case means that your exception class is not in one of the client package or does not implement the IsSerializable interface (in GWT 2.0).
I encountered the exact same problem, and all this is explained in the doc, but at the time, I found it difficult to find the information.
In my previosu comment, some text disappeared because of less than equal and greater than equal sign.
I was saying : does not implement the IsSerializable interface (in older versions of GWT) or the Serializable interface (in more recent versions).
Hi Martin,
Case B solution was outlined in my next post: http://www.roussev.org/2010/02/gwt-dynamic-exception-handling/ where I am demonstrating how to propagate exceptions to client without having to declare them anywhere. Probably you have more elegant solution? At that time I wrote the code there were no information so I had to extend GWT RemoteServiceServlet to achieve more dynamic approach.
Add your Comment!