java.util.logging: file handler leaves lock on file

J

johnmmcparland

Hi all,

I'm playing around with the java logging package and I notice that a
lock file is always left on log file I create in my example program.
The XML file is always created. Put these in a package called
com.johnmcparland.logging and compile / run with JDK 5.0

[verbatim]
// FileLogging.java
package com.johnmcparland.logging;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.SimpleFormatter;

/**
* Logs stuff to a file
*/
public class FileLogging
{

/**
* Name of this class for logging
*/
private static final String CLASS_NAME = "FileLogging";

/**
* Main program
*
* @param args Program arguments. Not required, any provided will
be ignored.
*/
public static void main(String[] args)
{
// Clear exiting handlers (if any)
SimpleLogging.clearLoggingHandlers();

// Add a handler for a file
final String methodName = "main(String[] args)";
try
{
final String xmlLogFile = "FileLoggingLogFile.xml";
FileHandler fHand = new FileHandler(xmlLogFile);
fHand.setLevel(Level.ALL);
SimpleLogging.logger.addHandler(fHand);
}
catch (IOException ioe)
{
SimpleLogging.logFatalException("Error setting xml log
file", CLASS_NAME, methodName, ioe);
System.exit(-1);
}
catch (SecurityException se)
{
SimpleLogging.logFatalException("Error setting xml log
file", CLASS_NAME, methodName, se);
System.exit(-1);
}

// Log using the default XML handler
SimpleLogging.logger.logp(Level.INFO, CLASS_NAME, methodName,
"Got file logging working for the default XML log");

// Change to use the "human-readable" logging
Handler[] handlers = SimpleLogging.logger.getHandlers();
for (Handler hand : handlers)
{
if (hand instanceof FileHandler)
{
// Clear the existing handler
try
{
hand.flush();
hand.close();
}
catch (SecurityException se)
{
SimpleLogging.logFatalException("Exception while
closing xml log file", CLASS_NAME,
methodName, se);
System.exit(-1);
}

// Set the human readable handler
try
{
final String humanLogFile =
"FileLoggingLogFile.txt";
hand = new FileHandler(humanLogFile);
hand.setFormatter(new SimpleFormatter());
}
catch (IOException ioe)
{
SimpleLogging.logFatalException("Exception while
setting human readable log file",
CLASS_NAME, methodName, ioe);
}
catch (SecurityException se)
{
SimpleLogging.logFatalException("Exception while
setting human readable log file",
CLASS_NAME, methodName, se);
}
}
}

// Log using the Simple formatter
SimpleLogging.logger.logp(Level.INFO, CLASS_NAME, methodName,
"Got file logging working using human readable log
file");

SimpleLogging.clearLoggingHandlers();
}
}
[/verbatim]

[verbatim]
// SimpleLogging.java
package com.johnmcparland.logging;

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

/**
* Simple example of using {@link java.util.logging}
* <p>
* This example is based on the examples at {@link http
* ://java.sun.com/j2se/1.5.0/docs/api/index.html?java/util/logging/
package-summary.html}
* </p>
*/
public class SimpleLogging
{

/**
* Name of the logger for this package
*/
private static final String LOGGER_NAME =
"com.johnmmcparland.logging";

/**
* The logger for this package
*/
protected static Logger logger = Logger.getLogger(LOGGER_NAME);

/**
* The name of this class
*/
private static final String CLASSNAME = "SimpleLogging";

/**
* Main program
*
* @param args Program arguments. Not required, any provided will
be ignored
*/
public static void main(String[] args)
{
// Clear exiting handlers (if any)
SimpleLogging.clearLoggingHandlers();

// Use finest level and log to console
logger.addHandler(new ConsoleHandler());
(new ConsoleHandler()).setLevel(Level.FINEST);
// logger.setLevel(Level.FINEST); Doesn't work?

/*
* Use different log levels
*/
final String methodName = "main(String[] args)";
logger.logp(Level.SEVERE, CLASSNAME, methodName, "SEVERE
logging");
logger.logp(Level.WARNING, CLASSNAME, methodName, "WARNING
logging");
logger.logp(Level.INFO, CLASSNAME, methodName, "INFO
logging");
logger.logp(Level.CONFIG, CLASSNAME, methodName, "CONFIG
logging");
logger.logp(Level.FINE, CLASSNAME, methodName, "FINE
logging");
logger.logp(Level.FINER, CLASSNAME, methodName, "FINER
logging");
logger.logp(Level.FINEST, CLASSNAME, methodName, "FINEST
logging");
}

/*
* Utility methods for this package's logger
*/

/**
* Clear all of the handlers in this package's handler
* <p>
* Handlers are flushed and closed prior to being removed
* </p>
*/
protected static void clearLoggingHandlers()
{
Handler[] handlers = logger.getHandlers();
for (Handler hand : handlers)
{
hand.flush();
try
{
hand.close();
logger.removeHandler(hand);
}
catch (SecurityException se)
{
logger.logp(Level.SEVERE, CLASSNAME,
"clearLogginHandlers()",
"Exception removing handler", se);
}
}
}

/**
* Log an exception which will cause the program to exit
* <p>
* This doesn't exit the program but ensures that the logging is
displayed prior to exit
* </p>
*
* @param message The message to display
* @param className The class in which the exception occurred
* @param methodName The method in which the exception occurred
* @param exception The exception that was raised
*/
protected static void logFatalException(String message, String
className, String methodName,
Throwable exception)
{
// We're going to exit so clear all handlers
SimpleLogging.clearLoggingHandlers();

// Temporarily log to the console
ConsoleHandler cHand = new ConsoleHandler();
try
{
cHand.setLevel(Level.SEVERE);
SimpleLogging.logger.addHandler(cHand);
}
catch (SecurityException se)
{
// We're stuffed
SimpleLogging.clearLoggingHandlers();
throw se;
}
SimpleLogging.logger.logp(Level.SEVERE, className, methodName,
message, exception);

// Need to clear this handler still prior to exiting
SimpleLogging.clearLoggingHandlers();
}
}
[/verbatim]

FileLogging is the one I am having trouble with.

Thanks,

John
 
J

johnmmcparland

Hi all,

I'm playing around with the java logging package and I notice that a
lock file is always left on log file I create in my example program.
The XML file is always created.  Put these in a package called
com.johnmcparland.logging and compile / run with JDK 5.0

[verbatim]
// FileLogging.java
package com.johnmcparland.logging;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.SimpleFormatter;

/**
 * Logs stuff to a file
 */
public class FileLogging
{

    /**
     * Name of this class for logging
     */
    private static final String CLASS_NAME = "FileLogging";

    /**
     * Main program
     *
     * @param args Program arguments. Not required, any provided will
be ignored.
     */
    public static void main(String[] args)
    {
        // Clear exiting handlers (if any)
        SimpleLogging.clearLoggingHandlers();

        // Add a handler for a file
        final String methodName = "main(String[] args)";
        try
        {
            final String xmlLogFile = "FileLoggingLogFile.xml";
            FileHandler fHand = new FileHandler(xmlLogFile);
            fHand.setLevel(Level.ALL);
            SimpleLogging.logger.addHandler(fHand);
        }
        catch (IOException ioe)
        {
            SimpleLogging.logFatalException("Error setting xml log
file", CLASS_NAME, methodName, ioe);
            System.exit(-1);
        }
        catch (SecurityException se)
        {
            SimpleLogging.logFatalException("Error setting xml log
file", CLASS_NAME, methodName, se);
            System.exit(-1);
        }

        // Log using the default XML handler
        SimpleLogging.logger.logp(Level.INFO, CLASS_NAME, methodName,
                "Got file logging working for the default XML log");

        // Change to use the "human-readable" logging
        Handler[] handlers = SimpleLogging.logger.getHandlers();
        for (Handler hand : handlers)
        {
            if (hand instanceof FileHandler)
            {
                // Clear the existing handler
                try
                {
                    hand.flush();
                    hand.close();
                }
                catch (SecurityException se)
                {
                    SimpleLogging.logFatalException("Exception while
closing xml log file", CLASS_NAME,
                            methodName, se);
                    System.exit(-1);
                }

                // Set the human readable handler
                try
                {
                    final String humanLogFile =
"FileLoggingLogFile.txt";
                    hand = new FileHandler(humanLogFile);
                    hand.setFormatter(new SimpleFormatter());
                }
                catch (IOException ioe)
                {
                    SimpleLogging.logFatalException("Exception while
setting human readable log file",
                            CLASS_NAME, methodName, ioe);
                }
                catch (SecurityException se)
                {
                    SimpleLogging.logFatalException("Exception while
setting human readable log file",
                            CLASS_NAME, methodName, se);
                }
            }
        }

        // Log using the Simple formatter
        SimpleLogging.logger.logp(Level.INFO, CLASS_NAME, methodName,
                "Got file logging working using human readable log
file");

        SimpleLogging.clearLoggingHandlers();
    }}

[/verbatim]

[verbatim]
// SimpleLogging.java
package com.johnmcparland.logging;

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

/**
 * Simple example of using {@link java.util.logging}
 * <p>
 * This example is based on the examples at {@link http
 * ://java.sun.com/j2se/1.5.0/docs/api/index.html?java/util/logging/
package-summary.html}
 * </p>
 */
public class SimpleLogging
{

    /**
     * Name of the logger for this package
     */
    private static final String LOGGER_NAME =
"com.johnmmcparland.logging";

    /**
     * The logger for this package
     */
    protected static Logger logger = Logger.getLogger(LOGGER_NAME);

    /**
     * The name of this class
     */
    private static final String CLASSNAME = "SimpleLogging";

    /**
     * Main program
     *
     * @param args Program arguments. Not required, any provided will
be ignored
     */
    public static void main(String[] args)
    {
        // Clear exiting handlers (if any)
        SimpleLogging.clearLoggingHandlers();

        // Use finest level and log to console
        logger.addHandler(new ConsoleHandler());
        (new ConsoleHandler()).setLevel(Level.FINEST);
        // logger.setLevel(Level.FINEST); Doesn't work?

        /*
         * Use different log levels
         */
        final String methodName = "main(String[] args)";
        logger.logp(Level.SEVERE, CLASSNAME, methodName, "SEVERE
logging");
        logger.logp(Level.WARNING, CLASSNAME, methodName, "WARNING
logging");
        logger.logp(Level.INFO, CLASSNAME, methodName, "INFO
logging");
        logger.logp(Level.CONFIG, CLASSNAME, methodName, "CONFIG
logging");
        logger.logp(Level.FINE, CLASSNAME, methodName, "FINE
logging");
        logger.logp(Level.FINER, CLASSNAME, methodName, "FINER
logging");
        logger.logp(Level.FINEST, CLASSNAME, methodName, "FINEST
logging");
    }

    /*
     * Utility methods for this package's logger
     */

    /**
     * Clear all of the handlers in this package's handler
     * <p>
     * Handlers are flushed and closed prior to being removed
     * </p>
     */
    protected static void clearLoggingHandlers()
    {
        Handler[] handlers = logger.getHandlers();
        for (Handler hand : handlers)
        {
            hand.flush();
            try
            {
                hand.close();
                logger.removeHandler(hand);
            }
            catch (SecurityException se)
            {
                logger.logp(Level.SEVERE, CLASSNAME,
"clearLogginHandlers()",
                        "Exception removing handler", se);
            }
        }
    }

    /**
     * Log an exception which will cause the program to exit
     * <p>
     * This doesn't exit the program but ensures that the logging is
displayed prior to exit
     * </p>
     *
     * @param message The message to display
     * @param className The class in which the exception occurred
     * @param methodName The method in which the exception occurred
     * @param exception The exception that was raised
     */
    protected static void logFatalException(String message, String
className, String methodName,
            Throwable exception)
    {
        // We're going to exit so clear all handlers
        SimpleLogging.clearLoggingHandlers();

        // Temporarily log to the console
        ConsoleHandler cHand = new ConsoleHandler();
        try
        {
            cHand.setLevel(Level.SEVERE);
            SimpleLogging.logger.addHandler(cHand);
        }
        catch (SecurityException se)
        {
            // We're stuffed
            SimpleLogging.clearLoggingHandlers();
            throw se;
        }
        SimpleLogging.logger.logp(Level.SEVERE, className, methodName,
message, exception);

        // Need to clear this handler still prior to exiting
        SimpleLogging.clearLoggingHandlers();
    }}

[/verbatim]

FileLogging is the one I am having trouble with.

Thanks,

John

Solved my own problem.
// Clear the existing handler
try
{
hand.flush();
hand.close();
}

// Clear the existing handler
try
{
hand.flush();
hand.close();
// Even though you wish to re-use the existing
handler you can't.
// You need to remove it
SimpleLogging.logger.removeHandler(hand);
}

and
// Set the human readable handler
try
{
final String humanLogFile =
"FileLoggingLogFile.txt";
hand = new FileHandler(humanLogFile);
hand.setFormatter(new SimpleFormatter());
}

// Set the human readable handler
try
{
final String humanLogFile =
"FileLoggingLogFile.txt";
// Create a new handler
FileHandler txtHand = new FileHandler
(humanLogFile);
txtHand.setFormatter(new SimpleFormatter());
SimpleLogging.logger.addHandler(txtHand);
}

Basically you can't seem to reistantiate a handler instance (don't
know why) so removing and creating a new one is the way to go.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top