Handling Errors and Logging

You write code and it works on your system. However, when you deploy it, it suddenly crashes. This is a common struggle for beginners. The real problem is not coding. It’s handling errors properly and knowing why something failed. 


In real-world applications, things will break. And, if your application does not handle errors correctly, users see confusing technical messages, debugging becomes difficult, security risks increase, and production issues take longer to fix. 


This is where error handling and logging become essential skills for every developer. In this blog, you will learn: 


  • What is error handling?

  • Complete exception handling hierarchy in Java

  • Best practices for managing errors securely

  • Why does login matter in real applications?

  • Effective logging strategies and tools

What is Error Handling?

Error handling is the process of identifying, managing, and responding to errors in an application so that the system does not crash unexpectedly. In simple words, instead of letting your application break when something goes wrong, you control the situation and respond properly. 


For example, imagine a user enters text instead of a number in a form. Without error handling, your application may crash. With proper error handling, you can show a user-friendly message like “Please enter a valid number.” 


That’s professional software behavior. In programming (especially Java), errors are handled using exceptions. An exception is an event that disrupts the normal flow of the program. 

Understanding the Exception Handling Hierarchy in Java

To truly understand error handling, you must understand the exception handling hierarchy in Java. At the top of the exception handling hierarchy is: 


  • <Throwable>


Under <Throwable>, there are two main branches: 

  • <Error>

  • <Exception>


<Error> represents serious issues (like system crashes or JVM problems) that applications generally should not try to handle. 


<Exception> represents problems that applications can handle. Under <Exception>, we have: 


  • Checked Exceptions (like <IOException>)

  • Unchecked Exceptions (like <NullPointerException>)


This structure is known as the exception handling hierarchy. Here is a simple example: 


Throwable

 ├── Error

 └── Exception

       ├── Checked Exceptions

       └── Unchecked Exceptions (RuntimeException)


Here is a basic exception handling example in Java: 


public class Example {

    public static void main(String[] args) {

        try {

            int result = 10 / 0;  // This will cause ArithmeticException

            System.out.println(result);

        } catch (ArithmeticException e) {

            System.out.println("Cannot divide by zero.");

        }

    }

}


  • The code inside <try> runs

  • Division by zero throws an <ArithmeticException>

  • The <catch> block handles it

  • Instead of crashing, the program prints a clear message

Best Practices in Error Handling

Writing secure, production-ready error handling is where most beginners struggle. In real-world applications, error handling must be structured, clean, and secure. Here are the best practices every developer should follow: 

1. Never Expose Technical Errors to Users

One of the biggest mistakes beginners make is showing an error message like: 


java.sql.SQLException: Access denied for user 'root'


This is dangerous as it exposes internal system details and creates unnecessary security risks. Instead of this, you should: 


  • Show simple, user-friendly messages

  • Log the detailed technical error internally

  • Never reveal stack traces in production


A better practice is: 

catch (Exception e) {

    System.out.println("Something went wrong. Please try again.");

}

2. Catch Specific Exceptions, Not Generic Ones

Many beginners write like: 

catch (Exception e)


While this is not wrong, it hides the real issue and makes debugging difficult. Because of the exception handling hierarchy in Java, you should catch the most specific exception possible. 


Example: 

try {

    int num = Integer.parseInt("abc");

} catch (NumberFormatException e) {

    System.out.println("Invalid number format.");

}


Catching specific exceptions improves debugging, makes code more readable, and prevents accidental suppression of important errors. 

3. Avoid Empty Catch Blocks

This is a very common mistake. 

try {

    int num = Integer.parseInt("abc");

} catch (NumberFormatException e) {

    System.out.println("Invalid number format.");

}


This silently ignores the error. The program continues, but the bug remains hidden. This makes production debugging extremely difficult. Always log the error, rethrow it, or handle it meaningfully. 

4. Use Custom Exceptions for Business Logic

When building real applications, generic exceptions are not enough. For example, you cannot use a dating app’s exceptions in a banking app. A banking system will have exceptions like: 


  • “InsufficientBalanceException”

  • “InvalidAccountException”


Custom exceptions make your application professional and readable. Example: 

