How do I format a message that contains date information?

This example demonstrate how you can use the java.text.MessageFormat class to format a message with a date information in it.

package org.kodejava.text;

import java.util.Date;
import java.util.Calendar;
import java.util.Locale;
import java.text.MessageFormat;

public class MessageFormatDate {
    public static void main(String[] args) {
        Date today = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7);

        Date nextWeek = calendar.getTime();

        // We want the message to be is Locale.US
        Locale.setDefault(Locale.US);

        // Format a date, the time value is included
        String message = MessageFormat.format("Today is {0} and next " +
                "week is {1}", today, nextWeek);
        System.out.println(message);

        // Format a date and display only the date portion
        message = MessageFormat.format("Today is {0,date} and next " +
                "week is {1,date}", today, nextWeek);
        System.out.println(message);

        // Format a date using a short format (e.g. dd/MM/yyyy)
        message = MessageFormat.format("Today is {0,date,short} and " +
                "next week is {1,date,short}", today, nextWeek);
        System.out.println(message);

        // Format a date using a medium format, it displays the month long-name,
        // but using a two digit date and year.
        message = MessageFormat.format("Today is {0,date,medium} and " +
                "next week is {1,date,medium}", today, nextWeek);
        System.out.println(message);

        // Format a date using a long format, two digit for date, a long month
        // name and a four digit year.
        message = MessageFormat.format("Today is {0,date,long} and " +
                "next week is {1,date,long}", today, nextWeek);
        System.out.println(message);

        // Format a date using a full format, the same as above plus a full day
        // name.
        message = MessageFormat.format("Today is {0,date,full} and " +
                "next week is {1,date,full}", today, nextWeek);
        System.out.println(message);

        // Format a date using a custom pattern.
        message = MessageFormat.format("Today is {0,date,dd-MM-yyyy} and " +
                "next week is {1,date,dd-MM-yyyy}", today, nextWeek);
        System.out.println(message);
    }
}

The above program produces:

Today is 10/8/21, 9:35 PM and next week is 10/15/21, 9:35 PM
Today is Oct 8, 2021 and next week is Oct 15, 2021
Today is 10/8/21 and next week is 10/15/21
Today is Oct 8, 2021 and next week is Oct 15, 2021
Today is October 8, 2021 and next week is October 15, 2021
Today is Friday, October 8, 2021 and next week is Friday, October 15, 2021
Today is 08-10-2021 and next week is 15-10-2021

How do I create a rolling log files?

In this example we create a rolling or a sequenced of log files. Instead of just limiting the file size (see. How do I limit the size of log file) we can also make the log file to roll. This will prevent a lost to an important log message if we use a single log file.

When using more than one file the log file name will have a sequence number in it starting from 0 to N-1. If we set the count to 5 then we’ll have log files such as myapp.log.0, myapp.log.1 up to myapp.log.5.

If the first log file (myapp.log.0) is about to full, it will be renamed to (myapp.log.1) before the log is written to the first log file. The log is always written to the first file (myapp.log.0).

To read the log messages in sequence you need to start from the highest to the lowest sequence number. By running this program multiple times you’ll see the creation of the log file one by one.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.FileHandler;
import java.util.logging.SimpleFormatter;
import java.io.IOException;

public class RollingLogFile {
    // Set a small log file size to demonstrate the rolling log files.
    public static final int FILE_SIZE = 1024;

    public static void main(String[] args) {
        Logger logger = Logger.getLogger(RollingLogFile.class.getName());

        try {
            // Creating an instance of FileHandler with 5 logging files
            // sequences.
            FileHandler handler = new FileHandler("myapp.log", FILE_SIZE, 5, true);
            handler.setFormatter(new SimpleFormatter());
            logger.addHandler(handler);
            logger.setUseParentHandlers(false);
        } catch (IOException e) {
            logger.warning("Failed to initialize logger handler.");
        }

        logger.info("Logging information message.");
        logger.warning("Logging warning message.");
    }
}

How do I limit the size of log file?

In this example you learn how to limit the size of a log file when using a FileHandler handler. Limiting the log file will prevent the log file to grow wildly without limit.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.FileHandler;
import java.io.IOException;

public class LogFileLimit {
    // The log file size is set to 1 MB.
    public static final int FILE_SIZE = 1024 * 1024;

    public static void main(String[] args) {
        Logger logger = Logger.getLogger(LogFileLimit.class.getName());

        try {
            // Create a FileHandler with 1 MB file size and a single log file.
            // We also tell the handler to append the log message.
            FileHandler handler = new FileHandler("myapp.log", FILE_SIZE, 1, true);
            logger.addHandler(handler);
        } catch (IOException e) {
            logger.warning("Failed to initialize logger handler.");
        }

        logger.info("Test info");
        logger.warning("Test warning");
        logger.severe("Test severe");
    }
}

How do I create a custom logger Formatter?

To create a custom Formatter we need to extend the java.util.logging.Formatter abstract class and implements the format(LogRecord) method. In the method then we can format the log message stored in the LogRecord to match our need.

The java.util.logging.Formatter class also have the getHead(Handler) and getTail(Handler) which can be overridden to add a head and a tail to our log message.

package org.kodejava.util.logging;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.*;

public class LogCustomFormatter {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(LogCustomFormatter.class.getName());
        logger.setUseParentHandlers(false);

        MyFormatter formatter = new MyFormatter();
        ConsoleHandler handler = new ConsoleHandler();
        handler.setFormatter(formatter);

        logger.addHandler(handler);
        logger.info("Example of creating custom formatter.");
        logger.warning("A warning message.");
        logger.severe("A severe message.");
    }
}

class MyFormatter extends Formatter {
    // Create a DateFormat to format the logger timestamp.
    private static final DateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");

    public String format(LogRecord record) {
        StringBuilder builder = new StringBuilder(1000);
        builder.append(df.format(new Date(record.getMillis()))).append(" - ");
        builder.append("[").append(record.getSourceClassName()).append(".");
        builder.append(record.getSourceMethodName()).append("] - ");
        builder.append("[").append(record.getLevel()).append("] - ");
        builder.append(formatMessage(record));
        builder.append("\n");
        return builder.toString();
    }

    public String getHead(Handler h) {
        return super.getHead(h);
    }

    public String getTail(Handler h) {
        return super.getTail(h);
    }
}

Below is an output produced by the custom formatter above.

08/10/2021 07:55:55.153 - [org.kodejava.util.logging.LogCustomFormatter.main] - [INFO] - Example of creating custom formatter.
08/10/2021 07:55:55.164 - [org.kodejava.util.logging.LogCustomFormatter.main] - [WARNING] - A warning message.
08/10/2021 07:55:55.164 - [org.kodejava.util.logging.LogCustomFormatter.main] - [SEVERE] - A severe message.

How do I prevent the logger send log messages to its parent logger?

To prevent log records being forwarded to the logger’s parent handlers we can set false the useParentHandlers field using the Logger.setUserParentHandlers(boolean useParentHandlers) method.

package org.kodejava.util.logging;

import java.util.logging.Logger;
import java.util.logging.ConsoleHandler;

public class NoParentLogger {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(NoParentLogger.class.getName());

        // Do not forward any log messages the logger parent handlers.
        logger.setUseParentHandlers(false);

        // Specify a ConsoleHandler for this logger instance.
        logger.addHandler(new ConsoleHandler());
        logger.info("Logging an information message.");
    }
}