DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Getting Started With JMS-ActiveMQ: Explained in a Simple Way
  • Jakarta NoSQL 1.0: A Way To Bring Java and NoSQL Together
  • How to Get Word Document Form Values Using Java
  • Build a REST API With Just 2 Classes in Java and Quarkus

Trending

  • Key Considerations in Cross-Model Migration
  • Beyond Microservices: The Emerging Post-Monolith Architecture for 2025
  • Scaling in Practice: Caching and Rate-Limiting With Redis and Next.js
  • Medallion Architecture: Efficient Batch and Stream Processing Data Pipelines With Azure Databricks and Delta Lake
  1. DZone
  2. Data Engineering
  3. Databases
  4. Implementing Custom Exceptions in Java

Implementing Custom Exceptions in Java

Learn why, when, and how to use custom exceptions in Java projects, including best practices, coding techniques, and tips for documentation.

By 
Thorben Janssen user avatar
Thorben Janssen
·
Nov. 13, 17 · Tutorial
Likes (33)
Comment
Save
Tweet
Share
107.0K Views

Join the DZone community and get the full member experience.

Join For Free

We already talked a lot about exception handling on this blog and described the differences between checked and unchecked exceptions, best practices, and common mistakes. If you’ve read these posts, you probably recognized a pattern. You should provide detailed information about the situation that caused the exception, and you should not remove anything that might be useful to the caller.

You often can achieve that by using standard exceptions with good messages. The Java Exception class describes the kind of event, and the message provides detailed information about it. You can take this concept one step further by using a custom exception.

Custom exceptions provide you the flexibility to add attributes and methods that are not part of a standard Java exception. These can store additional information, like an application-specific error code, or provide utility methods that can be used to handle or present the exception to a user.

4 Best Practices for Custom Exceptions

There are 4 general best practices that you should follow when you decide to implement a custom exception class. These recommendations make your code and API easier to understand. They also reduce the required amount of documentation. That quickly pays off if multiple developers work on the same application or library, new team members join your project, or a third-party software vendor decides to use your APIs.

1. Always Provide a Benefit

The previously described examples for additional attributes or methods showed the intention of a custom exception. It provides information or functionality that is not part of Java’s standard exceptions.

That’s the essence of the first and most important recommendation. Otherwise, your exception doesn’t provide any benefit compared to the vast number of exceptions that are already provided by the JDK.

If you can’t provide any benefits, you should better use one of the standard exceptions, like UnsupportedOperationException or IllegalArgumentException. All Java developers already know these exceptions. That makes your code and API easier to understand.

2. Follow the Naming Convention

When you take a look at the exception classes provided by the JDK, you quickly recognize that all of their names end with “Exception”. This general naming convention is used throughout the Java ecosystem. And your custom exception should follow it as well.

3. Provide Javadoc Comments for Your Exception Class

We shouldn’t need to talk about this best practice, but I have seen way too many custom exceptions without any Javadoc.

It’s a general best practice to document all classes, fields, constructors, and methods of your API. If you ever had to use an undocumented API, you know exactly why. Undocumented APIs are very difficult to use.

Exception classes might not be the most obvious part of your API, but they are still part of it. As soon as one of your client-facing methods throws an exception, the exception class becomes part of the API. That implies that it requires documentation and a good Javadoc.

The Javadoc should describe the general meaning of the exception and the situations in which it might occur. The goal is to help other developers to understand your API and to avoid common error scenarios.

/**
 * The MyBusinessException wraps all checked standard Java exception and enriches them with a custom error code.
 * You can use this code to retrieve localized error messages and to link to our online documentation.
 * 
 * @author TJanssen
 */
public class MyBusinessException extends Exception { ... }


4. Provide a Constructor That Sets the Cause

Quite often, your code catches a standard exception before you throw your custom exception. You should not hide this fact. The caught exception usually contains essential information that you will need to analyze a production incident.

In the following example, the NumberFormatException provides detailed information about the error. You will lose this information if you don’t set it as the cause of the MyBusinessException.

public void wrapException(String input) throws MyBusinessException {
    try {
        // do something
    } catch (NumberFormatException e) {
        throw new MyBusinessException("A message that describes the error.", e, ErrorCode.INVALID_PORT_CONFIGURATION);
    }
}


Exception and RuntimeException provide constructor methods that accept a Throwable which describes the cause of the exception. And your exception should do the same. You should implement at least one constructor that gets the causing Throwable as a parameter and sets it on the superclass.

public class MyBusinessException extends Exception {

    public MyBusinessException(String message, Throwable cause, ErrorCode code) {
            super(message, cause);
            this.code = code;
        }

        ...
}


