As you can see, each abstraction layer defines its own exception classes. When code in a layer throws an exception, the higher layer re-throws it under a new type of exception which corresponds to the abstraction level of that layer. In turn, the next higher layer re-throws the exception under its own type of exception, and so on. This process continues until a layer handles the exception instead of re-throwing. During this chaining process, the higher exception always wraps the lower exception as its cause. Therefore, when an exception occurs, the programmer has a complete stack trace of the exceptions, which is very helpful for debugging. public void setBirthday(String birthDate) throws InvalidBirthdayException {
DateFormat formatter = new SimpleDateFormat();
try {
Date birthday = formatter.parse(birthDate);
} catch (ParseException ex) {
throw new InvalidBirthdayException("Date of birth is invalid", ex);
}
}As you can see in the setBirthday() method, the ParseException is re-thrown under a new exception called InvalidBirthdayException. The ParseException is chained via the constructor of InvalidBirthdayException class:throw new InvalidBirthdayException("Date of birth is invalid", ex);This custom exception is implemented as following:public class InvalidBirthdayException extends Exception {
public InvalidBirthdayException(String message, Throwable cause) {
super(message, cause);
}
}You can notice that, this constructor invokes its super’s constructor:super(message, cause);The supertypes of all exceptions Throwable and Exception implement this constructor, so any custom exceptions can call it. The origin exception (the cause) is passed to the being-created exception via its constructor.Remember that the Exception class provides the following constructors that help chaining an exception:
public Throwable initCause(Throwable cause)
That’s how exceptions are chained together. Let’s see another example which is illustrated by the following picture:
And following is source code of each class.DAOException.java:public class DAOException extends Exception {
public DAOException(String message, Throwable cause) {
super(message, cause);
}
} StudentException.java:public class StudentException extends Exception {
public StudentException(String message) {
super(message);
}
public StudentException(String message, Throwable cause) {
super(message, cause);
}
} DatabaseUtils.java:import java.sql.*;
public class DatabaseUtils {
public static void executeQuery(String sql) throws SQLException {
throw new SQLException("Syntax Error");
}
} StudentDAO.java:import java.sql.*;
public class StudentDAO {
public void list() throws DAOException {
try {
DatabaseUtils.executeQuery("SELECT");
} catch (SQLException ex) {
throw new DAOException("Error querying students from database", ex);
}
}
} StudentManager.java:public class StudentManager {
private StudentDAO dao;
public StudentManager(StudentDAO dao) {
this.dao = dao;
}
public void findStudents(String keyword) throws StudentException {
try {
dao.list();
} catch (DAOException ex) {
throw new StudentException("Error finding students", ex);
}
}
} StudentProgram.java:public class StudentProgram {
public static void main(String[] args) {
StudentDAO dao = new StudentDAO();
StudentManager manager = new StudentManager(dao);
try {
manager.findStudents("Tom");
} catch (StudentException ex) {
ex.printStackTrace();
}
}
} Run the StudentProgram and you should see the following output:StudentException: Error finding students
at StudentManager.findStudents(StudentManager.java:13)
at StudentProgram.main(StudentProgram.java:9)
Caused by: DAOException: Error querying students from database
at StudentDAO.list(StudentDAO.java:11)
at StudentManager.findStudents(StudentManager.java:11)
... 1 more
Caused by: java.sql.SQLException: Syntax Error
at DatabaseUtils.executeQuery(DatabaseUtils.java:5)
at StudentDAO.list(StudentDAO.java:8)
... 2 moreYou see? The printed exception stack trace reveals an exception propagates from the DatabaseUtils layer up to the StudentProgram layer in which the exception is handled by printing this trace.Now, let rewrite, compile and run the example to experiment the exception chaining yourself.
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.