Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the advantage of chained exceptions

I do not understand the advantages of having a chained exception in the code.

Considering the ResourceLoader example from java world, if the programmer knows of a possibility of encountering ResourceLoadException , why not catch the same exception instead of SQLException? Else, the programmer can catch both the exceptions in the same code than having to throw a new Throwable instance?

like image 528
name_masked Avatar asked Feb 16 '11 19:02

name_masked


2 Answers

Can anyone please provide information on the need for chained exceptions?

The article says it quite well:

Exception chaining allows you to map one exception type to another, so that a method can throw exceptions defined at the same abstraction level as the method itself, without discarding important debugging information.

That is, if you have a method that loads some object from a database, you may rather want some ResourceLoadException (closer related to the methods abstraction level) instead of a low-level SQLException even if that was the original source of the problem. However, if you simply catch the SQLException and throw a ResourceLoadException instead, you may loose important debugging information.

Thus, chaining the exceptions is a good alternative. You throw a "high-level" exception, well suited for the particular method, but chain it with the exception that caused it.

Else, the programmer can catch both the exceptions in the same code than having to throw a new Throwable instance?

I don't quite follow your reasoning here. The point is that he should not need to worry about the SQLException at this level of abstraction.

like image 167
aioobe Avatar answered Sep 28 '22 08:09

aioobe


Why Chain exception?

We need to chain the exceptions to make logs readable.

Take following examples of 1. without chaining and 2. chaining, exceptions to feel the difference

Create following Exceptions

    class NoLeaveGrantedException extends Exception {

        public NoLeaveGrantedException(String message, Throwable cause) {
            super(message, cause);
        }

        public NoLeaveGrantedException(String message) {
            super(message);
        }
    }

    class TeamLeadUpsetException extends Exception {

        public TeamLeadUpsetException(String message, Throwable cause) {
            super(message, cause);
        }

        public TeamLeadUpsetException(String message) {
            super(message);
        }
    }

    class ManagerUpsetException extends Exception {

        public ManagerUpsetException(String message, Throwable cause) {
            super(message, cause);
        }

        public ManagerUpsetException(String message) {
            super(message);
        }
    }

    class GirlFriendOfManagerUpsetException extends Exception {

        public GirlFriendOfManagerUpsetException(String message, Throwable cause) {
            super(message, cause);
        }

        public GirlFriendOfManagerUpsetException(String message) {
            super(message);
        }
    }

Now use them

1. Without chaining

    public class MainClass {

        public static void main(String[] args) throws Exception {
            getLeave();
        }

        static void getLeave() throws NoLeaveGrantedException {
            try {
                howIsTeamLead();
            } catch (TeamLeadUpsetException e) {
                e.printStackTrace();
                throw new NoLeaveGrantedException("Leave not sanctioned.");
            }
        }

        static void howIsTeamLead() throws TeamLeadUpsetException {
            try {
                howIsManager();
            } catch (ManagerUpsetException e) {
                e.printStackTrace();
                throw new TeamLeadUpsetException(
                            "Team lead is not in good mood");
            }
        }

        static void howIsManager() throws ManagerUpsetException {
            try {
                howIsGirlFriendOfManager();
            } catch (GirlFriendOfManagerUpsetException e) {
                e.printStackTrace();
                throw new ManagerUpsetException("Manager is in bad mood");
            }

        }

        static void howIsGirlFriendOfManager() 
             throws GirlFriendOfManagerUpsetException {
            throw new GirlFriendOfManagerUpsetException(
             "Girl friend of manager is in bad mood");
        }
    }

2. Chaining

    public class MainClass {

        public static void main(String[] args) throws Exception {
            getLeave();
        }

        static void getLeave() throws NoLeaveGrantedException {
            try {
                howIsTeamLead();
            } catch (TeamLeadUpsetException e) {
                throw new NoLeaveGrantedException("Leave not sanctioned.", e);
            }
        }

        static void howIsTeamLead() throws TeamLeadUpsetException {
            try {
                howIsManager();
            } catch (ManagerUpsetException e) {
                throw new TeamLeadUpsetException(
                           "Team lead is not in good mood", e);
            }
        }

        static void howIsManager() throws ManagerUpsetException {
            try {
                howIsGirlFriendOfManager();
            } catch (GirlFriendOfManagerUpsetException e) {
                throw new ManagerUpsetException("Manager is in bad mood", e);
            }

        }

        static void howIsGirlFriendOfManager() 
           throws GirlFriendOfManagerUpsetException {
            throw new GirlFriendOfManagerUpsetException(
              "Girl friend of manager is in bad mood");
        }
    }

Now compare logs

1. Without chaining

    com.bskyb.svod.autoingest.GirlFriendOfManagerUpsetException: Girl friend of manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsGirlFriendOfManager(MainClass.java:61)
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:52)
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:43)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    com.bskyb.svod.autoingest.ManagerUpsetException: Manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:55)
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:43)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    com.bskyb.svod.autoingest.TeamLeadUpsetException: Team lead is not in good mood
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:46)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    Exception in thread "main" com.bskyb.svod.autoingest.NoLeaveGrantedException: Leave not sanctioned.
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:37)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)

2. Chaining

    Exception in thread "main" com.bskyb.svod.autoingest.NoLeaveGrantedException: Leave not sanctioned.
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:36)
        at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
    Caused by: com.bskyb.svod.autoingest.TeamLeadUpsetException: Team lead is not in good mood
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:44)
        at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
        ... 1 more
    Caused by: com.bskyb.svod.autoingest.ManagerUpsetException: Manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:52)
        at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:42)
        ... 2 more
    Caused by: com.bskyb.svod.autoingest.GirlFriendOfManagerUpsetException: Girl friend of manager is in bad mood
        at com.bskyb.svod.autoingest.MainClass.howIsGirlFriendOfManager(MainClass.java:58)
        at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:50)
        ... 3 more
like image 35
Kalher Avatar answered Sep 28 '22 08:09

Kalher