In my GWT project, I created an elaborate design for an exception chain to be thrown in service calls, only to discover that the getCause() always returns null in a client’s onFailure() method.
After debugging through GWT serialization code, I found this code in SerializabilityUtil:
private static boolean fieldQualifiesForSerialization(Field field) {
if (Throwable.class == field.getDeclaringClass()) {
/**
* Only serialize Throwable's detailMessage field; all others are ignored.
*
* NOTE: Changing the set of fields that we serialize for Throwable will
* necessitate a change to our JRE emulation's version of Throwable.
*/
if ("detailMessage".equals(field.getName())) {
assert (isNotStaticTransientOrFinal(field));
return true;
} else {
return false;
}
} else {
return isNotStaticTransientOrFinal(field);
}
}
Can anyone help me here, why would GWT designers put this in their code? Is there something really wrong (or security sensitive) with Throwable.cause?
And that taken for granted, how can I tell GWT serialization to make an exception for my exception class?
Note the comments in the code that say
Changing the set of fields that we serialize for Throwable will necessitate a change to our JRE emulation's version of Throwable.That’s why the code is there, because Throwable is Java, not Javascript, and as such, whatever is serialized to be caught at the client end must be compatible with GWT’s Javascript implementation of JRE classes. Look up GWT JRE Emulation Reference for more info.(Note that they might have attempted to be more aggressive in implementing Throwable sub-classes on the client side, but even if they did, they would still have no way to ensure that, say, some third party library’s exceptions would be present, and that would break the client-side deserialization.)
I too have a rather elaborate exception chain, in my project. What I did is I made sure to preserve the message, rather than the cause, in all my exception object constructors. Unfortunately, some Java exceptions are, shall we say, less than verbose with regards to their message, as opposed to C#, for instance. NullPointerException, for example, has an altogether empty message, whereas ArrayIndexOutOfBoundsException just has a number. So, I took care to embed the name of the cause exception in the message, in my constructors.
It’s not perfect, but it works.