Custom and Chained exceptions in Java
-
Last Updated: October 26, 2024
-
By: javahandson
-
Series
Learn how to create and use custom and chained exceptions in Java to improve error handling and debugging. This guide covers how to implement custom exception classes and chaining exceptions for better traceability.
Custom exceptions are the user-defined exceptions. Developers create these exceptions that are more domain and business specific making debugging and error handling easier in complex applications.
The custom exception that we create can be of checked or unchecked type.
To create a custom checked exception we have to create a Class that extends the Exception class. In this Class, we can define 2 types of constructors.
1. A constructor that accepts an error message. This error message can be forwarded to the parent class using the super keyword.
class NoFileFoundException extends Exception {
NoFileFoundException(String errorMessage) {
super(errorMessage);
}
}
2. A constructor that accepts an error message and a Throwable cause ( this constructor will be used in chaining exceptions that we will learn in the below section )
class NoFileFoundException extends Exception {
NoFileFoundException(String errorMessage, Throwable cause) {
super(errorMessage, cause);
}
}
Write a program to raise a custom-checked exception.
In this program, we will throw a custom-checked exception i.e. NoFileFoundException if the file is not found.
package com.javahandson; import java.io.File; class NoFileFoundException extends Exception { NoFileFoundException(String errorMessage) { super(errorMessage); } } public class CustomCheckedException { public static void main(String[] args) throws NoFileFoundException { File file = new File("file.txt"); boolean ifFileExist = file.exists(); try { if (!ifFileExist) { throw new NoFileFoundException("file is not found"); } } catch (NoFileFoundException exception) { System.out.println(exception.getMessage()); } } } Output: file is not found
To create a custom unchecked exception we have to create a Class that extends the RuntimeException class. In this Class, we can define 2 types of constructors, the same as we have defined in the case of custom-checked exceptions.
1. A constructor that accepts an error message. This error message can be forwarded to the parent class using the super keyword.
class FileProcessingException extends RuntimeException {
FileProcessingException (String message) {
super(message);
}
}
2. A constructor that accepts an error message and a Throwable cause ( this constructor will be used in chaining exceptions that we will learn in the below section )
class FileProcessingException extends RuntimeException {
FileProcessingException (String message, Throwable cause) {
super(message, cause);
}
}
Write a program to raise a custom unchecked exception.
Firstly we will create a text file with some data and then we will try to read this file. If we encounter the word ERROR in this file then we will throw a FileProcessingException i.e. a custom unchecked exception.
file.txt
Hello
ERROR
HOW ARE YOU
package com.javahandson; import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; class FileProcessingException extends RuntimeException { FileProcessingException(String message) { super(message); } } public class CustomUncheckedException { public static void main(String[] args) { File file = new File("file.txt"); try (Scanner scanner = new Scanner(file)) { while (scanner.hasNextLine()) { String line = scanner.nextLine(); if (line.contains("ERROR")) { throw new FileProcessingException("File contains invalid content"); } System.out.println("Processing line: " + line); } } catch (FileNotFoundException e) { System.out.println(e.getMessage()); } catch (FileProcessingException e) { System.out.println("Custom exception is raised : " + e.getMessage()); } } } Output: Processing line: Hello Custom exception is raised : File contains invalid content
Chained exceptions allow one exception to be linked to another. This is useful when the current exception is caused by another exception enabling us to trace the root cause of the error more effectively.
As we have discussed in the above sections there are 2 types of constructors and one of the constructors has Throwable as a parameter like below.
class NoFileFoundException extends Exception {
NoFileFoundException(String errorMessage, Throwable cause) {
super(errorMessage, cause);
}
}
This type of constructor helps us to allow the chaining of exceptions by passing the original exception as a second parameter i.e. cause.
Write a program to chain IOException with a custom exception.
Here, we will throw an IOException if the file is not found. We will catch this IOException and pass it as a throwable to the NoFileFoundException i.e. a custom exception.
package com.javahandson; import java.io.File; import java.io.IOException; class NoFileFoundException extends Exception { NoFileFoundException(String errorMessage, Throwable cause) { super(errorMessage, cause); } } public class CustomCheckedException { public static void main(String[] args) throws NoFileFoundException { File file = new File("file.txt"); boolean ifFileExist = file.exists(); try { if (!ifFileExist) { throw new IOException("file is not found"); } } catch (IOException exception) { throw new NoFileFoundException("Failed to find a file", exception); } } } Output: Exception in thread "main" com.javahandson.NoFileFoundException: Failed to find a file at com.javahandson.CustomCheckedException.main(CustomCheckedException.java) Caused by: java.io.IOException: file is not found at com.javahandson.CustomCheckedException.main(CustomCheckedException.java)
In the above program, IOException is the root cause of the exception and we are chaining it to the custom-checked exception.
We can access the original exception using the getCause method of the throwable class.
package com.javahandson; import java.io.File; import java.io.IOException; class NoFileFoundException extends Exception { NoFileFoundException(String errorMessage, Throwable cause) { super(errorMessage, cause); } } public class CustomCheckedException { public static void validate() throws NoFileFoundException { File file = new File("file.txt"); boolean ifFileExist = file.exists(); try { if (!ifFileExist) { throw new IOException("file is not found"); } } catch (IOException exception) { throw new NoFileFoundException("Failed to find a file", exception); } } public static void main(String[] args) { try { validate(); } catch (NoFileFoundException exception) { System.out.println(exception.getCause()); } } } Output: java.io.IOException: file is not found
In the above program, IOException is the original exception that is chained to NoFileFoundException. Hence using the getCause method we are able to get the original cause of the exception which in this case is an IOException.
So this is all about custom and chained exceptions in Java. If you have any questions on this topic, please raise them in the comments section. If you liked this article then please share this post with your friends and colleagues.