When working with a large codebase or complex applications, tracking and managing exceptions efficiently is crucial. Here's how you can centralize exception handling while adding unique IDs to each exception for better traceability and debugging.
What is it?
Using a SafeRunner
utility, we can wrap risky operations in a centralized exception handler, attaching a unique ID to each exception. This makes it easy to trace and manage exceptions across your application.
How it Works:
-
SafeRunner.run()
: Wraps a task in aCallable
, catches exceptions, and passes them to a centralized handler. -
Exception IDs: Each exception is tagged with an ID to help track the specific context of errors.
-
Custom
IdentifiedException
: This custom exception class stores the exception ID for logging or reporting.
Code Example:
import java.util.concurrent.Callable;
// SafeRunner with exception ID
public class SafeRunner {
public static <T> T run(Callable<T> task, String exceptionId) {
try {
return task.call();
} catch (Exception ex) {
handleGlobally(ex, exceptionId);
return null;
}
}
private static void handleGlobally(Exception ex, String exceptionId) {
ex = new IdentifiedException(exceptionId, ex.getMessage(), ex);
System.err.printf("Exception ID: %s\n", exceptionId);
System.err.println("Global handler caught: " + ex);
ex.printStackTrace(System.err);
}
}
// Custom exception class with ID
class IdentifiedException extends RuntimeException {
private final String id;
public IdentifiedException(String id, String message, Throwable cause) {
super(message, cause);
this.id = id;
}
public String getId() {
return id;
}
}
// Example usage
public class App {
public static void main(String[] args) {
Integer result = SafeRunner.run(() -> divide(10, 0), "DIV-1234");
SafeRunner.run(() -> { doSomethingRisky(); return null; }, "TASK-5678");
}
static int divide(int a, int b) {
return a / b; // Will throw ArithmeticException if b == 0
}
static void doSomethingRisky() throws Exception {
throw new Exception("Oh no!");
}
}
Benefits:
-
Traceability: Easily track which operation caused the exception.
-
Centralized Handling: Consolidates error handling logic in one place.
-
Better Debugging: Use exception IDs to correlate logs and errors across modules.
Use Cases:
-
Large Systems: Track errors across services and components.
-
Distributed Applications: Easily propagate error IDs across multiple services.
-
Debugging: Quickly trace specific issues through logs and support tickets.
This approach helps streamline exception management, providing a clear way to track and resolve issues quickly while keeping your codebase clean and maintainable.
-
git : https://github.com/stark9000/Centralized-Exception-Handling