JakartaJEEWebDevelopment

Jakarta JEE8 Enterprise Web Development

View on GitHub

Logging with Log4j and SLF4J in our Jakarta EE 8 Web Application

Introduction to Logging

Logging is a crucial aspect of software development, providing a means to record and monitor the behavior of an application. In our Jakarta EE 8 web application, we’ll explore the integration of two essential Java logging frameworks: Apache Log4j and SLF4J.

Why Logging Matters

Logging serves as a vital tool in the development and maintenance of software applications. It helps in debugging, troubleshooting, and monitoring application performance in production environments. Whether it’s tracking errors, monitoring system behavior, or gaining insights into application flow, logs are a valuable resource.

Key Reasons for Logging

  1. Application Crashes
    • Logging helps identify and trace unexpected application crashes, providing crucial insights into the root causes.
  2. Errors and Exceptions
    • Capture and log errors and exceptions, with a special mention to the notorious Null Pointer Exception (NPE) in Java.
  3. Problems with External Resources
    • Log issues related to external resources, such as message queues (MQs) or databases (DBs) being unavailable or inaccessible.
  4. Authentication, Authorization, and Transactional Steps
    • Confirm and log the success of critical steps like authentication, authorization, and transactions. Legal requirements may mandate documentation of these processes.
  5. Scaling Verbosity in Production
    • Logging can be adjusted in production to provide varying levels of detail, aiding in diagnosing and resolving issues efficiently.

How Logs are Written

  1. Console or System.out
    • Traditional method used since the beginning of the course. Note: restarting web applications results in the loss of previous console entries.
  2. Flat Files (.log extension)
    • Quick accumulation of log entries, but poses challenges:
      • Requires substantial drive space.
      • Needs configuration and management for compression and long-term storage.
      • Improvement: Transitioning from basic text to XML or JSON format enhances file management.
  3. Network Sockets, SMS, and SMTP
    • Crucial for logs in distributed cloud-based deployments (e.g., Amazon AWS, Google Kubernetes, Microsoft Azure).
    • Orchestration of logging is handled by cloud tools in such deployments.
  4. OS Tools (SysLog in Linux, Windows Event Log)
    • Useful for managing log files efficiently.
  5. Database Logging
    • Enables easy querying for specific incidents or timeframes.
    • Many logging stacks utilize NoSQL databases for efficient storage and retrieval.

Log4j and SLF4J Overview

We’ve chosen to use the latest Apache Log4j framework, compatible with JDK 11 and Jakarta EE 8, in conjunction with the log4j-slf4j-impl package. Before diving into the integration process, let’s understand the key differences between Log4j and SLF4J.

Log4j and SLF4J: Different Purposes

  1. Purpose:
    • Log4j:
      • Log4j is a comprehensive logging framework that offers a flexible and customizable logging infrastructure. It supports hierarchical loggers, various logging levels, and multiple output appenders (console, file, database, etc.).
    • SLF4J:
      • SLF4J is not a logging framework itself but a facade designed to provide a simple and efficient abstraction for various logging frameworks. It acts as a common interface without performing actual logging, allowing developers to switch between logging implementations seamlessly.
  2. Logging Levels and Configuration:
    • Log4j:
      • Log4j supports standard logging levels such as DEBUG, INFO, WARN, ERROR, etc., and offers extensive configuration options for loggers, appenders, layouts, and filters.
    • SLF4J:
      • SLF4J provides a facade for logging levels, and the actual interpretation depends on the underlying logging framework. While it offers a simple and consistent API, detailed configuration is left to the chosen logging framework.
  3. Binding to Logging Frameworks:
    • Log4j:
      • Directly utilizes the log4j library for logging.
    • SLF4J:
      • Acts as a bridge or facade, requiring a binding to an actual logging framework. This feature enables flexibility in switching between different logging implementations.
  4. Use Cases:
    • Log4j:
      • Ideal for projects requiring a feature-rich and highly configurable logging framework.
    • SLF4J:
      • Suitable for projects aiming to decouple code from a specific logging implementation, facilitating easy adaptation to different logging frameworks.

Integration into Our Web Application

Now that we have an understanding of the differences between Log4j and SLF4J, let’s explore how we can integrate logging into our Jakarta EE 8 web application.

Logging Levels and Categories

In general, the levels indicate the seriousness and the impact of the expected problem of our code.

Using Logging Levels

Before we delve into the integration process, it’s essential to understand the various logging levels commonly used in both Log4j and SLF4J.

Logging Levels Table

Each level corresponds to a specific severity of the log statement.

Choosing the Right Logging Facility

The choice between Log4j and SLF4J depends on the project’s requirements and preferences. Log4j is suitable for projects that demand a powerful and configurable logging framework, while SLF4J is ideal for those wanting a flexible facade to decouple code from the underlying logging implementation.

Integration Steps

To include logging in our Charity Registration Application, we’ll follow these general steps:

  1. Dependency Configuration:
    • Add the necessary dependencies for Log4j and SLF4J to your project’s build configuration.
  2. Logger Initialization:
    • Initialize the loggers in your application, either using Log4j directly or SLF4J’s facade.
  3. Log Statements:
    • Introduce log statements in your application code at relevant points using the chosen logging framework.
  4. Configuration:
    • Configure the logging framework (Log4j) according to your application’s requirements. This includes specifying log levels, output destinations, and formatting options.

Conclusion

Logging is a critical aspect of application development, providing invaluable insights into an application’s behavior. By integrating Log4j and SLF4J into our Jakarta EE 8 web application, we enhance our ability to monitor, debug, and troubleshoot effectively.

In the next sections, we’ll dive into the specifics of logging levels, facility selection, integration steps, and demonstrate the inclusion of logging in our Charity Registration Application.

The use of log.atDebug().log() instead of log.debug() in this example code is related to the structured logging capabilities provided by the Log4j 2 library. The log.atDebug() syntax is a part of Log4j 2’s fluent logging API, and it’s particularly useful when you want to include additional structured information in your log messages.

With log.atDebug(), you can chain additional attributes or context information using the withAttribute method before invoking log(). For example:

log.atDebug().withAttribute("key", value).log("Your log message");

This allows you to attach structured data to your log messages, providing more context or information that might be valuable for debugging or analysis.

In the provided example code, the use of CloseableThreadContext is another part of Log4j 2’s feature set. It allows you to add context data to the logging context for the duration of the try-with-resources block. This is particularly useful for tracking the context of log messages, especially in multi-threaded applications.

In summary, the use of log.atDebug().log() in this code is a way to take advantage of Log4j 2’s structured logging capabilities and the fluent API, providing a more flexible and extensible approach to logging with additional context information. If you don’t require structured logging or additional context, using log.debug() directly is also a valid and more concise option.