Sophie

Sophie

distrib > Mageia > 7 > i586 > by-pkgid > 0afd450631258dc5eee586b640925549 > files > 14

slf4j-manual-1.7.25-1.mga7.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

  <head>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
    <title>SLF4J FAQ</title>
    <link rel="stylesheet" type="text/css" media="screen" href="css/site.css" />   
    <link rel="stylesheet" type="text/css" href="css/prettify.css" />
  </head>
  <body  onload="prettyPrint(); decorate();">

  <script type="text/javascript" src="js/prettify.js"></script>
	<script type="text/javascript">prefix='';</script>

  <script type="text/javascript" src="templates/header.js"></script>
  <script type="text/javascript" src="js/jquery-min.js"></script>
  <script type="text/javascript" src="js/decorator.js"></script>

  <div id="left">
    <script src="templates/left.js" type="text/javascript"></script>
  </div>
  <div id="right">
     <script src="templates/right.js" type="text/javascript"></script>
  </div>

  <div id="content">

  <h2><a name="top">Frequently Asked Questions about SLF4J</a></h2>

  <p><b>Generalities</b></p>
  
  <ol type="1">
    <li><a href="#what_is">What is SLF4J?</a></li>
    
    <li><a href="#when">When should SLF4J be used?</a></li>
    
    <li><a href="#yet_another_facade"> Is SLF4J yet another loggingfacade?</a></li>
    
    <li><a href="#why_new_project"> If SLF4J fixes JCL, then why
    wasn't the fix made in JCL instead of creating a new project?
    </a>
    </li>
    
    <li><a href="#need_to_recompile"> When using SLF4J, do I have to
    recompile my application to switch to a different logging
    system?  
    </a>
    </li>
    
    <li><a href="#requirements">What are SLF4J's requirements?</a></li>
    
    <li><a href="#compatibility">Are SLF4J versions backward
    compatible?</a></li>

    <li><a href="#IllegalAccessError">I am getting
    <code>IllegalAccessError</code> exceptions when using SLF4J. Why
    is that?</a></li>


    <li>
      <a href="#license">Why is SLF4J licensed under X11 type
      license instead of the Apache Software License?  
      </a>
    </li>
    
    <li>
      <a href="#where_is_binding">Where can I get a particular
      SLF4J binding?
      </a>
    </li>
    
    <li>
      <a href="#configure_logging">Should my library attempt to
      configure logging?
      </a>
    </li>
    
    <li>
      <a href="#optional_dependency">In order to reduce the number of
      dependencies of our software we would like to make SLF4J an
      optional dependency. Is that a good idea?
      </a>
    </li>

    <li>
      <a href="#maven2">What about Maven transitive
      dependencies?
      </a>
    </li>
    
    <li>
      <a href="#excludingJCL">How do I exclude commons-logging as a
      Maven dependency?
      </a>
    </li>
  </ol>
  
  
  <b>About the SLF4J API</b>
  
  <ol type="1">
    
    <li>
      <a href="#string_or_object"> Why don't the printing methods
      in the Logger interface accept message of type Object, but only
      messages of type String?  
      </a>
    </li>
    
    <li>
      <a href="#exception_message">
        Can I log an exception without an accompanying message?
      </a>
    </li>
    
    
    <li>
      <a href="#logging_performance"> What is the fastest way of
      (not) logging?
      </a>
    </li>
    
    <li>
      <a href="#string_contents"> How can I log the string contents
      of a single (possibly complex) object?
      </a>
    </li>
    
    
    <li><a href="#fatal"> Why doesn't the
    <code>org.slf4j.Logger</code> interface have methods for the
    FATAL level?  </a></li>
    
    <li><a href="#trace">Why was the TRACE level introduced only in
    SLF4J version 1.4.0?  </a></li>
    
    <li><a href="#i18n">Does the SLF4J logging API support I18N
    (internationalization)? </a></li>


    <li><a href="#noLoggerFactory">Is it possible to retrieve loggers
    without going through the static methods in
    <code>LoggerFactory</code>?  </a></li>

    <li><a href="#paramException">In the presence of an
    exception/throwable, is it possible to parameterize a logging
    statement?</a></li>
    
  </ol>
  
  
  
  <b>Implementing the SLF4J API</b>
  
  <ol type="1">
    
    <li><a href="#slf4j_compatible">How do I make my logging
    framework SLF4J compatible?  </a></li>
    
    <li><a href="#marker_interface">How can my logging system add
    support for the <code>Marker</code> interface?  </a></li>
    
    <li><a href="#version_checks">How does SLF4J's version check
    mechanism work?  </a></li>
    
    
  </ol>
  
  
  <b>General questions about logging</b>
  
  
  <ol type="1">
    
    <li><a href="#declared_static"> Should Logger members of a class
    be declared as static?  </a></li>
    
    
    <li><a href="#declaration_pattern">Is there a recommended idiom
    for declaring a loggers in a class?</a></li>
    
  </ol>
  
  <h2>Generalities</h2>
  
  <dl>
    <dt class="doAnchor" name="what_is">What is SLF4J?</dt>
    <dd>
      <p>SLF4J is a simple facade for logging systems allowing the
      end-user to plug-in the desired logging system at deployment
      time.
      </p>      
    </dd>
    
    <dt class="doAnchor" name="when">When should SLF4J be used?</dt>
    
    <dd>
      <p>In short, libraries and other embedded components should
      consider SLF4J for their logging needs because libraries cannot
      afford to impose their choice of logging framework on the
      end-user. On the other hand, it does not necessarily make sense
      for stand-alone applications to use SLF4J. Stand-alone
      applications can invoke the logging framework of their choice
      directly. In the case of logback, the question is moot because
      logback exposes its logger API via SLF4J.
      </p>
      
      <p>SLF4J is only a facade, meaning that it does not provide a
      complete logging solution. Operations such as configuring
      appenders or setting logging levels cannot be performed with
      SLF4J. Thus, at some point in time, any non-trivial
      application will need to directly invoke the underlying
      logging system. In other words, complete independence from the
      API underlying logging system is not possible for a
      stand-alone application. Nevertheless, SLF4J reduces the
      impact of this dependence to near-painless levels.
      </p>
      
      <p>Suppose that your CRM application uses log4j for its
      logging. However, one of your important clients request that
      logging be performed through JDK 1.4 logging. If your
      application is riddled with thousands of direct log4j calls,
      migration to JDK 1.4 would be a relatively lengthy and
      error-prone process. Even worse, you would potentially need to
      maintain two versions of your CRM software. Had you been
      invoking SLF4J API instead of log4j, the migration could be
      completed in a matter of minutes by replacing one jar file with
      another.
      </p> 
      
      <p>SLF4J lets component developers to defer the choice of the
      logging system to the end-user but eventually a choice needs
      to be made.
      </p>
      
      
      
    </dd>
    
    <dt class="doAnchor" name="yet_another_facade">Is SLF4J yet
    another logging facade?</dt>
    
    <dd>
      <p>SLF4J is conceptually very similar to JCL. As such, it can
      be thought of as yet another logging facade. However, SLF4J is
      much simpler in design and arguably more robust. In a
      nutshell, SLF4J avoid the class loader issues that plague JCL.
      </p>
      
      
      
    </dd>
    <dt class="doAnchor" name="why_new_project">If SLF4J fixes JCL,
    then why wasn't the fix made in JCL instead of creating a new
    project?
    </dt>
    
    <dd>
      <p>This is a very good question. First, SLF4J static binding
      approach is very simple, perhaps even laughably so. It was
      not easy to convince developers of the validity of that
      approach. It is only after SLF4J was released and started to
      become accepted did it gain respectability in the relevant
      community. 
      </p>
      
      <p>Second, SLF4J offers two enhancements which tend to be
      underestimated. Parameterized log messages solve an important
      problem associated with logging performance, in a pragmatic
      way. Marker objects, which are supported by the
      <code>org.slf4j.Logger</code> interface, pave the way for
      adoption of advanced logging systems and still leave the door
      open to switching back to more traditional logging systems if
      need be.
      </p>
      
      
    </dd>
    
    <dt class="doAnchor" name="need_to_recompile">When using SLF4J, do
    I have to recompile my application to switch to a different
    logging system?
    </dt>
    
    <dd>
      <p>No, you do not need to recompile your application. You can
      switch to a different logging system by removing the previous
      SLF4J binding and replacing it with the binding of your choice.
      </p>
      
      <p>For example, if you were using the NOP implementation and
      would like to switch to log4j version 1.2, simply replace
      <em>slf4j-nop.jar</em> with <em>slf4j-log4j12.jar</em> on
      your class path but do not forget to add log4j-1.2.x.jar as
      well. Want to switch to JDK 1.4 logging?  Just replace
      <em>slf4j-log4j12.jar</em> with <em>slf4j-jdk14.jar</em>.
      </p>
      
      
    </dd>

    <dt class="doAnchor" name="requirements">What are SLF4J's
    requirements?
    </dt>
    
    <dd>
      
      <p>As of version 1.7.0, SLF4J requires JDK 1.5 or later. Earlier
      SLF4J versions, namely SLF4J 1.4, 1.5. and 1.6, required JDK
      1.4.
      </p>
      
      <p>&nbsp;</p>
      
      <table class="bodyTable striped">
        <tr align="left">
          <th>Binding</th>
          <th>Requirements</th>
        </tr>
        
        <tr>
          <td>slf4j-nop</td>
          <td>JDK 1.5</td>
        </tr>
        <tr>
          <td>slf4j-simple</td>
          <td>JDK 1.5</td>
        </tr>
        
        <tr>
          <td>slf4j-log4j12</td>
          <td align="left">JDK 1.5, plus any other library
          dependencies required by the log4j appenders in use</td>
        </tr>
        <tr>
          <td>slf4j-jdk14</td>
          <td>JDK 1.5 or later</td>
        </tr>
        <tr>
          <td>logback-classic</td>
          <td>JDK 1.5 or later, plus any other library dependencies
          required by the logback appenders in use</td>
        </tr>
        
      </table>
      
      
    </dd>

    <!-- ==================================================== -->
    <!-- entry has order dependees -->

    <dt class="doAnchor" name="compatibility">Are SLF4J versions
    backward compatible?
    </dt>

    <dd>
      <p>From the clients perspective, the SLF4J API is backward
      compatible for all versions. This means than you can upgrade
      from SLF4J version 1.0 to any later version without
      problems. Code compiled with <em>slf4j-api-versionN.jar</em>
      will work with <em>slf4j-api-versionM.jar</em> for any versionN
      and any versionM. <b>To date, binary compatibility in slf4j-api
      has never been broken.</b></p>

      <p>However, while the SLF4J API is very stable from the client's
      perspective, SLF4J bindings, e.g. slf4j-simple.jar or
      slf4j-log4j12.jar, may require a specific version of slf4j-api.
      Mixing different versions of slf4j artifacts can be problematic
      and is strongly discouraged. For instance, if you are using
      slf4j-api-1.5.6.jar, then you should also use
      slf4j-simple-1.5.6.jar, using slf4j-simple-1.4.2.jar will not
      work.
      </p>        

      <p>At initialization time, if SLF4J suspects that there may be a
      version mismatch problem, it emits a warning about the said
      mismatch. 
      </p>

      
    </dd>

    <!-- ==================================================== -->

    <dt class="doAnchor" name="IllegalAccessError">I am getting
    <code>IllegalAccessError</code> exceptions when using SLF4J. Why
    is that?
    </dt>

    <dd>

      <p>Here are the exception details.</p>

      <pre class="source">Exception in thread "main" java.lang.IllegalAccessError: tried to access field
