Mar 10, 2011

Why Care About Exception Chaining in Java

Why Should You Care About Chained Exceptions

Note: If you don't have the time and energy to read the details, execute the two programs in the post and learn what exception chaining is all about.

The exception chaining terminology may be new to a few Java developers of Enterprise Java Applications but we all have seen chained exceptions at some point of time. 

I have seen many sources on the internet before posting this article and no article brings out the main point to remember about exception chaining. 
The most important thing to remember about Exception chaining is that we need to use the constructor of the exception classes which accepts a parameter of type Throwable so that it can keep a reference to the exception which was the cause of this exception.

Definition of Exception Chaining:
The definition of chained exceptions is that when the occurrence of one exception raises another exception then the stack trace of second exception should also include the root exception in the application logs.

Few points to remember about Chained Exceptions are:
1) Java does magic in order to support Exception Chaining but it is also the responsibility of the developer to have proper exception chaining mechanism in place in any Java based application. The application needs to be coded so as to support exception chaining.

2) If the developer doesn't take any action to have chained exception in his program, the root exceptions are lost. No exception chaining code, no chained exceptions seen.

3) Chained exceptions are different from the stack trace that we see when an exception occurs which prints the method names which we were invoked before the exception was thrown (in other words, the method stack trace)

4) Exception Chaining is internally supported by Java by storing a reference to the root exception has a member field cause which was added in JDK 1.4 and looks like:
private Throwable cause = this; (inside Throwable.java class)

5) The methods which are provided by Java in order to only support exception chaining are
Throwable getCause()
Throwable initCause(Throwable)
Throwable(String, Throwable)
Throwable(Throwable)
Throwable printStackTrace(); 
The basic and important point to keep in mind about chained exception is that we need to write a custom exception
class which can accept an argument of type Throwable in is constructor and can invoke the super class's constructor
with the parameters passed to its constructor. This will become more clear with two examples:

Without any Exception Chaining mechanism in place:

package com.example;

class MyException extends Exception {  //Custom Exception class
    public MyException (String msg) {
        super(msg);
    } 
}

public class Test {
 
    static int a[] = {1,2,3};

    public static void main(String[] args) {

        try {
            System.out.println(a[4]);   //Deliberate ArrayIndexOutOfBoundsException
 } catch (ArrayIndexOutOfBoundsException ae) {
     try {
         throw new MyException("Exception Occured");  //throw custom exception
     } catch (MyException me) {
         me.printStackTrace();
     }
        }
    }
}

Output:
com.example.MyException: Exception Occured
 at com.example.Test.main(Test.java:20)
With Exception Chaining mechanism in place:

package com.example;

class MyException extends Exception {  //Custom Exception class
    public MyException (String msg, Throwable ex) {
        super(msg, ex);
    } 
}

public class Test {

    static int a[] = {1,2,3};

    public static void main(String[] args) {

        try {
            System.out.println(a[4]);   //Deliberate ArrayIndexOutOfBoundsException
        } catch (ArrayIndexOutOfBoundsException ae) {
            try {
                throw new MyException("Exception Occured",ae);  //throw custom exception
            } catch (MyException me) {
                me.printStackTrace();
            }
        }
    }
}

Output:

com.example.MyException: Exception Occured
 at com.example.Test.main(Test.java:19)
Caused by: java.lang.ArrayIndexOutOfBoundsException: 4
 at com.example.Test.main(Test.java:16)

Please note that the use of custom exception in above examples is for demonstration only. It could be any JDK exception class like IllegalArgumentException, ClassNotFoundException or IllegalStateException.

Hope you enjoyed this blog post.

2 comments:

  1. Very nice post Sandeep. Indeed its important concept which most often overlooked. thanks for the code as well which makes things quite easy to understand.

    Javin
    Why String is immutable in Java

    ReplyDelete
  2. public class exceptionTest {

    public static void main(String[] args) throws SampleException {

    try {
    throw new ArrayIndexOutOfBoundsException();
    } catch (ArrayIndexOutOfBoundsException e) {
    throw new SampleException("custom exception", e);
    }
    }


    private static class SampleException extends Exception {
    public SampleException(String s, Throwable ex) {
    super(s, ex);
    }
    }
    }

    ReplyDelete