Friends, we have been using exception handling in our code for almost every industry standard application. Usual approach is to create some custom Exception classes extending the base Exception class. In this post, I will suggest another approach which might make you more sense.
This post is part of series related to best practices and mini guides.
Sections in this post:
- Our new approach
- Advantages
Our new approach
Probably some of us are already using this mechanism. If you are one of them, then please review this post and suggest the improvements. Otherwise, learn about this mechanism and give your feedback.
Our new approach uses static inner classes for every new exceptional scenario. Traditionally, we create a DBException class by extending Exception class. Now, every time we are caught in a situation where there needs to thrown exception, we usually create an instance of this class, put some information in form of message and throw it.
Now, lets consider there are following situations we have identified in which we need to throw DBException:
- SQL execution error
- No data exist where we expect at least one row
- Multiple rows exist where we expect only single row
- Invalid parameters error
and many more such cases can exist.
Different with our traditional approach, let try our new approach i.e. create static inner classes.
Lets start with BaseException class which is created as abstract and will be super class of all our exception classes.
// Make this class abstract so that developers are forced to create
// suitable exception types only
public abstract class BaseException extends Exception{
//Each exception message will be hold here
private String message;
public BaseException(String msg)
{
this.message = msg;
}
//Message can be retrieved using this accessor method
public String getMessage() {
return message;
}
}
Not its time to create out new Exception inner classes. Let hit the keyboard.
public class DBExeption
{
//SQL execution error
public static class BadExecution extends BaseException
{
private static final long serialVersionUID = 3555714415375055302L;
public BadExecution(String msg) {
super(msg);
}
}
//No data exist where we expect at least one row
public static class NoData extends BaseException
{
private static final long serialVersionUID = 8777415230393628334L;
public NoData(String msg) {
super(msg);
}
}
//Multiple rows exist where we expect only single row
public static class MoreData extends BaseException
{
private static final long serialVersionUID = -3987707665150073980L;
public MoreData(String msg) {
super(msg);
}
}
//Invalid parameters error
public static class InvalidParam extends BaseException
{
private static final long serialVersionUID = 4235225697094262603L;
public InvalidParam(String msg) {
super(msg);
}
}
}
Here, we created an inner class for each possible error scenario identified in starting. There can be many more extra. It depends on you only to identify and add more classes.
Let see how these classes look like in log files.
public class TestExceptions {
public static void main(String[] args)
{
try
{
throw new DBExeption.NoData("No row found for id : x");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Output:
com.exception.DBExeption$NoData: No row found for id : x
at com.test.TestExceptions.main(TestExceptions.java:7)
As you can see the log message in exception stack trace, if has become more informative.
Advantages of using inner classes
- Foremost advantage is that if you developer has written some doubtful message text, then also you can clearly observe that what was actually wrong.
- You can use instance-of comparison in different situation where you handle different exceptional scenarios.
- You don’t need to send single exception for a large set of exceptional conditions.
- Its easy to write unit test cases for negative cases where you know the exact exception class, you should expect.
- Logging is more meaningful and informative.
I hope this post has been some informative for you. If you have some suggestions, please write to me.
Happy Learning !!

Discussion
Trackbacks/Pingbacks
[...] some of your test cases expect the exceptions to be thrown from application, then use “expected” attribute like this. Do not catch [...]