org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
   at org.slf4j.LoggerFactory.&lt;clinit>(LoggerFactory.java:60)</pre>

      <p>This error is caused by the static initializer of the
      <code>LoggerFactory</code> class attempting to directly access
      the SINGLETON field of
      <code>org.slf4j.impl.StaticLoggerBinder</code>. While this was
      allowed in SLF4J 1.5.5 and earlier, in 1.5.6 and later the
      SINGLETON field has been marked as private access.
      </p>


      <p>If you get the exception shown above, then you are using an
      older version of slf4j-api, e.g. 1.4.3, with a new version of a
      slf4j binding, e.g. 1.5.6. Typically, this occurs when your
      Maven <em>pom.ml</em> file incorporates hibernate 3.3.0 which
      declares a dependency on slf4j-api version 1.4.2. If your
      <em>pom.xml</em> declares a dependency on an slf4j binding, say
      slf4j-log4j12 version 1.5.6, then you will get illegal access
      errors.
      </p>

      <p>To see which version of slf4j-api is pulled in by Maven, use
      the maven dependency plugin as follows.</p>

      <p class="source">mvn dependency:tree</p>

      <p>If you are using Eclipse, please do not rely on the dependency
      tree shown by <a
      href="http://m2eclipse.codehaus.org/">m2eclipse</a>.</p>

      <p>In your <em>pom.xml</em> file, explicitly declaring a
      dependency on slf4j-api matching the version of the declared
      binding will make the problem go away.
      </p>

      <p>Please also read the FAQ entry on <a
      href="#compatibility">backward compatibility</a> for a more
      general explanation.</p>

      
    </dd>
    

    <!-- ==================================================== -->

    <dt class="doAnchor" name="license">Why is SLF4J licensed under
    X11 type license instead of the Apache Software License?
    </dt>
    
    <dd>
      <p>SLF4J is licensed under a permissive X11 type license
      instead of the <a
      href="http://www.apache.org/licenses/">ASL</a> or the <a
      href="http://www.gnu.org/copyleft/lesser.html">LGPL</a>
      because the X11 license is deemed by both the Apache Software
      Foundation as well as the Free Software Foundation as
      compatible with their respective licenses.
      </p>
      
      
    </dd>

    <!-- ==================================================== -->
    <dt class="doAnchor" name="where_is_binding">Where can I get a
    particular SLF4J binding?
    </dt>
    
    <dd>
      
      <p>SLF4J bindings for <a
      href="api/org/slf4j/impl/SimpleLogger.html">SimpleLogger</a>,
      <a href="api/org/slf4j/impl/NOPLogger.html">NOPLogger</a>, <a
      href="api/org/slf4j/impl/Log4jLoggerAdapter.html">Log4jLoggerAdapter</a>
      and <a
      href="api/org/slf4j/impl/JDK14LoggerAdapter.html">JDK14LoggerAdapter</a>
      are contained within the files <em>slf4j-nop.jar</em>,
      <em>slf4j-simple.jar</em>, <em>slf4j-log4j12.jar</em>, and
      <em>slf4j-jdk14.jar</em>. These files ship with the <a
      href="download.html">official SLF4J distribution</a>. Please
      note that all bindings depend on <em>slf4j-api.jar</em>.
      </p>
      
      <p>The binding for logback-classic ships with the <a
      href="http://logback.qos.ch/download.html">logback
      distribution</a>. However, as with all other bindings, the
      logback-classic binding requires <em>slf4j-api.jar</em>.
      </p>
      
      
    </dd>
    
    <dt class="doAnchor" name="configure_logging">Should my library
    attempt to configure logging?
    </dt>
    
    <dd>
      <p><b>Embedded components such as libraries not only do not need
      to configure the underlying logging framework, they really
      should not do so</b>. They should invoke SLF4J to log but should
      let the end-user configure the logging environment. When
      embedded components try to configure logging on their own, they
      often override the end-user's wishes. At the end of the day, it
      is the end-user who has to read the logs and process them. She
      should be the person to decide how she wants her logging
      configured.
      </p>      
      
      
    </dd>
    
    <!-- ======================================================= -->

    <dt class="doAnchor" name="optional_dependency">In order to reduce
    the number of dependencies of our software we would like to make
    SLF4J an optional dependency. Is that a good idea?      
    </dt>

    <dd>
      <p><a
      href="http://stackoverflow.com/questions/978670/is-it-worth-wrapping-a-logging-framework-in-an-additional-layer">This
      question pops up</a> whenever a software project reaches a point
      where it needs to devise a logging strategy.
      </p>

      <p>Let Wombat be a software library with very few
      dependencies. If SLF4J is chosen as Wombat's logging API, then a
      new dependency on <em>slf4j-api.jar</em> will be added to
      Wombat's list of dependencies. Given that writing a logging
      wrapper does not seem that hard, some developers will be tempted
      to wrap SLF4J and link with it only if it is already present on
      the classpath, making SLF4J an optional dependency of Wombat. In
      addition to solving the dependency problem, the wrapper will
      isolate Wombat from SLF4J's API ensuring that logging in Wombat
      is future-proof. 
      </p>

      <p>On the other hand, any SLF4J-wrapper by definition depends on
      SLF4J. It is bound to have the same general API. If in the
      future a new and significantly different logging API comes
      along, code that uses the wrapper will be equally difficult to
      migrate to the new API as code that used SLF4J directly. Thus,
      the wrapper is not likely to future-proof your code, but to make
      it more complex by adding an additional indirection on top of
      SLF4J, which is an indirection in itself. 
      </p>

      <p><span class="label">increased vulnerability</span> It is
      actually worse than that. Wrappers will need to depend on
      certain internal SLF4J interfaces which change from time to
      time, contrary to the client-facing API which never
      changes. Thus, wrappers are usually dependent on the major
      version they were compiled with. A wrapper compiled against
      SLF4J version 1.5.x will not work with SLF4J 1.6 whereas client
      code using <code>org.slf4j.Logger</code>,
      <code>LoggerFactory</code>, <code>MarkerFactory</code>,
      <code>org.slf4j.Marker</code>, and <code>MDC</code> will work
      fine with any SLF4J version from version 1.0 and onwards.
      </p>

      <p>It is reasonable to assume that in most projects Wombat will
      be one dependency among many.  If each library had its own
      logging wrapper, then each wrapper would presumably need to be
      configured separately. Thus, instead of having to deal with one
      logging framework, namely SLF4J, the user of Wombat would have
      to detail with Wombat's logging wrapper as well.  The problem
      will be compounded by each framework that comes up with its own
      wrapper in order to make SLF4J optional.  (Configuring or
      dealing with the intricacies of five different logging wrappers
      is not exactly exciting nor endearing.) 
      </p>

      <p>The <a
      href="http://velocity.apache.org/engine/devel/developer-guide.html#Configuring_Logging">logging
      strategy adopted by the Velocity project</a> is a good example
      of the "custom logging abstraction" anti-pattern. By adopting an
      independent logging abstraction strategy, Velocity developers
      have made life harder for themselves, but more importantly, they
      made life harder for their users.
      </p>

      <p>Some projects try to detect the presence of SLF4J on the
      class path and switch to it if present. While this approach
      seems transparent enough, it will result in erroneous location
      information. Underlying logging frameworks will print the
      location (class name and line number) of the wrapper instead of
      the real caller. Then there is the question of API coverage as
      SLF4J support MDC and markers in addition to parameterized
      logging.  While one can come up with a seemingly working
      SLF4J-wrapper within hours, many technical issues will emerge
      over time which Wombat developers will have to deal with. Note
      that SLF4J has evolved over several years and has 260 bug
      reports filed against it.</p>

      <p>For the above reasons, developers of frameworks should resist
      the temptation to write their own logging wrapper. Not only is
      it a waste of time of the developer, it will actually make life
      more difficult for the users of said frameworks and make logging
      code paradoxically more vulnerable to change.
      </p>
    </dd>


   <!-- ======================================================= -->

    <dt class="doAnchor" name="maven2">What about Maven transitive
    dependencies?
    </dt>
    
    <dd>
      <p>As an author of a library built with Maven, you might want to
      test your application using a binding, say slf4j-log4j12 or
      logback-classic, without forcing log4j or logback-classic as a
      dependency upon your users. This is rather easy to accomplish.
      </p>

      <p>Given that your library's code depends on the SLF4J API, you
      will need to declare slf4j-api as a compile-time (default scope)
      dependency.
      </p>
      <pre class="prettyprint source">&lt;dependency&gt;
  &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
  &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
  &lt;version&gt;1.7.25&lt;/version&gt;
