Effective Approach for Creating Custom Exceptions in Java

We have been using handling Java custom exceptions in our code for almost every industry standard application. The usual approach is to create some custom exception classes extending the base exception handling best practice which might make more sense.

1. Traditional Approach

Suppose we are creating a custom exception DBException for representing the exceptions that occurred during the database-related operations. Traditionally, we create a DBException class by extending Exception class.

public class DBException extends Exception {

  public DBException() {
    super();
  }

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

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

Now, every time we are caught in a situation where there is a need to throw a database-related exception, we usually create an instance of DBException, put some information in form of a message and throw it.

Now, let’s 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 a single row
  • Invalid parameters error
  • and many more such cases

The problem with the above approach is that in catch block or in application code where these exceptions shall be handled, DBException does not provide enough information to handle each above-listed usecases, uniquely.

2. New Approach using Inner Classes

Our new approach uses static inner classes for every new exceptional scenario.

2.1. Create New Exception Types

Let’s solve the above problem with inner classes where we will create one class per use-case, and then group them inside DBException class.

Let us start with BaseException class which is created as an abstract and will be the superclass of all our exception classes.

public abstract class BaseException extends Exception {

  private String message;

  public BaseException(String msg) {
    super(msg);
    this.message = msg;
  }

  public String getMessage() {
    return message;
  }
}

Now it is time to create out new Exception inner classes.

public class DBException {

  //SQL execution error
  public static class BadExecution extends BaseException {

    public BadExecution(String msg) {
      super(msg);
    }
  }

  //No data exist where we expect at least one row
  public static class NoData extends BaseException {

    public NoData(String msg) {
      super(msg);
    }
  }

  //Multiple rows exist where we expect only single row
  public static class MoreData extends BaseException {

    public MoreData(String msg) {
      super(msg);
    }
  }

  //Invalid parameters error
  public static class InvalidParam extends BaseException {

    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 extras. It depends on you only to identify and add more classes.

2.2. How to use custom exceptions?

Now to understand its usefulness, let’s create an exception and throw it. Then we will see the error message in the logs.

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();
		}
	}
}

Program 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 the exception stack trace has become more informative. It clearly tells what the error is. In the application code as well, you can check the instance of custom exception and handle it accordingly.

3. Advantages

  • The foremost advantage is that if the developer has written some doubtful message text, then also he can clearly observe what was actually wrong.
  • You can use instance-of comparison in different situations where you handle different exceptional scenarios.
  • You don’t need to send a single exception for a large set of exceptional conditions.
  • It is 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 about Java custom exceptions has been some information for you. If you have some suggestions, please write to me.

Happy Learning !!

Comments

Subscribe
Notify of
guest
17 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode