Propagating exceptions in a method chain

In Java, exception propagation refers to the process of passing an exception from one method to another in the method call stack until it is caught or the program terminates. This is typically done using the throws keyword, which declares that a method might throw an exception, and allows the exception to be handled by the caller.

How It Works

When a method throws a checked exception and does not handle it locally with a try-catch block, it must declare the exception in its method signature using throws. If the caller also does not handle it, the exception propagates up further. This continues until either:

  • It is caught in a method with a try-catch block, or
  • It reaches the main() method and causes the program to terminate.

Key Benefits

  • Encourages modular exception handling, where the appropriate method or layer decides how to respond.
  • Helps delegate responsibility for handling exceptions to higher-level logic that understands the broader context.
  • Makes code cleaner by avoiding deep nesting of try-catch blocks.

Example Scenario

Imagine a banking application with three methods:

  1. validateAccount() — Checks if an account is valid.
  2. processTransaction() — Calls validateAccount() and performs a transaction.
  3. main() — Calls processTransaction() and handles any exceptions.

Each method in the chain passes the exception upward using throws.

Program Statement

In this program, LotusJavaPrince wants to validate a user’s account and process a banking transaction. If the account number is invalid, a custom InvalidAccountException is thrown. The exception propagates from validateAccount() to processTransaction() and finally to the main() method, where Mahesh handles it.

// Custom Exception
class InvalidAccountException extends Exception {
    public InvalidAccountException(String message) {
        super(message);
    }
}

public class ExceptionPropagationExample {

    // Method 1: Validates account
    public static void validateAccount(String accountNumber) throws InvalidAccountException {
        if (accountNumber == null || !accountNumber.startsWith("AC")) {
            throw new InvalidAccountException("Invalid account number: " + accountNumber);
        }
        System.out.println("Account validated: " + accountNumber);
    }

    // Method 2: Processes transaction
    public static void processTransaction(String accountNumber) throws InvalidAccountException {
        System.out.println("Processing transaction for: " + accountNumber);
        validateAccount(accountNumber); // Exception may propagate from here
        System.out.println("Transaction completed for: " + accountNumber);
    }

    // Method 3: Main method
    public static void main(String[] args) {
        try {
            processTransaction("12345"); // Invalid account (doesn't start with "AC")
        } catch (InvalidAccountException e) {
            System.out.println("Mahesh caught the exception: " + e.getMessage());
        }

        System.out.println("\nTrying a valid account...\n");

        try {
            processTransaction("AC7890"); // Valid account
        } catch (InvalidAccountException e) {
            System.out.println("Mahesh caught the exception: " + e.getMessage());
        }
    }
}
/*
Processing transaction for: 12345
Mahesh caught the exception: Invalid account number: 12345

Trying a valid account...

Processing transaction for: AC7890
Account validated: AC7890
Transaction completed for: AC7890
*/

Exception propagation is a powerful technique in Java that allows exceptions to be passed up the call stack. This avoids cluttering lower-level code with handling logic and instead lets higher-level components deal with exceptions in a meaningful way. However, developers should ensure proper documentation and handling at appropriate levels to prevent uncaught exceptions from terminating the application unexpectedly.

Scroll to Top