These are the most important best practices for implementing custom exception. If you’re looking for more tips and recommendations, take a look at my posts featuring 9 best practices and 7 common mistakes when working with Java exceptions.

Implementing a Custom Exception

Creating a custom checked exception is simple. You already saw multiple parts of it when I explained the 4 best practices for implementing custom exceptions.

When you implement a checked exception, you need to extend the class Exception. That’s the only thing you need to do to create a custom exception class. But as I explained earlier, you should also provide a constructor method that sets the causing exception and provide a benefit compared to the available standard exceptions.

The following example does all of that. As you can see, I added a Javadoc comment that describes the exception. I also implemented a constructor method that sets the causing exception on the superclass. And to provide a benefit compared to the standard exceptions, MyBusinessException uses a custom enumeration to store an error code that identifies the problem. Clients can use the error code to show localized error messages or tell the user to include this code in a support ticket.

/**
 * The MyBusinessException wraps all checked standard Java exception and enriches them with a custom error code.
 * You can use this code to retrieve localized error messages and to link to our online documentation.
 * 
 * @author TJanssen
 */
public class MyBusinessException extends Exception {

    private static final long serialVersionUID = 7718828512143293558 L;

    private final ErrorCode code;

    public MyBusinessException(ErrorCode code) {
        super();
        this.code = code;
    }

    public MyBusinessException(String message, Throwable cause, ErrorCode code) {
        super(message, cause);
        this.code = code;
    }

    public MyBusinessException(String message, ErrorCode code) {
        super(message);
        this.code = code;
    }

    public MyBusinessException(Throwable cause, ErrorCode code) {
        super(cause);
        this.code = code;
    }

    public ErrorCode getCode() {
        return this.code;
    }
}


That’s all you need to do to implement a custom checked exception. You can now throw the MyBusinessException in your code, specify it as part of your method signature and handle it in a catch clause.

public void handleExceptionInOneBlock() {
    try {
        wrapException(new String("99999999"));
    } catch (MyBusinessException e) {
        // handle exception
        log.error(e);
    }
}

private void wrapException(String input) throws MyBusinessException {
    try {
        // do something
    } catch (NumberFormatException e) {
        throw new MyBusinessException("A message that describes the error.", e, ErrorCode.INVALID_PORT_CONFIGURATION);
    }
}


Implementing an Unchecked Exception

The implementation of a custom unchecked exception is almost identical to a checked exception. You should follow the same recommendations as I explained at the beginning of this post. The only difference is that an unchecked exception has to extend RuntimeException instead of Exception.

/**
 * The MyUncheckedBusinessException wraps all unchecked standard Java exception and enriches them with a custom error code.
 * You can use this code to retrieve localized error messages and to link to our online documentation.
 * 
 * @author TJanssen
 */
public class MyUncheckedBusinessException extends RuntimeException {

    private static final long serialVersionUID = -8460356990632230194 L;

    private final ErrorCode code;

    public MyUncheckedBusinessException(ErrorCode code) {
        super();
        this.code = code;
    }

    public MyUncheckedBusinessException(String message, Throwable cause, ErrorCode code) {
        super(message, cause);
        this.code = code;
    }

    public MyUncheckedBusinessException(String message, ErrorCode code) {
        super(message);
        this.code = code;
    }

    public MyUncheckedBusinessException(Throwable cause, ErrorCode code) {
        super(cause);
        this.code = code;
    }

    public ErrorCode getCode() {
        return this.code;
    }
}


You can use the MyUncheckedBusinessException in the same way as any other unchecked exception. You can throw it in your code and catch it in a catch clause. And you can but don’t need to specify if your method throws it.

private void wrapException(String input) {
    try {
        // do something
    } catch (NumberFormatException e) {
        throw new MyUncheckedBusinessException("A message that describes the error.", e, ErrorCode.INVALID_PORT_CONFIGURATION);
    }
}


Summary

As described in this post, the implementation of a custom exception is easy. You just need to extend Exception for a custom checked exception, or RuntimeException if it’s a custom unchecked exception.

In addition to that, you should follow a few best practices. They make your code easier to read and your API easier to use. Here are the 4 most important best practices for custom exceptions in Java:

  • You should only implement a custom exception if it provides a benefit compared to Java’s standard exceptions.
  • The class name of your exception should end with Exception.
  • If an API method specifies an exception, the exception class becomes part of the API, and you need to document it.
  • You should provide a constructor which sets the cause of the exception.
Java (programming language) code style API

Published at DZone with permission of Thorben Janssen, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Getting Started With JMS-ActiveMQ: Explained in a Simple Way
  • Jakarta NoSQL 1.0: A Way To Bring Java and NoSQL Together
  • How to Get Word Document Form Values Using Java
  • Build a REST API With Just 2 Classes in Java and Quarkus

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!