class InsufficientBalanceException extends Exception {

    public InsufficientBalanceException(String message) {

        super(message);

    }

}


This improves code clarity, maintainability, and domain-level understanding. 

5. Always Log Errors Properly

Error handling without logging in is incomplete. When an error happens in production, you cannot reproduce the issue easily, you cannot access the user’s system, and you depend entirely on logs. 


So, even if you show a simple message to the user, internally you must log: 


  • Error message

  • Stack trace

  • Timestamp

  • Request details (if applicable)

6. Use Global Exception Handling in Web Applications

If you are using frameworks like SpringBoot, you should use centralized exception handling instead of writing <try-catch> everywhere. 


Example: 

@RestControllerAdvice

public class GlobalExceptionHandler {


    @ExceptionHandler(Exception.class)

    public String handleException(Exception ex) {

        return "Something went wrong.";

    }

}

What is Logging and Why It Matters?

Logging is the process of recording application events, errors, and system activities so that developers can monitor, debug, and maintain software effectively. In simple terms, if error handling controls what happens when something breaks, logging tells you why it broke. 


Think about this practical solution. A user says:

“Sir, your website is not working.” 


You check the server. Everything looks fine. No visible error. Without logs, you are guessing. With proper logging, you can check: 


  • What request was made?

  • What input was sent?

  • What exception occurred?

  • At what time did it happened

  • Which system component failed?


Here is a simple logging example: 

import java.util.logging.Logger;


public class Example {

    private static final Logger logger = Logger.getLogger(Example.class.getName());


    public static void main(String[] args) {

        try {

            int result = 10 / 0;

        } catch (ArithmeticException e) {

            logger.severe("Error occurred: " + e.getMessage());

        }

    }

}


Here, the user does not see technical details, and the system records the actual error internally. 

Why Logging is Critical in Real Applications?

For beginners, logging feels optional. In production, it is non-negotiable. Here’s why logging matters: 


  • Faster Debugging: Instead of manually reproducing issues, 

  • Production Monitoring: In live applications, you cannot attach a debugger. Logs are your only visibility into the system. 

  • Security & Incident Response: If a system is attacked or misused, logs help trace suspicious activity, unauthorized access attempts, and data manipulation. 

  • Performance Analysis: Logs can reveal slow database queries, API response delays, and high memory usage patterns. 

  • Compliance & Auditing: Many companies require audit logs to track user actions, financial transactions, and administrative changes. 

Effective Logging Strategies 

Logging is not about printing everything. Poor logging can be just as harmful as no logging. Many beginners either log nothing or log everything. Both are wrong. Effective logging means logging the right information, at the right level, in a structured and secure way. 

1. Use Log Levels Correctly

Most logging frameworks support different log levels. Each level has a purpose. 


  • INFO: General application flow (app started, request received)

  • DEBUG: Detailed information used during development

  • WARN: Something unexpected but not critical

  • ERROR: A serious issue that needs attention

  • FATAL: Application cannot continue


Using proper log levels helps filter logs easily, reduce noise, and identify critical issues quickly. For example: 

logger.info("User registration started");

logger.warn("Profile image not uploaded");

logger.error("Database connection failed", e);

2. Never Log Sensitive Information

This is a very important security rule. Never log sensitive information like passwords, OTPs, credit card details, Aadhar/PAN numbers, and session tokens. 


Here is an example of what not to do:

logger.info("User password: " + password);


Instead, do this: 

logger.info("User login attempt failed");


Logs are often accessible to multiple teams. Sensitive data in logs is a serious security risk. 

3. Log Errors With Context

A log that only says “Error occurred” is useless. To make debugging faster, always add context like: 


  • Which users?

  • Which API?

  • Which operation?

  • Which input (non-sensitive)?

 

Example: 

logger.error("Payment failed for userId: " + userId, e);

4. Avoid Excessive Logging

Logging inside loops or logging every request detail can slow down the application, increase server storage cost, and make logs unreadable. Only log important events, not everything. 


Here is a rule of thumb to follow: 


  • Log business events

  • Log failures

  • Log unusual behavior

5. Separate Application Logs and Error Logs

