ADFLogger: Using a Custom Formatter Class to Print Log Messages

Based on some posts on the OTN JDeveloper forum this article shows how to implement a custom fdormatter class to use with ADFLogging and how to integrate it with the embedded WLS instance in JDeveloper. Sample workspace for the custom logger is available at the end of the article.
For this post I assume you now your way around java.util.logging. I show how to implement a custom formatter class to format the log messages with more information and a different style. The picture below shows the general java logging model:

General Logging Model

General Logging Model

As the model shows the formatter is used by the log handler which gets a log record and processes it by piping the record through a filter and then through a formatter to finaly pass it to the attached output target. In most cases the output target is a file, a db table, a system log or a stream. For the console logger its most often a stream (e.g. stdout and/or stderr).

A typlical JDev log message from the ConsoleFormatter looks like this:

<AdfcAppInitializer> <loadDebugFacades> ADFc: Initializing ADF Debugger

I’ll change this to:

FINE: 22.09.2011 13:18:17 -$beaVersion0_39.selectionListenerEmp( - 15 -
  Selected: oracle.jbo.Key[105 ]

The general layout of the log message is

data in [] is customizable, data in {} is printed only if available
level: date time [- threadId] [- class] [- method] [- message] {- throwable.message}
These parameters configure which information to print
       t = thread
       n = logger name
       l = line number; if 'l' is selected 'c' and 'm' are not used
       c = class name
       m = method name

As you see there is more information printed, e.g. source and line number and log level. As this creates long log lines I made this customizable. How the parameters are passed to the logger is shown later.

First of all I implement a class DebugFormatter which extends java.util.logging.SimpleFromatter as this class is an implementation of the abstract class java.util.logging.Formatter the base of all formatter attached to a log handler. The key part of this class is the method

public String format(LogRecord record) {...}

which gets a log record and returns a string of the information which send to the handler for further action. The format method checks the parameters given and returns a string according to them.

To wire things up I modify the logging.xml file which can be reached from the ‘Application Server Navigator’. Right click on the integrated WLS and select ‘Configure Oracle Diagnostic Logging for …’. This will open a nice graphical overview



Now I add a new logger by clicking the green ‘+’ sign and specifying the log level and the name of the logger, which is actually the part of the class path the logger reacts on.
Add  Logger

Add Logger

this creates a new line in the logging.xml file looking like
Added Line

Added Line

Next I set up a new log handler in the logging.xml file which uses my DebugLogger class as formatter. Together with the log handler I specify the parameters which configure the output format of the string. The DebugLogger is not used directly, but instead a wrapper class WLSConsoleFormatter used which specifies default parameter set to the DebugFormatter. This way you can omit the parameters in the setup. Below is the resulting log handler entry in the logging.xml file:

        <log_handler name='blog-console-handler'
                     class='' level='ALL'
            <property name='formatStyle' value='tnlcm'/>
            <property name='formatter'

To add this you need to change to the source view for the logging.xml file.
Finally I change the added logger to use the new handler

        <logger name='de' level='TRACE:1' useParentHandlers='false'>
            <handler name='blog-console-handler'/>
            <handler name="odl-handler"/>

I have to set the useParentHandlers to false to prevent that the messages get printed multiple times. To be able to analyze the messages with the log analyzer I add the ODL handler too. Now all log messages are printed to the console and to the ODL logger.

Now that the logger are setup in the logging.xml all I need to do is to make the classes available to the WLS instance. For this I build a jar from the project and put the resulting BlogConsoleFormatter.jar in a folder where WLS picks it up while starting. There a a couple of folder, but I choose <ide.system.dir>/DefaultDomain/lib folder. ide.system.dir is also known as the systemfolder of your JDeveloper installation. If you don't know where to find it check this blog. You can either copy the jar into the folder or setup the deployment profile to generate the jar in this folder.

Sample Oiutout

Sample Oiutout

The picture above show a small code sample with the generated output from DebugFormatter. As you see the log lines are marked as links. If you click on such a line you see that you are transfered to the code location of the message.

You can download the source code for the and a using the ADFLogger to generate messages in different log levels. After downloading the files you need to remove the ‘.doc’ suffix and rename them to ‘.zip’ as the files are normal zip files.
The sample workspaces are developed with JDeveloper, BlogPopupRegion uses the HR schema as DB connection.

About these ads

14 thoughts on “ADFLogger: Using a Custom Formatter Class to Print Log Messages

  1. Hi Timo,

    Great Job Done…
    Thanks a ton…. I was waiting for this post of yours……. you have shown us how to format log for console handler will it work for odlhandler (and other file handlers) and how??

    • In theory you can do something similar with the ODL handler, but you should not. The ODL handler collects many more information and uses an XML format which. is later shown to the user via the ‘Log Analyzer’. This is more like an XML transformation then to change the output format.
      However, you can write the output of a custom logger in a file so that you get the log in a format you want.

  2. Hi Timo,

    I see a class “BlogLogger” in Can I use that class to create logs without modifying logging.xml? If so, how and when to call that getInstance() method?


  3. Hello Mr. Hahn,
    Thanks for your great post, very usefull.

    I wrote a custom log handler using your example. I would like to have access to not only the ADF Message (of oracle.jbo, oracle.adf and oracle.adfinternal), but also to the ADF Message data, as seen in the ADF Request Logger in JDeveloper, see (screenprint just under section ‘But Wait, There’s More’). I tried several ways, but I dont see how how it is possible to get access to that data when i’m in the custom LogHandler. I still have valuable data, but only half of what should be possible. Do you pease have any suggestions ?

    • Frank,
      I see this as part of the analyze function. Here you use information from different log records to genders the info you see if you select ‘by ADF record’.
      As all loggers use java.util.logging as framework I’m not sure how you would access this kind info when writing one log message.


  4. Pingback: Customize ADF Logger with IP and Username information | SOLARKID.INFO

  5. Hi,
    Very nice post.
    However, I’ve got an error message when I attempt to change the level of the logger on the fly.
    Weblogic doesn’t find anymore the jar and its classes. Could you help me ?
    But if you don’t change the level, it works perfectly !


    • Somehow the class loader looses track of the jar. Seen this in one instance too. I never found out exactly why. Solution was to add the library to the start class path of the WLS. For this you can change the start environment (e.g. setDomainEnv.cmd for windows) and add a line like
      Then the jar will we part of the startpath and the class loader will pick it up and keep it.

  6. Hi,
    Thanks a lot for the detailed explanation. Very helpful.

    It works great except for one weird behavior. Whenever the logging is done from a Managed Bean, the Log statement doesn’t give the Logging class name and line number – but like ADFLogger:1166 as the name and line number. The method name is coming correct, just the class name is different.

    Any idea why this is happening?

    Thanks for your input.

    • Which version of Jdev do you use?
      I guess the problem is the depth of the stack trace. Depending on the version the line number is calculate differently.

  7. Hi Timo,

    This is the best article I have read so far on ADFLogger esp using formatter.
    Really appreciate the detailed explanation.

    But I have few questions:
    1] Everything works perfectly if we want the output to be on console. But how to divert the log messages to a file?
    I tried using the path property but its not working..
    <property name='path' value='${domain.home}/servers/${weblogic.Name}/logs/test.log'
    I even tried with -Djbo.debugoutput=adflogger option but its not working..

    Or is it like using the above approach we cannot divert the log messages to a file?
    Or am I missing anything?

    2] Is it possible in any way to append the system date to the file name? I even approached the Oracle support team, but they did not help me.

    Am using Jdev 12.1.2

    Thanks in Advance,

    • MJ,
      1) you just have to add another handler (look a the first image). The blog defines a formatter which styles the message. For redirecting it into a file you add another handler to the logger which writes into a file. I would not advice to use your own format if you write into a file as you probable break the log analyzer format (which makes your file analyzable from within JDev or EM).
      2) I don’t know. You should be able to write your own handler which you can instruct to set the file name as you like.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s