&lt;/dependency&gt;</pre>
      
      <p>Limiting the transitivity of the SLF4J binding used in your
      tests can be accomplished by declaring the scope of the
      SLF4J-binding dependency as "test".  Here is an example:</p>
      
      <pre class="prettyprint source">&lt;dependency&gt;
  &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
  &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
  &lt;version&gt;1.7.25&lt;/version&gt;
  <b>&lt;scope&gt;test&lt;/scope&gt;</b>
&lt;/dependency&gt;</pre>
      
      <p>Thus, as far as your users are concerned you are exporting
      slf4j-api as a transitive dependency of your library, but not
      any SLF4J-binding or any underlying logging system.
      </p>
      
      <p>Note that as of SLF4J version 1.6, in the absence of an SLF4J
      binding, slf4j-api will default to a no-operation
      implementation.
      </p>

      
      
    </dd>
    
    <!-- ====================================================== -->
    <dt class="doAnchor" name="excludingJCL">How do I exclude
    commons-logging as a Maven dependency?
    </dt>
    
    <dd>
      <p><b>alternative 1) explicit exclusion</b></p>

      <p>Many software projects using Maven declare commons-logging as
      a dependency. Therefore, if you wish to migrate to SLF4J or use
      jcl-over-slf4j, you would need to exclude commons-logging in all
      of your project's dependencies which transitively depend on
      commons-logging. <a
      href="http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html">Dependency
      exclusion</a> is described in the Maven documentation. Excluding
      commons-logging explicitly for multiple dependencies distributed
      on several <em>pom.xml</em> files can be a cumbersome and a
      relatively error prone process.
      </p>

      <p><b>alternative 2) provided scope</b></p>

      <p>Commons-logging can be rather simply and conveniently
      excluded as a dependency by declaring it in the
      <em>provided</em> scope within the pom.xml file of your
      project. The actual commons-logging classes would be provided by
      jcl-over-slf4j. This translates into the following pom file
      snippet:</p>
      
         <pre class="prettyprint source">&lt;dependency>
  &lt;groupId>commons-logging&lt;/groupId>
  &lt;artifactId>commons-logging&lt;/artifactId>
  &lt;version>1.1.1&lt;/version>
  &lt;scope>provided&lt;/scope>
