Serializing exceptions

Showing 1-3 of 3 messages
Serializing exceptions Jérôme 9/13/10 6:44 AM
Hi everyone,

I just started using GSon for a project I am woking on.
I have a strange problem, for which I found nothing on the web :
Whenever I try to serialize an exception, GSon raises an
IllegalStateException with message :
circular reference error
Offending field: cause

Here is the code I have to reproduce this :

Gson serializer = new GsonBuilder().create();
Exception theException = new Exception();
String result = serializer.toJson(theException);

Pretty simple.
In such a case, theException.getCause() returns null, but the debugger
tells me that the cause field points to the exception itself,
therefore causing a circular reference.

I am a bit lost. Is this normal, and if so, how can I handle
Exception's serialization ?

Thanks for your help !
Re: [google-gson:763]: Serializing exceptions Pawel 9/13/10 11:21 AM
Well, from the source code of java.lang.Throwable (file version 1.56,
from some SDK 1.6):

...
    /**
     * The throwable that caused this throwable to get thrown, or null if this
     * throwable was not caused by another throwable, or if the causative
     * throwable is unknown.  If this field is equal to this throwable itself,
     * it indicates that the cause of this throwable has not yet been
     * initialized.
     *
     * @serial
     * @since 1.4
     */
    private Throwable cause = this;
...

Also:

    /**
     * Initializes the <i>cause</i> of this throwable to the specified value.
     * (The cause is the throwable that caused this throwable to get thrown.)
     *
     * <p>This method can be called at most once.  It is generally called from
     * within the constructor, or immediately after creating the
     * throwable.  If this throwable was created
     * with {@link #Throwable(Throwable)} or
     * {@link #Throwable(String,Throwable)}, this method cannot be called
     * even once.
     *
     * @param  cause the cause (which is saved for later retrieval by the
     *         {@link #getCause()} method).  (A <tt>null</tt> value is
     *         permitted, and indicates that the cause is nonexistent or
     *         unknown.)
     * @return  a reference to this <code>Throwable</code> instance.
     * @throws IllegalArgumentException if <code>cause</code> is this
     *         throwable.  (A throwable cannot be its own cause.)
     * @throws IllegalStateException if this throwable was
     *         created with {@link #Throwable(Throwable)} or
     *         {@link #Throwable(String,Throwable)}, or this method has already
     *         been called on this throwable.
     * @since  1.4
     */
    public synchronized Throwable initCause(Throwable cause) {
        if (this.cause != this)
            throw new IllegalStateException("Can't overwrite cause");
        if (cause == this)
            throw new IllegalArgumentException("Self-causation not permitted");
        this.cause = cause;
        return this;
    }
...

So, you have three (exclusive) choices:

1) If you are serializing your own exceptions, modify all of your
exceptions to set the cause to null, or to passed parameter upon
constructing.
2) Call initCause(null) on any exceptions returning (null) from
getCause() (may end up getting some IllegalStateExceptions here)
3) Write your own Serializer that would call getCause() rather than
attempting to dereference "cause" field.

Also, attempting to send serialized exception code over the wire may
be somewhat of a unorthodox design choice.

Thanks,
  Pawel.

> --
> You received this message because you are subscribed to the Google Groups "google-gson" group.
> To post to this group, send email to googl...@googlegroups.com.
> To unsubscribe from this group, send email to google-gson...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/google-gson?hl=en.
>
>

--
With best of best regards
Pawel S. Veselov

Re: : Serializing exceptions Jérôme 9/14/10 6:37 AM
Oups, I did not thought looking at Throwable's sources.

My idea was to serialize the exception in case of service failure, to
embed the message giving details on why the service failed in the
response.
The workaround I used is to extract the message, and send it instead
of the exception.

Thanks for your help. Next time, i will dig a bit more before
posting :-).