Search code examples
javajakarta-eeloggingjava-web-startjava.util.logging

Unable to set log level in a Java web start application?


Some logging levels appear to be broke?

I run a Java web start (which I will begin to call JWS from now on) application straight from a GlassFish 3.1.2.2 instance. The client has a static logger like so:

private final static Logger LOGGER;
static {
    LOGGER = Logger.getLogger(App.class.getName());
    // Not sure how one externalize this setting or even if we want to:
    LOGGER.setLevel(Level.FINER);
}

In the main method, I begin my logic with some simple testing of the logging feature:

alert("isLoggable() INFO? " + LOGGER.isLoggable(Level.INFO));     // Prints TRUE!
alert("isLoggable() FINE? " + LOGGER.isLoggable(Level.FINE));     // ..TRUE
alert("isLoggable() FINER? " + LOGGER.isLoggable(Level.FINER));   // ..TRUE
alert("isLoggable() FINEST? " + LOGGER.isLoggable(Level.FINEST)); // ..FALSE

My alert methods will display a JOptionPane dialog box for "true GUI logging". Anyways, you see the printouts in my comments I added to the code snippet. As expected, the logger is enabled for levels INFO, FINE and FINER but not FINEST.

After my alert methods, I type:

// Info
LOGGER.info("Level.INFO");
LOGGER.log(Level.INFO, "Level.INFO");

// Fine
LOGGER.fine("Level.FINE");
LOGGER.log(Level.FINE, "Level.FINE");

// Finer
LOGGER.finer("Level.FINER");
LOGGER.log(Level.FINER, "Level.FINER");
LOGGER.entering("", "Level.FINER", args); // <-- Uses Level.FINER!

// Finest
LOGGER.finest("Level.FINEST");
LOGGER.log(Level.FINEST, "Level.FINEST");

I go to my Java console and click on the tab "Advanced", then I tick "Enable logging". Okay let's start the application. Guess what happens? Only Level.INFO prints! Here's my proof (look at the bottom):

enter image description here

I've done my best to google for log files on my computer and see if not Level.FINE and Level.FINER end up somewhere on the file system. However, I cannot find the log messages anywhere.

Summary of Questions

  1. Why does it appear that logging of Level.FINE and Level.FINER does not work in the example provided?

  2. I set the logging level in my static initializing block, but I'd sure like to externalize this setting to a configuration file of some sort, perhaps packaged together with the EAR file I deploy on GlassFish. Or why not manually write in some property in the JNLP file we download from the server. Is this possible somehow?


Solution

  • Solution for problem no 1.

    After doing a little bit more reading on the topic, I concluded that a logger in Java uses a handler to publish his logs. And this handler in his turn has his own set of "walls" for what levels he handles. But this handler need not be attached directly to our logger! You see loggers are organized in a hierarchical namespace and a child logger may inherit his parents handlers. If so, then By default a Logger will log any output messages to its parent's handlers, and so on recursively up the tree (see Java Logging Overview - Oracle).

    I ain't saying I get the full picture just yet, and I sure didn't find any quotes about how all of this relates to a Java Web Start application. Surely there has to be some differences. Anyways, I did manage to write together this static initializing block that solves my immediate problem:

    static {
        LOGGER = Logger.getLogger(App.class.getName());
        /*
         * This logic can be externalized. See the next solution!
         */
        // DEPRECATED: LOGGER.setLevel(Level.FINER);
        if (LOGGER.getUseParentHandlers())
            LOGGER.getParent().getHandlers()[0].setLevel(Level.FINER);
        else
            LOGGER.setLevel(Level.FINER);
    }
    

    Solution for problem no 2.

    The LogManager API docs provided much needed information for the following solution. In a subdirectory of your JRE installation, there is a subdirectory called "lib" and in there you shall find a "logging.properties" file. This is the full path to my file on my Windows machine:

    C:\Program Files (x86)\Java\jre7\lib\logging.properties

    In here you can change a lot of flavors. One cool thing you could do is to change the global logging level. In my file, this was done on row 29 (why do we see only a dot in front of the "level"? The root-parent of all loggers is called ""!). That will produce a hole lot of output; on my machine I received about one thousand log messages per second. Thus changing the global level isn't even plausible enough to be considered an option. Instead, add a new row where you specify the level of your logger. In my case, I added this row:

    martinandersson.com.malivechat.app.App.level = FINER

    However, chances are you still won't see any results. In solution no 1, I talked about how loggers are connected to handlers. The default handler is specified in logging.properties, most likely on row 18. Here's how my line reads:

    handlers= java.util.logging.ConsoleHandler

    Also previously, I talked about how these handlers in their turn use levels for what should trouble their mind. So, find the line that reads something like this (should now be on row 44?):

    java.util.logging.ConsoleHandler.level = INFO

    ..and in my case I swapped "INFO" to "FINER". Problem solved.

    But!

    My original inquiry into this matter still hasn't provided an answer how one can set these properties closer in par with the application deployment. More specifically, I would like to attach these properties in a separate file, bundled with the application EAR file I deploy on GlassFish or something like that. Do you have more information? Please share!