&lt;/dependency>

&lt;dependency>
  &lt;groupId>org.slf4j&lt;/groupId>
  &lt;artifactId>jcl-over-slf4j&lt;/artifactId>
  &lt;version>1.7.25&lt;/version>
&lt;/dependency></pre>

      <p>The first dependency declaration essentially states that
      commons-logging will be "somehow" provided by your
      environment. The second declaration includes jcl-over-slf4j into
      your project. As jcl-over-slf4j is a perfect binary-compatible
      replacement for commons-logging, the first assertion becomes
      true.
      </p>

      <p>Unfortunately, while declaring commons-logging in the
      provided scope gets the job done, your IDE, e.g. Eclipse, will
      still place <em>commons-logging.jar</em> on your project's class
      path as seen by your IDE. You would need to make sure that
      <em>jcl-over-slf4j.jar</em> is visible before
      <em>commons-logging.jar</em> by your IDE.
      </p>

      <p><b>alternative 3) empty artifacts</b></p>
      
      <p>An alternative approach is to depend on an <b>empty</b>
      <em>commons-logging.jar</em> artifact. This clever <a
      href="http://day-to-day-stuff.blogspot.com/2007/10/announcement-version-99-does-not-exist.html">approach
      first was imagined</a> and initially supported by Erik van
      Oosten.
      </p>

      <p>The empty artifact is available from a <a
      href="http://version99.qos.ch">http://version99.qos.ch</a> a
      high-availability Maven repository, replicated on several hosts
      located in different geographical regions.</p>

      <p>The following declaration adds the version99 repository to
      the set of remote repositories searched by Maven. This
      repository contains empty artifacts for commons-logging and
      log4j. By the way, if you use the version99 repository, please
      drop us a line at &lt;version99 AT qos.ch&gt;.
      </p>

      <pre class="prettyprint source">&lt;repositories>
  &lt;repository>
    &lt;id>version99&lt;/id>
    &lt;!-- highly available repository serving empty artifacts --&gt;
    &lt;url>http://version99.qos.ch/&lt;/url>
  &lt;/repository>
&lt;/repositories></pre>
      
    <p>Declaring version 99-empty of commons-logging in the
    <code>&lt;dependencyManagement></code> section of your project
    will direct all transitive dependencies for commons-logging to
    import version 99-empty, thus nicely addressing the
    commons-logging exclusion problem. The classes for commons-logging
    will be provided by jcl-over-slf4j. The following lines declare
    commons-logging version 99-empty (in the dependency management
    section) and declare jcl-over-slf4j as a dependency.
    </p>
    
<pre class="prettyprint source">&lt;dependencyManagement>
  &lt;dependencies>
    &lt;dependency>
      &lt;groupId>commons-logging&lt;/groupId>
      &lt;artifactId>commons-logging&lt;/artifactId>
      &lt;version><b>99-empty</b>&lt;/version>
    &lt;/dependency>
    ... other declarations...
  &lt;/dependencies>
&lt;/dependencyManagement>

&lt;!-- Do not forget to declare a dependency on jcl-over-slf4j in the        --&gt;
&lt;!-- dependencies section. Note that the dependency on commons-logging     --&gt;
&lt;!-- will be imported transitively. You don't have to declare it yourself. --&gt;
&lt;dependencies>
  &lt;dependency>
    &lt;groupId>org.slf4j&lt;/groupId>
    &lt;artifactId>jcl-over-slf4j&lt;/artifactId>
    &lt;version>1.7.25&lt;/version>
  &lt;/dependency>
  ... other dependency declarations
&lt;/dependencies>
</pre>


    </dd>
    
    
    
  </dl>
  
  
  <h2>About the SLF4J API</h2>
  
  <dl>
    
    <dt class="doAnchor" name="string_or_object">Why don't the
    printing methods in the Logger interface accept message of type
    Object, but only messages of type String?
    </dt>
    
    <dd>
      
      <p>In SLF4J 1.0beta4, the printing methods such as debug(),
      info(), warn(), error() in the <a
      href="api/org/slf4j/Logger.html">Logger interface</a> were
      modified so as to accept only messages of type String
      instead of Object.
      </p>
      
      <p>Thus, the set of printing methods for the DEBUG level
      became:</p>
      
      <pre class="prettyprint source">debug(String msg); 