In real applications, normal activity logs go to one file and error logs go to another. This separation helps teams quickly focus on issues. Most logging frameworks support log file configuration and rotation. 

6. Use Structured Logging

Instead of plain text logs, structured logs use key-value pairs. They work better with monitoring tools and cloud platforms. 


Example:

logger.error("Order failed",

    Map.of("orderId", orderId, "userId", userId));

7. Combine Logging With Proper Error Handling

Good logging complements good error handling. This balance is what makes an application production-ready. 


  • Users see a clean message

  • Developer sees full stack trace in logs

  • System remains stable

Logging Libraries and Tools in Java

In real-world projects, developers do not use <System.out.println()> for logging. Professional applications use dedicated logging libraries that provide log levels, log file management, log rotation, and structured logging. Here are the most commonly used logging libraries: 

1. Log4j

Log4j is one of the most popular logging frameworks in Java. It allows you to: 


  • Configure log levels

  • Write logs to files

  • Send logs to external systems

  • Formal logs properly


Logging example using Log4j: 

import org.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.Logger;


public class Example {

    private static final Logger logger = LogManager.getLogger(Example.class);


    public static void main(String[] args) {

        logger.info("Application started");

        logger.error("An error occurred");

    }

}

2. SLF4J (Simple Logging Facade For Java)

SLF4J is not a logging framework itself. It is a facade (an interface). It allows you to plug different logging implementations (like Log4j or Logback) without changing your application code. This makes your application flexible and future-proof. 


Example: 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;


public class Example {

    private static final Logger logger = LoggerFactory.getLogger(Example.class);


    public static void main(String[] args) {

        logger.info("Using SLF4J logging");

    }

}

3. Logback

Logback is considered a successor to Log4j and works very well with SLF4J. If you are learning backend development in Java, Logback is a very good choice. It provides: 


  • Better performance

  • Automatic log file rotation

  • Flexible configuration

  • Cleaner integration with SpringBoot

4. Built-in Java Logging (java.util.logging)

Java also provides its own logging API. It is simple but less flexible compared to Log4j or Logback. For small projects or learning purposes, it is acceptable. On the other hand, for production systems, external frameworks are preferred. 

5. Centralized Logging Tools

In larger applications, logs are not only stored in text files. They are sent to centralized systems like: 


  • ELK Stack (Elastisearch, Logstash, Kibana)

  • Splunk

  • Cloud logging services


These tools help teams search logs easily, create dashboards, monitor system health, and detect suspicious behavior. 

Final Words

Error handling and logging are not optional skills. They define how professional your application really is. If you understand the exception handling hierarchy, your application will fail gracefully instead of crashing unexpectedly. When you combine that with structured logging, debugging becomes faster, and production issues become manageable. 


Start treating errors as part of the system design. That simple shift will immediately improve the quality, security, and reliability of your projects. 

Frequently Asked Questions (FAQs)

Q1. What is the exception handling hierarchy in Java?


Ans. The exception handling hierarchy in Java starts with <Throwable> class at the top. It is divided into <Error> and <Exception>. Errors represent serious system issues that applications usually do not handle. Exceptions are further divided into checked exceptions and unchecked exceptions. 


Q2. What is exception handling in Java?


Ans. Exception handling in Java is a mechanism that allows a program to manage runtime errors without crashing. It uses keywords like try, catch, throw, and throws to handle unexpected situations such as invalid input, division by zero, or database failures. Proper exception handling ensures stable and reliable applications. 


Q3. What is a simple exception handling example in Java?


Ans. A simple example is handling a division-by-zero error using a try and catch block. Instead of letting the program crash, the catch block handles the error and displays a meaningful message. This approach improves user experience and application stability. 


Q4. Why is logging important in web applications?


Ans. Logging records application events, errors, and system activity. In production environments, logs help developers identify what went wrong, when it happened, and why it happened. Without proper logging, debugging, and monitoring, real-world applications become very difficult. 


Q5. What is the difference between error handling and logging?


Ans. Error handling controls how an application responds when something fails. Logging records the details of that failure for debugging and monitoring purposes. Both work together to build secure, reliable, and production-ready applications.

Discover More Courses on Skillwaala