1. Introduction

Exception classes are essential in Java applications to catch and handle errors correctly. It’s common to spend time writing duplicate code for exceptions instead of thinking about other aspects of the application.

In this tutorial, we’ll use Lombok‘s @StandardException annotation to auto-generate constructors for exception-type classes. In addition, we’ll look at its advantages and drawbacks.

2. What Is @StandardException?

@StandardException is an experimental annotation added to version v1.18.22 of Project Lombok. That annotation works on any subclass of Throwable and auto-generates four constructors:

  • a no-args constructor
  • a message-only constructor without a cause
  • a cause-only constructor without a message
  • a canonical constructor with a message and a cause

Like most Lombok annotations, @StandardException is very simple, as we’ll see in the following sections.

2.1. Adding the Lombok Dependency

We’ll need version v.1.18.22 or higher of Project Lombok to use the annotation. Hence, let’s add the latest one, lombok::1.18.26, to our pom.xml file:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

2.2. Using the Class Annotation

To use the @StandardException in our exceptions, we must create a target class that extends the Throwable class or any of its subclasses. Therefore, it works for checked and unchecked exceptions as well for errors.

To illustrate, let’s create a CustomException class:

@StandardException
public class CustomException extends Throwable {
}

The code compiles normally since CustomException extends Throwable. Let’s see the code that’s generated after compiling:

public class CustomException extends Throwable {
    public CustomException() {
        this((String)null, (Throwable)null);
    }

    public CustomException(String message) {
        this(message, (Throwable)null);
    }

    public CustomException(Throwable cause) {
        this(cause != null ? cause.getMessage() : null, cause);
    }

    public CustomException(String message, Throwable cause) {
        super(message);
        if (cause != null) {
            super.initCause(cause);
        }
    }
}

The Lombok annotation works differently than the usual Java approach to implementing custom exception constructors. Typically, the JDK implements them by calling the super constructor version for the specified signature. For instance, the cause-only constructor would call super(cause) in its implementation.

On the other hand, Lombok’s first three constructors depend on the generated canonical constructor to build the exception object. The canonical constructor calls super(message) to build the initial object. Then, it initializes the cause of CustomException using the initCause() method if it’s not null.

The two implementations have different nuances that we must consider when using the annotation.

We’ll look at some advantages and drawbacks of @StandardException compared to the usual way in the next sections.

3. Advantages

The main advantage of using @StandardException is that we avoid writing boilerplate code. For example, creating a subclass of a NumberFormatException in vanilla Java might look like this:

public class CustomNumberFormatException extends NumberFormatException{
    public CustomNumberFormatException() {
        super();
    }

    public CustomNumberFormatException(String s) {
        super(s);
    }
}

In the code above, we manually created constructors using the available super constructors of NumberFormatException.

In real-world applications, that code is often repeated across exception classes. So, we end up copying and pasting the same code many times. That becomes harder to maintain when the number of exception classes is high.

In contrast, by using @StandardException, we get four auto-generated constructors using a single line of code. Therefore, it might increase development speed and improve code maintainability.

Another good point about @StandardException is that the generated constructors use only the super(message) constructor, which exists in most Java exceptions. Hence, we avoid calling a super constructor that doesn’t exist on the superclass. For example, the NumberFormatException doesn’t define the canonical and cause-only constructors. Thus, calling super(message, cause) or super(cause) would fail in its subclasses.

Finally, all exceptions using @StandardException share the same behavior as implemented by Lombok. We can’t modify the code by Lombok since it’s auto-generated. So, we are less likely to introduce potentially problematic code to classes annotated with @StandardException.

4. Drawbacks

A noticeable drawback of using code generators is the introduction of more complexity for debugging. It’s easier to debug and find flaws in written code than in generated code. Thus, using @StandardException might complicate the debugging sessions if something works incorrectly.

Another pitfall to consider is the dependency created on Lombok. Coupling our code to @StandardException creates extra work if we want to return to plain Java. In addition, if a bug happens on the Lombok side, it will affect all exceptions using the annotation.

5. Conclusion

In this short article, we learned how to use the @StandardException added to Lombok in version v.1.18.22. We also saw some of its advantages and drawbacks compared to plain Java.

The key is to balance its advantages and drawbacks instead of using it indiscriminately in our applications.

As always, the source code is available over on GitHub.

Course – LS (cat=Java)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.