debug(String format, Object arg); 
debug(String format, Object arg1, Object arg2);           
debug(String msg, Throwable t);</pre>
      
      <p>Previously, the first argument in the above methods was of
      type <code>Object</code>.</p>
      
      <p>This change enforces the notion that logging systems are
      about decorating and handling messages of type String, and not
      any arbitrary type (Object).
      </p>
      
      <p>Just as importantly, the new set of method signatures offer
      a clearer differentiation between the overloaded methods
      whereas previously the choice of the invoked method due to
      Java overloading rules were not always easy to follow.</p>
      
      <p>It was also easy to make mistakes. For example, previously
      it was legal to write:</p>
      
      <pre class="prettyprint source">logger.debug(new Exception("some error"));</pre>
      
      <p>Unfortunately, the above call did not print the stack trace
      of the exception. Thus, a potentially crucial piece of
      information could be lost. When the first parameter is
      restricted to be of type String, then only the method
      </p>
      
      <pre class="prettyprint source">debug(String msg, Throwable t);</pre>
      
      <p>can be used to log exceptions. Note that this method
      ensures that every logged exception is accompanied with a
      descriptive message.</p>
      
      
    </dd>
    
    <!-- ====================================================== -->

    <dt class="doAnchor" name="exception_message">Can I log an
    exception without an accompanying message?
    </dt>

    <dd>
      <p>In short, no.</p>
      
      <p>If <code>e</code> is an <code>Exception</code>, and you
      would like to log an exception at the ERROR level, you must
      add an accompanying message. For example,</p>
      
      <pre class="prettyprint source">logger.error("some accompanying message", e);</pre>
      
      <p>You might legitimately argue that not all exceptions have a
      meaningful message to accompany them. Moreover, a good exception
      should already contain a self explanatory description. The
      accompanying message may therefore be considered redundant.
      </p>
      
      
      <p>While these are valid arguments, there are three opposing
      arguments also worth considering. First, on many, albeit not
      all occasions, the accompanying message can convey useful
      information nicely complementing the description contained
      in the exception. Frequently, at the point where the
      exception is logged, the developer has access to more
      contextual information than at the point where the exception
      is thrown. Second, it is not difficult to imagine more or
      less generic messages, e.g. "Exception caught", "Exception
      follows", that can be used as the first argument for
      <code>error(String msg, Throwable t)</code> invocations.
      Third, most log output formats display the message on a
      line, followed by the exception on a separate line. Thus,
      the message line would look inconsistent without a message.
      </p>
      
      <p>In short, if the user were allowed to log an exception
      without an accompanying message, it would be the job of the
      logging system to invent a message. This is actually what
      the <a href="http://tinyurl.com/cr9kg">throwing(String
      sourceClass, String sourceMethod, Throwable thrown)</a>
      method in java.util.logging package does. (It decides on its
      own that accompanying message is the string "THROW".)
      </p>
      
      <p>It may initially appear strange to require an accompanying
      message to log an exception. Nevertheless, this is common
      practice in <em>all</em> log4j derived systems such as
      java.util.logging, logkit, etc. and of course log4j itself. It
      seems that the current consensus considers requiring an
      accompanying message as a good a thing (TM).
      </p>
      
    </dd>     
    
    <!-- ====================================================== -->
    
    
    <dt class="doAnchor" name="logging_performance">What is the
    fastest way of (not) logging?
    </dt>

    <dd>    
      <p>SLF4J supports an advanced feature called parameterized
      logging which can significantly boost logging performance for
      <em>disabled</em> logging statement.</p>
      
      <p> For some Logger <code>logger</code>, writing,</p>
      <pre class="prettyprint source">logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));</pre>
      
      <p>incurs the cost of constructing the message parameter, that
      is converting both integer <code>i</code> and
      <code>entry[i]</code> to a String, and concatenating
      intermediate strings. This, regardless of whether the message
      will be logged or not.
      </p>        
      
      <p>One possible way to avoid the cost of parameter
      construction is by surrounding the log statement with a
      test. Here is an example.</p>
      
      <pre class="prettyprint source">if(logger.isDebugEnabled()) {
  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}</pre>
      
      
      <p>This way you will not incur the cost of parameter
      construction if debugging is disabled for
      <code>logger</code>. On the other hand, if the logger is
      enabled for the DEBUG level, you will incur the cost of
      evaluating whether the logger is enabled or not, twice: once in
      <code>debugEnabled</code> and once in <code>debug</code>.  This
      is an insignificant overhead because evaluating a logger takes
      less than 1% of the time it takes to actually log a statement.
      </p>
      
      <p><b>Better yet, use parameterized messages</b></p>
      
      <p>There exists a very convenient alternative based on message
      formats. Assuming <code>entry</code> is an object, you can write:
      </p>
      
      
      <pre class="prettyprint source">Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);</pre>
      
      <p>After evaluating whether to log or not, and only if the
      decision is affirmative, will the logger implementation format
      the message and replace the '{}' pair with the string value of
      <code>entry</code>. In other words, this form does not incur
      the cost of parameter construction in case the log statement is
      disabled.
      </p>
      
      <p>The following two lines will yield the exact same
      output. However, the second form will outperform the first
      form by a factor of at least 30, in case of a
      <em>disabled</em> logging statement.
      </p>
      
      <pre class="prettyprint source">logger.debug("The new entry is "+entry+".");
