BEST PRACTICES

Error Handling Cheat Sheet

Robust exception handling patterns and logging strategies for production-grade systems.

Try CodeError?Success PathCatchFinally(Cleanup)
Control Flow

Basic Try-Catch

Handle code that might throw an exception without crashing the program.

try {
// Risky code
int result = 10 / 0;
} catch (ArithmeticException e) {
// Handle specific error
System.err.println("Math error: " + e.getMessage());
} catch (Exception e) {
// Handle generic error
System.err.println("Unknown error");
}
Control Flow

Finally / Cleanup

Code that *always* runs, regardless of whether an exception occurred (e.g., closing connections).

FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
} catch (IOException e) {
e.printStackTrace();
} finally {
// Always closes, even if error above
if (fis != null) fis.close();
}
Best Practice

Resource Management

Automatic cleanup using syntax sugar (Try-with-resources / Context Managers). Prevents leaks.

// Java 7+ Try-with-resources
// Auto-closes objects implementing AutoCloseable
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
Design

Custom Exceptions

Creating domain-specific errors to make handling more meaningful.

public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String msg) {
super(msg);
}
}
// Usage
throw new InsufficientFundsException("Balance low");
Logging

Log Levels

Use the appropriate level. Don't just print stack traces.

import org.slf4j.Logger;
logger.debug("Entering method x with args {}", args); // Dev only
logger.info("User {} logged in", userId); // Business event
logger.warn("Cache miss for key {}", key); // Potential issue
logger.error("DB connection failed", e); // Actionable failure
Logging

Structured Logging

Log in JSON format for easy parsing by tools like ELK, Datadog, or Splunk.

// Using MDC (Mapped Diagnostic Context)
MDC.put("transactionId", "tx-123");
logger.info("Processing payment");
// Output: {"timestamp": "...", "level": "INFO", "transactionId": "tx-123", "message": "Processing payment"}
Patterns

Wrapping/Rethrowing

Catching a low-level exception and throwing a high-level one (Exception Chaining).

try {
// Low level DB code
} catch (SQLException e) {
// Wrap in domain exception, keep cause
throw new UserServiceException("Unable to fetch user", e);
}
Patterns

Global Handler

Centralized place to catch unhandled exceptions (e.g., for API responses).

@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handle(Exception e) {
return ResponseEntity.status(500).body("Oops");
}
}