There are various reasons when we have to wrap java exceptions. Often those reasons are called: Checked Exceptions. According to the definition there are 2 types of exceptions:
- Checked Exceptions – Exceptions that are not descending from RuntimeException are called checked exceptions. Checked exceptions must be handled by a try catch mechanism or by adding the throws declaration to the method. If neither of those is done then the compiler throws an exception.
- Unchecked Exceptions – The exceptions that are not checked, of course. They are inherited from RuntimeException and no handling is enforced by the compiler. Simply put you don’t have to check them.
In practice using checked exceptions will lead to undesired behavior. Here are a few scenarios:
Let’s assume we have to use a method called getProperty(String key) throws SQLException defined in DBConfig to read a color property from the database and then to display it on screen. We instantiate the config object and then invoke the method. For avoiding a compiler exception we’ll add a throws SQLException to our method declaration. And then imagine that you have to add another one to the method invoking the method we wrote. The more mothods are involved the more checked exceptions added to the method declaration. It doesn’t make sense for a method called paintScreen to force you to handle excpetions like SQLException or IOException, doesn’t it?
Now we are going to add an interface named IConfig. We’ll have the existing class DBConfig and we’ll create another one FileConfig. The first one will throw SQLException and the second one IOException. If we’ll have too many checked exceptions we’ll pollute the interface with exceptions that might depend on implementation, inducing a tight coupling in our classes: the abstraction depends on modules exceptions. Pretty bad, isn’t it?
Now the bad practice: We’ll not going to use throws declaration. Not at all, because it generates too many problems. So let’s just try, catch, printstacktrace and that’s it. We’ll see later what to do. This is fast. This practice is again bad, because it just hide the problems. Especially in large applications with many programmers they tend to forget about the caught exceptions and real problems are not discovered. After all remember that exceptions are meant to signal a real abnormal behavior of the application.
There is also another reason that make us wrapping exceptions which is not related to checked or unchecked exceptions. Sometimes we simply want to hide and separate the implementation details from the exposed interface in order to reduce the complexity and to simplify the interface.
Ok, then. But How?
We have 2 simple options:
- To wrap the exceptions in such a way that the original exception object is not used.and only the message as String is encapsulated in the new exception.
- Create another exception that contains references to the thrown exception
There is a very thin line between those 2 options and you have to understand it very well. First of all let’s think about it. The module which invokes the code throwing exceptions will have the wrapped class in the class path? If the response is definitely an yes then go for second point, otherwise choose the first one.
For example a client invokes remotely your api using rmi. The api throws the exception wrapped but the client have only the wrapper exception class in the classpath, not the wrapped one. An exception will be thrown. In cases like this one runtime exception should be created containing a descriptive message and should not wrap the original exception.