logger.debug("The new entry is {}.", entry);</pre>
      
      
      <p>A <a
      href="apidocs/org/slf4j/Logger.html#debug(java.lang.String,%20java.lang.Object%2C%20java.lang.Object)">two
      argument</a> variant is also available. For example, you can
      write:</p>
      
      
      <pre class="prettyprint source">logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);</pre>
      
      <p>If three or more arguments need to be passed, you can make
      use of the <a
      href="apidocs/org/slf4j/Logger.html#debug(java.lang.String%2C%20java.lang.Object...)"><code>Object...</code>
      variant</a> of the printing methods. For example, you can
      write:</p>
      
      <pre class="prettyprint source">logger.debug("Value {} was inserted between {} and {}.", newVal, below, above);</pre>
      
      <p>This form incurs the hidden cost of construction of an
      Object[] (object array) which is usually very small. The one and
      two argument variants do not incur this hidden cost and exist
      solely for this reason (efficiency). The slf4j-api would be
      smaller/cleaner with only the Object... variant.</p>
     
      
      <p>Array type arguments, including multi-dimensional arrays,
      are also supported.</p>
      
      <p>SLF4J uses its own message formatting implementation which
      differs from that of the Java platform. This is justified by
      the fact that SLF4J's implementation performs about 10 times
      faster but at the cost of being non-standard and less
      flexible.
      </p>
      
      <p><b>Escaping the "{}" pair</b></p>
      
      <p>The "{}" pair is called the <em>formatting anchor</em>. It
      serves to designate the location where arguments need to be
      substituted within the message pattern.
      </p>
      
      <p>SLF4J only cares about the <em>formatting anchor</em>, that
      is the '{' character immediately followed by '}'. Thus, in
      case your message contains the '{' or the '}' character, you
      do not have to do anything special unless the '}' character
      immediately follows '}'. For example,
      </p>
      
      <pre class="prettyprint source">logger.debug("Set {1,2} differs from {}", "3");</pre>
      
      <p>which will print as "Set {1,2} differs from 3". </p>
      
      <p>You could have even written,</p>
      <pre class="prettyprint source">logger.debug("Set {1,2} differs from {{}}", "3");</pre>
      <p>which would have printed as "Set {1,2} differs from {3}". </p>
      
      <p>In the extremely rare case where the the "{}" pair occurs
      naturally within your text and you wish to disable the special
      meaning of the formatting anchor, then you need to escape the
      '{' character with '\', that is the backslash character. Only
      the '{' character should be escaped. There is no need to
      escape the '}' character. For example,
      </p>
      
      <pre class="prettyprint source">logger.debug("Set \\{} differs from {}", "3");</pre>
      
      <p>will print as "Set {} differs from 3". Note that within
      Java code, the backslash character needs to be written as
      '\\'.</p>
      
      <p>In the rare case where the "\{}" occurs naturally in the
      message, you can double escape the formatting anchor so that
      it retains its original meaning. For example,</p>
      
      
      <pre class="prettyprint source">logger.debug("File name is C:\\\\{}.", "file.zip");</pre>
      <p>will print as "File name is C:\file.zip".</p>
      
    </dd>
    
    <!-- ================================================= -->
    
    <dt class="doAnchor" name="string_contents">How can I log the
    string contents of a single (possibly complex) object?</dt>
    
    <dd>
      <p> In relatively rare cases where the message to be logged
      is the string form of an object, then the parameterized
      printing method of the appropriate level can be
      used. Assuming <code>complexObject</code> is an object of
      certain complexity, for a log statement of level DEBUG, you
      can write:
      </p>
      
      <pre class="prettyprint source">logger.debug("{}", complexObject);</pre>
      
      
      <p>The logging system will invoke
      <code>complexObject.toString()</code> method only after it
      has ascertained that the log statement was
      enabled. Otherwise, the cost of
      <code>complexObject.toString()</code> conversion will be
      advantageously avoided.
      </p>
      
      
      
    </dd>
    
    <!-- ================================================= -->
    
    
    <dt class="doAnchor" name="fatal">Why doesn't the
    <code>org.slf4j.Logger</code> interface have methods for the FATAL
    level?
    </dt>
    
    <dd>      
      <p>The <a href="apidocs/org/slf4j/Marker.html">Marker</a>
      interface, part of the <code>org.slf4j</code> package, renders
      the FATAL level largely redundant. If a given error requires
      attention beyond that allocated for ordinary errors, simply mark
      the logging statement with a specially designated marker which
      can be named "FATAL" or any other name to your liking.
      </p>

      <p>Here is an example,</p>
    
<pre class="prettyprint">import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

class Bar {
  void foo() {
    <b>Marker fatal = MarkerFactory.getMarker("FATAL");</b>
    Logger logger = LoggerFactory.getLogger("aLogger");

    try {
      ... obtain a JDBC connection
    } catch (JDBException e) {
      logger.error(<b>fatal</b>, "Failed to obtain JDBC connection", e);
    }
  }
}</pre>


      <p>While markers are part of the SLF4J API, only logback
      supports markers off the shelf. For example, if you add the
      <code>%marker</code> conversion word to its pattern, logback's
      <code>PatternLayout</code> will add marker data to its
      output. Marker data can be used to <a
      href="http://logback.qos.ch/manual/filters.html">filter
      messages</a> or even <a
      href="http://logback.qos.ch/manual/appenders.html#OnMarkerEvaluator">trigger</a>
      an outgoing email <a
      href="http://logback.qos.ch/recipes/emailPerTransaction.html">at
      the end of an individual transaction</a>.
      </p>

      <p>In combination with logging frameworks such as log4j and
      java.util.logging which do not support markers, marker data will
      be silently ignored.</p>

      <p>Markers add a new dimension with infinite possible values for
      processing log statements compared to five values, namely ERROR,
      WARN, INFO, DEBUG and TRACE, allowed by levels. At present time,
      only logback supports marker data. However, nothing prevents
      other logging frameworks from making use of marker data.
      </p>
      
    </dd>
    
    <!-- ======================================================= -->
    <dt class="doAnchor" name="trace">Why was the TRACE level
    introduced only in SLF4J version 1.4.0?</dt>
    
    <dd>
      
      <p>The addition of the TRACE level has been frequently and
      hotly debated request. By studying various projects, we
      observed that the TRACE level was used to disable logging
      output from certain classes <em>without</em> needing to
      configure logging for those classes. Indeed, the TRACE level
      is by default disabled in log4j and logback as well most other
      logging systems. The same result can be achieved by adding the
      appropriate directives in configuration files.
      </p>
      
      <p>Thus, in many of cases the TRACE level carried the same
      semantic meaning as DEBUG. In such cases, the TRACE level
      merely saves a few configuration directives. In other, more
      interesting occasions, where TRACE carries a different meaning
      than DEBUG, <a href="api/org/slf4j/Marker.html">Marker</a>
      objects can be put to use to convey the desired
      meaning. However, if you can't be bothered with markers and
      wish to use a logging level lower than DEBUG, the TRACE level
      can get the job done.
      </p>
      
      <p>Note that while the cost of evaluating a disabled log
      request is in the order of a few <code>nanoseconds</code>, the
      use of the TRACE level (or any other level for that matter) is
      discouraged in tight loops where the log request might be
      evaluated millions of times. If the log request is enabled,
      then it will overwhelm the target destination with massive
      output. If the request is disabled, it will waste resources.
      </p>
      
      <p>In short, although we still discourage the use of the TRACE
      level because alternatives exist or because in many cases log
      requests of level TRACE are wasteful, given that people kept
      asking for it, we decided to bow to popular demand.
      </p>
      
      
    </dd>

    <!-- ================================================= -->
    <dt class="doAnchor" name="i18n">Does the SLF4J logging API
    support I18N (internationalization)?
    </dt>
    
    <dd>
      <p>Yes, as of version 1.5.9, SLF4J ships with a package called
      <code>org.slf4j.cal10n</code> which adds <a
      href="localization.html">localized/internationalized logging</a>
      support as a thin layer built upon the <a
      href="http://cal10n.qos.ch">CAL10N API</a>.</p>

      
    </dd>          

    <!-- ================================================= -->

    <dt class="doAnchor" name="noLoggerFactory">Is it possible to
    retrieve loggers without going through the static methods in
    <code>LoggerFactory</code>?
    </dt>

    <dd>

      <p>Yes. <code>LoggerFactory</code> is essentially a wrapper
      around an <a
      href="xref/org/slf4j/ILoggerFactory.html"><code>ILoggerFactory</code></a>
      instance. The <code>ILoggerFactory</code> instance in use is
      determined according to the static binding conventions of the
      SLF4J framework. See the <a
      href="xref/org/slf4j/LoggerFactory.html#217">getSingleton()</a>
      method in <code>LoggerFactory</code> for details.
      </p>

      <p>However, nothing prevents you from using your own
      <code>ILoggerFactory</code> instance. Note that you can also
      obtain a reference to the <code>ILoggerFactory</code> that the
      <code>LoggerFactory</code> class is using by invoking the <a
      href="apidocs/org/slf4j/LoggerFactory.html#getILoggerFactory()">
      <code>LoggerFactory.getILoggerFactory()</code></a> method.
      </p>

      <p>Thus, if SLF4J binding conventions do not fit your needs, or
      if you need additional flexibility, then do consider using the
      <code>ILoggerFactory</code> interface as an alternative to
      inventing your own logging API.</p>
    </dd>
    
    <!-- ================================================= -->

    <dt class="doAnchor" name="paramException">In the presence of an
    exception/throwable, is it possible to parameterize a logging
    statement?</dt>


    <dd>
      <p>Yes, as of SLF4J 1.6.0, but not in previous versions. The
      SLF4J API supports parametrization in the presence of an
      exception, assuming the exception is the last parameter. Thus,
    </p>
    <pre class="prettyprint">String s = "Hello world";
