<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<article id="LOG4J">
  <articleinfo>
    <title>Log4J</title>
    <author>
      <firstname>Ashley</firstname>
      <othername>J.S</othername>
      <surname>Mills</surname>
      <affiliation>
        <address><email>ashley@ashleymills.com</email></address>
      </affiliation>
    </author>

    <copyright>
      <year>2005</year>
      <holder role="mailto:ashley@ashleymills.com">The University Of Birmingham</holder>
    </copyright>
  </articleinfo>

  <sect1 id="LOG4J-Introduction"><title>Introduction</title>
    <para>
      Logging within the context of program development constitutes inserting statements into the program that provide some kind of output information that is useful to the developer.  Examples of logging are trace statements, dumping of structures and the familiar System.out.println or printf debug statements. log4j offers a hierarchical way to insert logging statements within a Java program.  Multiple output formats and multiple levels of logging information are available.
    </para>

    <para>
      By using a dedicated logging package, the overhead of maintaining thousands of System.out.println statements is alleviated as the logging may be controlled at runtime from configuration scripts. log4j maintains the log statements in the shipped code. By formalising the process of logging, some feel that one is encouraged to use logging more and with higher degree of usefulness. 
    </para>
  </sect1>

  <sect1 id="LOG4J-Installation"><title>Installation</title>
    <para>
      In order to use the tools we are about to install it is necessary to setup the operating environment so that the tools know where to find stuff they need and the operating system knows where to find the tools. A understanding of how to do this is essential as you will be asked to change the operating environment. I have comprehensively covered this in documents entitled <ulink url="../winenvars/winenvarshome.html"><citetitle>Configuring A Windows Working Environment</citetitle></ulink> and <ulink url="../unixenvars/unixenvarshome.html"><citetitle>Configuring A Unix Working Environment</citetitle></ulink>.
    </para>


    <orderedlist>
      <listitem>
        <para>
          Download the log4j distribution from <ulink url="http://jakarta.apache.org/log4j/docs/download.html">http://jakarta.apache.org/log4j/docs/download.html</ulink>.
        </para>
      </listitem>
      <listitem>
        <para>Extract the archived files to some suitable directory.</para>
      </listitem>
      <listitem>
        <para>
          Add the file <filename>dist/lib/log4j-1.2.6.jar</filename> to your <envar>CLASSPATH</envar> environment variable. 
        </para>
      </listitem>
      <listitem>
        <para>
          Download <ulink url="http://apache.rmplc.co.uk/dist/xml/xerces-j/Xerces-J-bin.2.6.0.zip">http://apache.rmplc.co.uk/dist/xml/xerces-j/Xerces-J-bin.2.6.0.zip</ulink> and unzip it to a temporary directory. Copy the files <filename>xercesImpl.jar</filename> and <filename>xmlParserAPIs.jar</filename> to some permanent location and append their paths to the <envar>CLASSPATH</envar> environment variable.
        </para>
      </listitem>
    </orderedlist>
  </sect1>

  <sect1 id="LOG4J-Basics"><title>log4j Basic Concepts</title>
    <para>The use of log4j revolves around 3 main things:</para>

    <orderedlist>
      <listitem>
        <para><emphasis role="strong">public class Logger</emphasis></para>
        <para>
          <emphasis role="strong">Logger</emphasis> is responsible for handling the majority of log operations.
        </para>
      </listitem>
      <listitem>
        <para><emphasis role="strong">public interface Appender</emphasis></para>
        <para>
          <emphasis>Appender</emphasis> is responsible for controlling the output of log operations.
        </para>
      </listitem>
      <listitem>
        <para><emphasis role="strong">public abstract class Layout</emphasis></para>
        <para>
          <emphasis role="strong">Layout</emphasis> is responsible for formatting the output for <emphasis role="strong">Appender</emphasis>.
        </para>
      </listitem>
    </orderedlist>

    <sect2 id="LOG4J-Basics-Logger"><title>Logger</title>
      <para>
        The logger is the core component of the logging process. In log4j, there are 5 normal levels <emphasis role="strong">Level</emphasis>s of logger available (not including custom <emphasis role="strong">Level</emphasis>s), the following is borrowed from the log4j <acronym>API</acronym> (<ulink url="http://jakarta.apache.org/log4j/docs/api/index.html">http://jakarta.apache.org/log4j/docs/api/index.html</ulink>):
      </para>

      <itemizedlist>
        <listitem>
          <para><emphasis role="strong">static Level DEBUG</emphasis>
          </para>
          <para>
            The DEBUG Level designates fine-grained informational events that are most useful to debug an application.
          </para>
        </listitem>
        <listitem>
          <para><emphasis role="strong">static Level INFO</emphasis>
          </para>
          <para>
            The INFO level designates informational messages that highlight the progress of the application at coarse-grained level. 
          </para>
        </listitem>
        <listitem>
          <para><emphasis role="strong">static Level WARN</emphasis></para>
          <para>The WARN level designates potentially harmful situations.</para>
        </listitem>
        <listitem>
          <para><emphasis role="strong">static Level ERROR</emphasis></para>
          <para>The ERROR level designates error events that might still allow the application to continue running.</para>
        </listitem>
        <listitem>
          <para><emphasis role="strong">static Level FATAL</emphasis></para>
          <para>
            The FATAL level designates very severe error events that will presumably lead the application to abort.
          </para>
        </listitem>
      </itemizedlist>

      <para>
        In addition, there are two special levels of logging available: (descriptions borrowed from the log4j <acronym>API</acronym> <ulink url="http://jakarta.apache.org/log4j/docs/api/index.html">http://jakarta.apache.org/log4j/docs/api/index.html</ulink>):
      </para>

      <itemizedlist>
        <listitem>
          <para><emphasis role="strong">static Level ALL</emphasis></para>
          <para>The ALL Level has the lowest possible rank and is intended to turn on all logging.</para>
        </listitem>
        <listitem>
          <para><emphasis role="strong">static Level OFF</emphasis></para>
          <para>The OFF Level has the highest possible rank and is intended to turn off logging.</para>
        </listitem>        
      </itemizedlist>

      <para>The behaviour of loggers is hierarchical. The following table illustrates this:</para>

      <figure><title>Logger Output Hierarchy</title>
        <mediaobject>
          <imageobject><imagedata fileref="files/images/loggerlevels.png" format="PNG"/></imageobject>
        </mediaobject>
      </figure>

      <para>
        A logger will only output messages that are of a level greater than or equal to it. If the level of a logger is not set it will inherit the level of the closest ancestor. So if a logger is created in the package <emphasis role="strong">com.foo.bar</emphasis> and no level is set for it, it will inherit the level of the logger created in <emphasis role="strong">com.foo</emphasis>. If no logger was created in <emphasis role="strong">com.foo</emphasis>, the logger created in <emphasis role="strong">com.foo.bar</emphasis> will inherit the level of the <emphasis role="strong">root</emphasis> logger, the root logger is always instantiated and available, the root logger is assigned the level <emphasis role="strong">DEBUG</emphasis>.
      </para>

      <para>There are a number of ways to create a logger, one can retrieve the root logger:</para>

      <programlisting>Logger logger = Logger.getRootLogger();</programlisting>

      <para>One can create a new logger:</para>

      <programlisting>Logger logger = Logger.getLogger(&quot;MyLogger&quot;);</programlisting>

      <para>More usually, one instantiates a static logger globally, based on the name of the class:</para>

      <programlisting>static Logger logger = Logger.getLogger(test.class);</programlisting>

      <para>All these create a logger called &quot;logger&quot;, one can set the level with:</para>

      <programlisting>logger.setLevel((Level)Level.WARN);</programlisting>

      <para>
        You can use any of 7 levels; Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR, Level.FATAL, Level.ALL and Level.OFF.
      </para>
    </sect2>

    <sect2 id="LOG4J-Basics-Appender"><title>Appender</title>
      <para>
        The <emphasis role="strong">Appender</emphasis> controls how the logging is output. The Appenders available are (descriptions borrowed from the log4j <acronym>API</acronym> <ulink url="http://jakarta.apache.org/log4j/docs/api/index.html">http://jakarta.apache.org/log4j/docs/api/index.html</ulink>):
      </para>

      <orderedlist>
        <listitem>
          <para>
            <emphasis role="strong">ConsoleAppender:</emphasis> appends log events to System.out or System.err using a layout specified by the user. The default target is System.out.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">DailyRollingFileAppender</emphasis> extends FileAppender so that the underlying file is rolled over at a user chosen frequency.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">FileAppender</emphasis> appends log events to a file.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">RollingFileAppender</emphasis> extends FileAppender to backup the log files when they reach a certain size.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">WriterAppender</emphasis> appends log events to a Writer or an OutputStream depending on the user's choice.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">SMTPAppender</emphasis> sends an e-mail when a specific logging event occurs, typically on errors or fatal errors.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">SocketAppender</emphasis> sends LoggingEvent objects to a remote a log server, usually a SocketNode. 
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">SocketHubAppender</emphasis> sends LoggingEvent objects to a set of remote log servers, usually a SocketNodes
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">SyslogAppender</emphasis>sends messages to a remote syslog daemon. 
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">TelnetAppender</emphasis> is a log4j appender that specializes in writing to a read-only socket.
          </para>
        </listitem>
      </orderedlist>

      <para>
        One may also implement the <emphasis>Appender</emphasis> interface to create ones own ways of outputting log statements.
      </para>

      <sect3 id="LOG4J-Basics-Appender-ConsoleAppender"><title>Using A ConsoleAppender</title>
        <para>A ConsoleAppender can be created like this:</para>

        <programlisting>ConsoleAppender appender = new ConsoleAppender(new PatternLayout());</programlisting> 

        <para>
          Which creates a console appender, with a default PatternLayout. The default output of <emphasis role="strong">System.out</emphasis> is used.
        </para>
      </sect3>

      <sect3 id="LOG4J-Basics-Appender-FileAppender"><title>Using A FileAppender</title>
        <para>A FileAppender can be created like this:</para>

        <programlisting>
          FileAppender appender = null;
          try {
             appender = new FileAppender(new PatternLayout(),&quot;filename&quot;);
          } catch(Exception e) {}
        </programlisting>

        <para>The constructor in use above is:</para>

        <programlisting>
FileAppender(Layout layout, String filename) 
          Instantiate a FileAppender and open the file designated by filename.
        </programlisting>

        <para>Another useful constructor is:</para>

        <programlisting>
FileAppender(Layout layout, String filename, boolean append) 
          Instantiate a FileAppender and open the file designated by filename. 
        </programlisting>

        <para>
          So that one may choose whether or not to append the file specified or not. If this is not specified, the default is to append.
        </para>
      </sect3>

      <sect3 id="LOG4J-Basics-Appender-WriterAppender"><title>Using A WriterAppender</title>
        <para>A WriterAppender can be created like this:</para>

        <programlisting>
          WriterAppender appender = null;
          try {
            appender = new WriterAppender(new PatternLayout(),new FileOutputStream(&quot;filename&quot;));
          } catch(Exception e) {}
        </programlisting>

        <para>
          This WriterAppender uses the constructor that takes a PatternLayout and an OutputStream as arguments, in this case a FileOutputStream is used to output to a file, there are other constructors available.
        </para>
      </sect3>
    </sect2>

    <sect2 id="LOG4J-Basics-Layout"><title>Layout</title>
      <para>
        The Appender must have have an associated <emphasis role="strong">Layout</emphasis> so it knows how to format the output. There are three types of Layout available:
      </para>

      <orderedlist>
        <listitem>
          <para>
            <emphasis role="strong">HTMLLayout</emphasis> formats the output as a <acronym>HTML</acronym> table.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">PatternLayout</emphasis> formats the output based on a <emphasis>conversion pattern</emphasis> specified, or if none is specified, the default conversion pattern.
          </para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="strong">SimpleLayout</emphasis> formats the output in a very simple manner, it prints the <emphasis role="strong">Level</emphasis>, then a dash '-' and then the log message.
          </para>
        </listitem>
      </orderedlist>
    </sect2>

    <sect2 id="LOG4J-Basics-Basics-Example"><title>Basic Examples Illustrating this</title>
      <sect3 id="LOG4J-Basics-Basics-Example-SimpAndFile"><title>SimpleLayout and FileAppender</title>
        <para>Here is a very simplistic example of a program implementing a SimpleLayout and FileAppender:</para>

        <programlisting>
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import org.apache.log4j.FileAppender;
public class simpandfile {
   static Logger logger = Logger.getLogger(simpandfile.class);
   public static void main(String args[]) {
      SimpleLayout layout = new SimpleLayout();

      FileAppender appender = null;
      try {
         appender = new FileAppender(layout,&quot;output1.txt&quot;,false);
      } catch(Exception e) {}

      logger.addAppender(appender);
      logger.setLevel((Level) Level.DEBUG);

      logger.debug(&quot;Here is some DEBUG&quot;);
      logger.info(&quot;Here is some INFO&quot;);
      logger.warn(&quot;Here is some WARN&quot;);
      logger.error(&quot;Here is some ERROR&quot;);
      logger.fatal(&quot;Here is some FATAL&quot;);
   }
}
        </programlisting>

        <para>
          You can download it: <ulink url="files/simpandfile.java">simpandfile.java</ulink>. And checkout the output produced: <ulink url="files/output1.txt">output1.txt</ulink>.
        </para>
      </sect3>

      <sect3 id="LOG4J-Basics-Basics-Example-HTMLandFile"><title>HTMLLayout and WriterAppender</title>
        <para>Here is a very simplistic example of a program implementing a HTMLLayout and WriterAppender:</para>

        <programlisting>
import java.io.*;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.HTMLLayout;
import org.apache.log4j.WriterAppender;
public class htmlandwrite {
   static Logger logger = Logger.getLogger(htmlandwrite.class);
   public static void main(String args[]) {
      HTMLLayout layout = new HTMLLayout();

      WriterAppender appender = null;
      try {
         FileOutputStream output = new FileOutputStream(&quot;output2.html&quot;);
         appender = new WriterAppender(layout,output);
      } catch(Exception e) {}

      logger.addAppender(appender);
      logger.setLevel((Level) Level.DEBUG);

      logger.debug(&quot;Here is some DEBUG&quot;);
      logger.info(&quot;Here is some INFO&quot;);
      logger.warn(&quot;Here is some WARN&quot;);
      logger.error(&quot;Here is some ERROR&quot;);
      logger.fatal(&quot;Here is some FATAL&quot;);
   }
}
        </programlisting>

        <para>
          You can download it: <ulink url="files/htmlandwrite.java">htmlandwrite.java</ulink>. And checkout the output produced: <ulink url="files/output2.html">output2.html</ulink>.
        </para>
      </sect3>

      <sect3 id="LOG4J-Basics-Basics-Example-consandpatt"><title>PatternLayout and ConsoleAppender</title>
        <para>Here is a very simplistic example of a program implementing a PatternLayout and ConsoleAppender:</para>

        <programlisting>
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.ConsoleAppender;
public class consandpatt {
   static Logger logger = Logger.getLogger(consandpatt.class);
   public static void main(String args[]) {

      // Note, %n is newline
      String pattern =  &quot;Milliseconds since program start: %r %n&quot;;
             pattern += &quot;Classname of caller: %C %n&quot;;
             pattern += &quot;Date in ISO8601 format: %d{ISO8601} %n&quot;;
             pattern += &quot;Location of log event: %l %n&quot;;
             pattern += &quot;Message: %m %n %n&quot;; 
      
      PatternLayout layout = new PatternLayout(pattern);
      ConsoleAppender appender = new ConsoleAppender(layout);

      logger.addAppender(appender);
      logger.setLevel((Level) Level.DEBUG);

      logger.debug(&quot;Here is some DEBUG&quot;);
      logger.info(&quot;Here is some INFO&quot;);
      logger.warn(&quot;Here is some WARN&quot;);
      logger.error(&quot;Here is some ERROR&quot;);
      logger.fatal(&quot;Here is some FATAL&quot;);
   }
}
        </programlisting>

        <para>
          You can download it: <ulink url="files/consandpatt.java">consandpatt.java</ulink>. And checkout the output produced: <ulink url="files/output2.txt">output2.txt</ulink>.
        </para>
      </sect3>
    </sect2>
  </sect1>

  <sect1 id="LOG4J-External-Config-File"><title>Using External Configuration Files</title>
    <para>
      Log4j is usually used in conjunction with external configuration files so that options do not have to be hard-coded within the software. The advantage of using an external configuration file is that changes can be made to the options without having to recompile the software. A disadvantage could be, that due to the <emphasis>io</emphasis> instructions used, it is slightly slower.
    </para>

    <para>
      There are two ways in which one can specify the external configuration file: a plain text file or an XML file. Since everything is written in <acronym>XML</acronym> these days, this tutorial will focus on the <acronym>XML</acronym> approach but will also include relevant plain text examples. To begin with, examine the sample <acronym>XML</acronym> config file shown below:
    </para>

    <programlisting>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE log4j:configuration SYSTEM &quot;log4j.dtd&quot;&gt;

&lt;log4j:configuration xmlns:log4j=&quot;http://jakarta.apache.org/log4j/&quot;&gt;
        
  &lt;appender name=&quot;ConsoleAppender&quot; class=&quot;org.apache.log4j.ConsoleAppender&quot;&gt;
    &lt;layout class=&quot;org.apache.log4j.SimpleLayout&quot;/&gt;
  &lt;/appender&gt;

  &lt;root&gt;
    &lt;priority value =&quot;debug&quot; /&gt;
    &lt;appender-ref ref=&quot;ConsoleAppender&quot;/&gt;
  &lt;/root&gt;

&lt;/log4j:configuration&gt; 
    </programlisting>

    <para>
      The file starts with a standard <acronym>XML</acronym> declaration followed by a DOCTYPE declaration which indicates the DTD(Document Type Definition), this defines the structure of the <acronym>XML</acronym> file, what elements may be nested within other elements etc. This file is provided in the log4j distribution under <filename>src/java/org/apache/log4j/xml</filename>. Next comes the all-encapsulating <emphasis role="strong">log4j:configuration</emphasis> element, which was specified as the root element in the DOCTYPE declaration. Nested within the root element are two structures:
    </para>

    <programlisting>
  &lt;appender name=&quot;ConsoleAppender&quot; class=&quot;org.apache.log4j.ConsoleAppender&quot;&gt;
    &lt;layout class=&quot;org.apache.log4j.SimpleLayout&quot;/&gt;
  &lt;/appender&gt;      
    </programlisting>

    <para>
      Here an <emphasis>Appender</emphasis> is created and called &quot;ConsoleAppender&quot;, note that any name could have been chosen, it is because of the contrivity of examples that this name was chosen. The class for the appender is then specified in full, when referring to classes, one always uses the fully qualified class name. An <emphasis>Appender</emphasis> must always have a <emphasis>name</emphasis> and a <emphasis>class</emphasis> specified. Nested within <emphasis>Appender</emphasis> is the <emphasis>layout</emphasis> element which defines the layout to be a SimpleLayout. <emphasis>Layout</emphasis> must always have the <emphasis>class</emphasis> attribute.
    </para>

    <programlisting>
  &lt;root&gt;
    &lt;priority value =&quot;debug&quot; /&gt;
    &lt;appender-ref ref=&quot;ConsoleAppender&quot;/&gt;
  &lt;/root&gt;      
    </programlisting>

    <para>
      The root element always exists and cannot be sub-classed. The example shows the priority being set to &quot;debug&quot; and the appender setup by including an <emphasis>appender-ref</emphasis> element, of which, more that one may be specified. See the file <filename>src/java/org/apache/log4j/xml/log4j.dtd</filename> in your log4j distribution for more information about the structure of an <acronym>XML</acronym> configuration file. The configuration file is pulled into the Java program like this:
    </para>

    <programlisting>
DOMConfigurator.configure(&quot;configurationfile.xml&quot;);
    </programlisting>

    <para> 
      The <emphasis>DOMConfigurator</emphasis> is used to initialise the log4j environment using a DOM tree.  Here is the example xml configuration file: <ulink url="files/plainlog4jconfig.xml">plainlog4jconfig.xml</ulink>. Here is a program which implements this configuration file: <ulink url="externalxmltest.java">files/externalxmltest.java</ulink>:
    </para>

    <programlisting>
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
public class externalxmltest {
   static Logger logger = Logger.getLogger(externalxmltest.class);
   public static void main(String args[]) {
      DOMConfigurator.configure(&quot;xmllog4jconfig.xml&quot;);
      logger.debug(&quot;Here is some DEBUG&quot;);
      logger.info(&quot;Here is some INFO&quot;);
      logger.warn(&quot;Here is some WARN&quot;);
      logger.error(&quot;Here is some ERROR&quot;);
      logger.fatal(&quot;Here is some FATAL&quot;);
   }
}
    </programlisting>
      

    <para>Here is an XML configuration file for a Logger implementing a <emphasis>FileAppender</emphasis> using a <emphasis>PatternLayout</emphasis>:</para>

    <programlisting>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE log4j:configuration SYSTEM &quot;log4j.dtd&quot;&gt;

&lt;log4j:configuration xmlns:log4j=&quot;http://jakarta.apache.org/log4j/&quot;&gt;
        
  &lt;appender name=&quot;appender&quot; class=&quot;org.apache.log4j.FileAppender&quot;&gt;
    &lt;param name=&quot;File&quot; value=&quot;Indentify-Log.txt&quot;/&gt;
    &lt;param name=&quot;Append&quot; value=&quot;false&quot;/&gt;
    &lt;layout class=&quot;org.apache.log4j.PatternLayout&quot;&gt;
      &lt;param name=&quot;ConversionPattern&quot; value=&quot;%d [%t] %p - %m%n&quot;/&gt;
    &lt;/layout&gt;
  &lt;/appender&gt;

  &lt;root&gt;
    &lt;priority value =&quot;debug&quot;/&gt;
    &lt;appender-ref ref=&quot;appender&quot;/&gt;
  &lt;/root&gt;

&lt;/log4j:configuration&gt;
    </programlisting>

    <para>
      You can download this example from here: <ulink url="files/xmllog4jconfig2.xml">xmllog4jconfig2.xml</ulink>. For more examples of using xml files to configure a log4j environment, see the <filename>src/java/org/apache/log4j/xml/examples/</filename> directory in the log4j distribution.
    </para>

    <para>Here is the configuration file discussed above, expressed in the form of a plain text file:</para>

    <programlisting>
# initialise root logger with level DEBUG and call it BLAH
log4j.rootLogger=DEBUG, BLAH
# add a ConsoleAppender to the logger BLAH
log4j.appender.BLAH=org.apache.log4j.ConsoleAppender
# set set that layout to be SimpleLayout
log4j.appender.BLAH.layout=org.apache.log4j.SimpleLayout
    </programlisting>

    <para>
      You can download it here: <ulink url="files/plainlog4jconfig.txt">plainlog4jconfig.txt</ulink>. Here is a program implementing this:
    </para>

    <programlisting>
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class externalplaintest {
   static Logger logger = Logger.getLogger(externalplaintest.class);
   public static void main(String args[]) {
      PropertyConfigurator.configure(&quot;plainlog4jconfig.xml&quot;);
      logger.debug(&quot;Here is some DEBUG&quot;);
      logger.info(&quot;Here is some INFO&quot;);
      logger.warn(&quot;Here is some WARN&quot;);
      logger.error(&quot;Here is some ERROR&quot;);
      logger.fatal(&quot;Here is some FATAL&quot;);
   }
}
    </programlisting>

    <para>
      You can download an example program that uses this configuration file here: <filename>files/externalplaintest.java</filename>. For more examples of using plain text files to configure a log4j environment, see the <filename>examples</filename> directory in the log4j distribution.
    </para>

    <para>
      The use of external example files has only been briefly discussed here, it is assumed that you have the capacity to learn more by yourself by studying the examples provided with the log4j distribution and experimenting.
    </para>
  </sect1>

  <sect1 id="LOG4J-References"><title>References (And links you may find useful)</title>
    <itemizedlist>
      <listitem>
        <para><ulink url="http://jakarta.apache.org/log4j/docs/manual.html">http://jakarta.apache.org/log4j/docs/manual.html</ulink></para>

        <para>Short introduction to log4j - Ceki Gülcü - March 2002</para>
      </listitem>

      <listitem>
        <para><ulink url="http://www.vipan.com/htdocs/log4jhelp.html">http://www.vipan.com/htdocs/log4jhelp.html</ulink></para>

        <para>
           Don't Use System.out.println!  Use Log4j - Vipan Singla
	       </para>
      </listitem>

      <listitem>
        <para><ulink url="http://www.opensymphony.com/guidelines/logging.jsp">http://www.opensymphony.com/guidelines/logging.jsp</ulink></para>

        <para>LOG4J / OpenSymphony Logging Primer</para>
      </listitem>

      <listitem>
        <para><ulink url="http://builder.com.com/article.jhtml?id=u00820020124kev01.htm">http://builder.com.com/article.jhtml?id=u00820020124kev01.htm</ulink></para>
        <para>Add logging to your Java Applications - Kevin Brown</para>
      </listitem>
    </itemizedlist>
  </sect1>
</article>