try {
  Integer i = Integer.valueOf(s);
} catch (NumberFormatException e) {
  logger.error("Failed to format {}", s, e);
}</pre>

     <p>will print the <code>NumberFormatException</code> with its
     stack trace as expected. The java compiler will invoke the <a
     href="http://www.slf4j.org/apidocs/org/slf4j/Logger.html#error%28java.lang.String,%20java.lang.Object,%20java.lang.Object%29">error
     method taking a String and two Object arguments</a>. SLF4J, in
     accordance with the programmer's most probable intention, will
     interpret <code>NumberFormatException</code> instance as a
     throwable instead of an unused <code>Object</code> parameter. In
     SLF4J versions prior to 1.6.0, the
     <code>NumberFormatException</code> instance was simply ignored.
     </p>

     <p>If the exception is not the last argument, it will be treated
     as a plain object and its stack trace will NOT be printed.
     However, such situations should not occur in practice.
     </p>
    
    </dd>
  </dl>


  
  <h2>Implementing the SLF4J API</h2>
  
  <dl>

    <!-- ============================================================= -->

    <dt class="doAnchor" name="slf4j_compatible">How do I make my
    logging framework SLF4J compatible?
    </dt>
    
    
    <dd>
      
      <p>Adding supporting for the SLF4J is surprisingly
      easy. Essentially, you coping an existing binding and tailoring
      it a little (as explained below) does the trick.
      </p>
      
      <p>Assuming your logging system has notion of a
      logger, called say <code>MyLogger</code>, you need to provide
      an adapter for <code>MyLogger</code> to
      <code>org.slf4j.Logger</code> interface. Refer to slf4j-jcl,
      slf4j-jdk14, and slf4j-log4j12 modules for examples of
      adapters.
      </p>
      
      <p>Once you have written an appropriate adapter, say
      <code>MyLoggerAdapter</code>, you need to provide a factory
      class implementing the <code>org.slf4j.ILoggerFactory</code>
      interface. This factory should return instances
      <code>MyLoggerAdapter</code>. Let <code>MyLoggerFactory</code>
      be the name of your factory class.
      </p>
      
      <p>Once you have the adapter, namely
      <code>MyLoggerAdapter</code>, and a factory, namely
      <code>MyLoggerFactory</code>, the last remaining step is to
      modify the <code>StaticLoggerBinder</code> class so that it
      returns an new instance of <code>MyLoggerFactory</code>. You
      will also need to modify the
      <code>loggerFactoryClassStr</code> variable.
      </p>
      
      <p>For Marker or MDC support, you could use the one of the
      existing NOP implementations.
      </p>
      
      <p>In summary, to create an SLF4J binding for your logging
      system, follow these steps:</p>
      
      <ol>
        <li>start with a copy of an existing module,</li>
        <li>create an adapter between your logging system and
        <code>org.slf4j.Logger</code> interface
        </li>
        <li>create a factory for the adapter created in the previous step,</li>
        <li>modify <code>StaticLoggerBinder</code> class to use the
        factory you created in the previous step</li>
      </ol>
      
      
    </dd>

    <!-- ============================================================= -->

    <dt class="doAnchor" name="marker_interface">How can my logging
    system add support for the <code>Marker</code> interface?
    </dt>
    <dd>
      
      <p>Markers constitute a revolutionary concept which is
      supported by logback but not other existing logging
      systems. Consequently, SLF4J conforming logging systems are
      allowed to ignore marker data passed by the user.
      </p>
      
      <p>However, even though marker data may be ignored, the user
      must still be allowed to specify marker data. Otherwise, users
      would not be able to switch between logging systems that
      support markers and those that do not.  
      </p>
      
      <p>The <code>MarkerIgnoringBase</code> class can serve as a
      base for adapters or native implementations of logging
      systems lacking marker support. In
      <code>MarkerIgnoringBase</code>, methods taking marker data
      simply invoke the corresponding method without the Marker
      argument, discarding any Marker data passed as
      argument. Your SLF4J adapters can extend
      <code>MarkerIgnoringBase</code> to quickly implement the
      methods in <code>org.slf4j.Logger</code> which take a
      <code>Marker</code> as the first argument.
      </p>
      
      
    </dd>
    
    <!-- ============================================================= -->

    <dt class="doAnchor" name="version_checks">How does SLF4J's
    version check mechanism work?
    </dt>
    
    <dd>
      <p>The version check performed by SLF4J API during its
      initialization is an <em>elective</em> process. Conforming SLF4J
      implementations may choose <em>not</em> to participate, in which
      case, no version check will be performed.
      </p>
      
      <p>However, if an SLF4J implementation decides to participate,
      than it needs to declare a variable called
      REQUESTED_API_VERSION within its copy of the
      <code>StaticLoggerBinder</code> class. The value of this
      variable should be equal to the version of the slf4j-api.jar
      it is compiled with. If the implementation is upgraded to a
      newer version of slf4j-api, than you also need to update the
      value of REQUESTED_API_VERSION. 
      </p>
      
      <p>For each version, SLF4J API maintains a list of compatible
      versions. SLF4J will emit a version mismatch warning only if
      the requested version is not found in the compatibility
      list. So even if your SLF4J binding has a different release
      schedule than SLF4J, assuming you update the SLF4J version you
      use every 6 to 12 months, you can still participate in the
      version check without incurring a mismatch warning. For
      example, logback has a different release schedule but still
      participates in version checks.</p>
      
      <p><b>As of SLF4J 1.5.5</b>, all bindings shipped within the
      SLF4J distribution, e.g. slf4j-log4j12, slf4j-simple and
      slf4j-jdk14, declare the REQUESTED_API_VERSION field with a
      value equal to their SLF4J version. It follows that, for example
      if slf4j-simple-1.5.8.jar is mixed with slf4j-api-1.6.0.jar,
      given that 1.5.8 is not on the compatibility list of SLF4J
      version 1.6.x, a version mismatch warning will be issued.
      </p>

      <p>Note that SLF4J versions prior to 1.5.5 did not have a
      version check mechanism.  Only slf4j-api-1.5.5.jar and later can
      emit version mismatch warnings.
      </p>

      
    </dd>
    
  </dl>
  
  <h2>General questions about logging</h2>
  
  

  <dl>

    <!-- ============================================================= -->
    <dt class="doAnchor" name="declared_static">Should Logger members
    of a class be declared as static?
    </dt>
    <dd>
      
      <p>We <code>used</code> to recommend that loggers members be
      declared as instance variables instead of static. After further
      analysis, <b>we no longer recommend one approach over the
      other.</b>
      </p>
      
      <p>Here is a summary of the pros and cons of each approach.
      </p>
      
      <table class="bodyTable">
        <tr valign="top">
          <th width="50%">Advantages for declaring loggers as static</th>       
          <th width="50%">Disadvantages for declaring loggers as static</th>              
        </tr>
        <tr  valign="top" class="alt">
          <td>
            <ol>
              <li>common and well-established idiom</li>
              <li>less CPU overhead: loggers are retrieved and
              assigned only once, at hosting class
              initialization</li>
              <li>less memory overhead: logger declaration will
              consume one reference per class</li>            
            </ol>
          </td>
          
          <td> <!-- static con -->
            <ol>
              <li>For libraries shared between applications, not
              possible to take advantage of repository selectors. It
              should be noted that if the SLF4J binding and the
              underlying API ships with each application (not shared
              between applications), then each application will still
              have its own logging environment.  
              </li>
              <li>not IOC-friendly</li>
            </ol>
          </td>
        </tr>
        
        <tr>
          <th width="50%">Advantages for declaring loggers as instance variables</th>       
          <th width="50%">Disadvantages for declaring loggers as
          instance variables</th>
        </tr>
        
        <tr class="alt" valign="top">
          <td> <!-- instance pros -->
            <ol>
              <li>Possible to take advantage of repository selectors
              even for libraries shared between applications. However,
              repository selectors only work if the underlying logging
              system is logback-classic. Repository selectors do not
              work for the SLF4J+log4j combination.
              </li>
              <li>IOC-friendly</li>
            </ol>
          </td>
          
          <td> <!-- instance cons -->
            <ol>
              <li>Less common idiom than declaring loggers as static
              variables</li>
              
              <li>higher CPU overhead: loggers are retrieved and
              assigned for each instance of the hosting class</li>
              
              <li>higher memory overhead: logger declaration will
              consume one reference per instance of the hosting class</li>                   
            </ol>
          </td>
        </tr>        
      </table>
      
      
      <h3>Explanation</h3>
      
      <p>Static logger members cost a single variable reference for
      all instances of the class whereas an instance logger member
      will cost a variable reference for every instance of the
      class. For simple classes instantiated thousands of times
      there might be a noticeable difference.
      </p>
      
      <p>However, more recent logging systems, e.g log4j or logback,
      support a distinct logger context for each application running
      in the application server. Thus, even if a single copy of
      <em>log4j.jar</em> or <em>logback-classic.jar</em> is deployed
      in the server, the logging system will be able to differentiate
      between applications and offer a distinct logging environment
      for each application.
      </p>
      
      <p>More specifically, each time a logger is retrieved by
      invoking <code>LoggerFactory.getLogger()</code> method, the
      underlying logging system will return an instance appropriate
      for the current application. Please note that within the
      <em>same</em> application retrieving a logger by a given name
      will always return the same logger. For a given name, a
      different logger will be returned only for different
      applications.
      </p>
      
      <p>If the logger is static, then it will only be retrieved once
      when the hosting class is loaded into memory. If the hosting
      class is used in only in one application, there is not much to
      be concerned about. However, if the hosting class is shared
      between several applications, then all instances of the shared
      class will log into the context of the application which
      happened to first load the shared class into memory - hardly the
      behavior expected by the user.
      </p>
      
      <p>Unfortunately, for non-native implementations of the SLF4J
      API, namely with slf4j-log4j12, log4j's repository selector will
      not be able to do its job properly because slf4j-log4j12, a
      non-native SLF4J binding, will store logger instances in a map,
      short-circuiting context-dependent logger retrieval. For native
      SLF4J implementations, such as logback-classic, repository
      selectors will work as expected.
      </p>          
      
      <p>The Apache Commons wiki contains an <a
      href="http://wiki.apache.org/jakarta-commons/Logging/StaticLog">informative
      article</a> covering the same question.</p>
      
      <p><b>Logger serialization</b></p>
      
      <p>Contrary to static variables, instance variables are
      serialized by default. As of SLF4J version 1.5.3, logger
      instances survive serialization. Thus, serialization of the host
      class no longer requires any special action, even when loggers
      are declared as instance variables. In previous versions, logger
      instances needed to be declared as <code>transient</code> in the
      host class. </p>
      
      <p><b>Summary</b></p>
      
      <p>In summary, declaring logger members as static variables
      requires less CPU time and have a slightly smaller memory
      footprint. On the other hand, declaring logger members as
      instance variables requires more CPU time and have a slightly
      higher memory overhead.  However, instance variables make it
      possible to create a distinct logger environment for each
      application, even for loggers declared in shared
      libraries. Perhaps more important than previously mentioned
      considerations, instance variables are IOC-friendly whereas
      static variables are not.
      </p>    
     
      <p>See also <a
      href="http://wiki.apache.org/jakarta-commons/Logging/StaticLog">related
      discussion</a> in the commons-logging wiki.
      </p>
      
    </dd>       
  </dl>
  
  <!-- ============================================================= -->
  <dl>
    <dt class="doAnchor" name="declaration_pattern">Is there a
    recommended idiom for declaring a logger in a class?
    </dt>
    
    <dd>
      <p>The following is the recommended logger declaration
      idiom. For reasons <a href="#declared_static">explained
      above</a>, it is left to the user to determine whether loggers
      are declared as static variables or not.</p>
      
      <pre class="prettyprint source">package some.package;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
      
public class MyClass {
  <b>final (static) Logger logger = LoggerFactory.getLogger(MyClass.class);</b>
  ... etc
}</pre>
      
      <p>Unfortunately, given that the name of the hosting class is
      part of the logger declaration, the above logger declaration
      idiom is <em>not</em> resistant to cut-and-pasting between
      classes.
      </p>
    </dd>
  </dl>
    
  <script src="templates/footer.js" type="text/javascript"></script>
</div>
</body>
</html>