Home | History | Annotate | Download | only in pages
      1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      2   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      3 <html xmlns="http://www.w3.org/1999/xhtml">
      4 
      5   <head>
      6     <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
      7     <title>SLF4J FAQ</title>
      8     <link rel="stylesheet" type="text/css" media="screen" href="css/site.css" />   
      9     <link rel="stylesheet" type="text/css" href="css/prettify.css" />
     10   </head>
     11   <body  onload="prettyPrint(); decorate();">
     12 
     13   <script type="text/javascript" src="js/prettify.js"></script>
     14 	<script type="text/javascript">prefix='';</script>
     15 
     16   <script type="text/javascript" src="templates/header.js"></script>
     17   <script type="text/javascript" src="js/jquery-min.js"></script>
     18   <script type="text/javascript" src="js/decorator.js"></script>
     19 
     20   <div id="left">
     21     <script src="templates/left.js" type="text/javascript"></script>
     22   </div>
     23 
     24   <div id="content">
     25 
     26   <h2><a name="top">Frequently Asked Questions about SLF4J</a></h2>
     27 
     28   <p><b>Generalities</b></p>
     29   
     30   <ol type="1">
     31     <li><a href="#what_is">What is SLF4J?</a></li>
     32     
     33     <li><a href="#when">When should SLF4J be used?</a></li>
     34     
     35     <li><a href="#yet_another_facade"> Is SLF4J yet another loggingfacade?</a></li>
     36     
     37     <li><a href="#why_new_project"> If SLF4J fixes JCL, then why
     38     wasn't the fix made in JCL instead of creating a new project?
     39     </a>
     40     </li>
     41     
     42     <li><a href="#need_to_recompile"> When using SLF4J, do I have to
     43     recompile my application to switch to a different logging
     44     system?  
     45     </a>
     46     </li>
     47     
     48     <li><a href="#requirements">What are SLF4J's requirements?</a></li>
     49     
     50     <li><a href="#compatibility">Are SLF4J versions backward
     51     compatible?</a></li>
     52 
     53     <li><a href="#IllegalAccessError">I am getting
     54     <code>IllegalAccessError</code> exceptions when using SLF4J. Why
     55     is that?</a></li>
     56 
     57 
     58     <li>
     59       <a href="#license">Why is SLF4J licensed under X11 type
     60       license instead of the Apache Software License?  
     61       </a>
     62     </li>
     63     
     64     <li>
     65       <a href="#where_is_binding">Where can I get a particular
     66       SLF4J binding?
     67       </a>
     68     </li>
     69     
     70     <li>
     71       <a href="#configure_logging">Should my library attempt to
     72       configure logging?
     73       </a>
     74     </li>
     75     
     76     <li>
     77       <a href="#optional_dependency">In order to reduce the number of
     78       dependencies of our software we would like to make SLF4J an
     79       optional dependency. Is that a good idea?
     80       </a>
     81     </li>
     82 
     83     <li>
     84       <a href="#maven2">What about Maven transitive
     85       dependencies?
     86       </a>
     87     </li>
     88     
     89     <li>
     90       <a href="#excludingJCL">How do I exclude commons-logging as a
     91       Maven dependency?
     92       </a>
     93     </li>
     94   </ol>
     95   
     96   
     97   <b>About the SLF4J API</b>
     98   
     99   <ol type="1">
    100     
    101     <li>
    102       <a href="#string_or_object"> Why don't the printing methods
    103       in the Logger interface accept message of type Object, but only
    104       messages of type String?  
    105       </a>
    106     </li>
    107     
    108     <li>
    109       <a href="#exception_message">
    110         Can I log an exception without an accompanying message?
    111       </a>
    112     </li>
    113     
    114     
    115     <li>
    116       <a href="#logging_performance"> What is the fastest way of
    117       (not) logging?
    118       </a>
    119     </li>
    120     
    121     <li>
    122       <a href="#string_contents"> How can I log the string contents
    123       of a single (possibly complex) object?
    124       </a>
    125     </li>
    126     
    127     
    128     <li><a href="#fatal"> Why doesn't the
    129     <code>org.slf4j.Logger</code> interface have methods for the
    130     FATAL level?  </a></li>
    131     
    132     <li><a href="#trace">Why was the TRACE level introduced only in
    133     SLF4J version 1.4.0?  </a></li>
    134     
    135     <li><a href="#i18n">Does the SLF4J logging API support I18N
    136     (internationalization)? </a></li>
    137 
    138 
    139     <li><a href="#noLoggerFactory">Is it possible to retrieve loggers
    140     without going through the static methods in
    141     <code>LoggerFactory</code>?  </a></li>
    142 
    143     <li><a href="#paramException">In the presence of an
    144     exception/throwable, is it possible to parameterize a logging
    145     statement?</a></li>
    146     
    147   </ol>
    148   
    149   
    150   
    151   <b>Implementing the SLF4J API</b>
    152   
    153   <ol type="1">
    154     
    155     <li><a href="#slf4j_compatible">How do I make my logging
    156     framework SLF4J compatible?  </a></li>
    157     
    158     <li><a href="#marker_interface">How can my logging system add
    159     support for the <code>Marker</code> interface?  </a></li>
    160     
    161     <li><a href="#version_checks">How does SLF4J's version check
    162     mechanism work?  </a></li>
    163     
    164     
    165   </ol>
    166   
    167   
    168   <b>General questions about logging</b>
    169   
    170   
    171   <ol type="1">
    172     
    173     <li><a href="#declared_static"> Should Logger members of a class
    174     be declared as static?  </a></li>
    175     
    176     
    177     <li><a href="#declaration_pattern">Is there a recommended idiom
    178     for declaring a loggers in a class?</a></li>
    179     
    180   </ol>
    181   
    182   <h2>Generalities</h2>
    183   
    184   <dl>
    185     <dt class="doAnchor" name="what_is">What is SLF4J?</dt>
    186     <dd>
    187       <p>SLF4J is a simple facade for logging systems allowing the
    188       end-user to plug-in the desired logging system at deployment
    189       time.
    190       </p>      
    191     </dd>
    192     
    193     <dt class="doAnchor" name="when">When should SLF4J be used?</dt>
    194     
    195     <dd>
    196       <p>In short, libraries and other embedded components should
    197       consider SLF4J for their logging needs because libraries cannot
    198       afford to impose their choice of logging framework on the
    199       end-user. On the other hand, it does not necessarily make sense
    200       for stand-alone applications to use SLF4J. Stand-alone
    201       applications can invoke the logging framework of their choice
    202       directly. In the case of logback, the question is moot because
    203       logback exposes its logger API via SLF4J.
    204       </p>
    205       
    206       <p>SLF4J is only a facade, meaning that it does not provide a
    207       complete logging solution. Operations such as configuring
    208       appenders or setting logging levels cannot be performed with
    209       SLF4J. Thus, at some point in time, any non-trivial
    210       application will need to directly invoke the underlying
    211       logging system. In other words, complete independence from the
    212       API underlying logging system is not possible for a
    213       stand-alone application. Nevertheless, SLF4J reduces the
    214       impact of this dependence to near-painless levels.
    215       </p>
    216       
    217       <p>Suppose that your CRM application uses log4j for its
    218       logging. However, one of your important clients request that
    219       logging be performed through JDK 1.4 logging. If your
    220       application is riddled with thousands of direct log4j calls,
    221       migration to JDK 1.4 would be a relatively lengthy and
    222       error-prone process. Even worse, you would potentially need to
    223       maintain two versions of your CRM software. Had you been
    224       invoking SLF4J API instead of log4j, the migration could be
    225       completed in a matter of minutes by replacing one jar file with
    226       another.
    227       </p> 
    228       
    229       <p>SLF4J lets component developers to defer the choice of the
    230       logging system to the end-user but eventually a choice needs
    231       to be made.
    232       </p>
    233       
    234       
    235       
    236     </dd>
    237     
    238     <dt class="doAnchor" name="yet_another_facade">Is SLF4J yet
    239     another logging facade?</dt>
    240     
    241     <dd>
    242       <p>SLF4J is conceptually very similar to JCL. As such, it can
    243       be thought of as yet another logging facade. However, SLF4J is
    244       much simpler in design and arguably more robust. In a
    245       nutshell, SLF4J avoid the class loader issues that plague JCL.
    246       </p>
    247       
    248       
    249       
    250     </dd>
    251     <dt class="doAnchor" name="why_new_project">If SLF4J fixes JCL,
    252     then why wasn't the fix made in JCL instead of creating a new
    253     project?
    254     </dt>
    255     
    256     <dd>
    257       <p>This is a very good question. First, SLF4J static binding
    258       approach is very simple, perhaps even laughably so. It was
    259       not easy to convince developers of the validity of that
    260       approach. It is only after SLF4J was released and started to
    261       become accepted did it gain respectability in the relevant
    262       community. 
    263       </p>
    264       
    265       <p>Second, SLF4J offers two enhancements which tend to be
    266       underestimated. Parameterized log messages solve an important
    267       problem associated with logging performance, in a pragmatic
    268       way. Marker objects, which are supported by the
    269       <code>org.slf4j.Logger</code> interface, pave the way for
    270       adoption of advanced logging systems and still leave the door
    271       open to switching back to more traditional logging systems if
    272       need be.
    273       </p>
    274       
    275       
    276     </dd>
    277     
    278     <dt class="doAnchor" name="need_to_recompile">When using SLF4J, do
    279     I have to recompile my application to switch to a different
    280     logging system?
    281     </dt>
    282     
    283     <dd>
    284       <p>No, you do not need to recompile your application. You can
    285       switch to a different logging system by removing the previous
    286       SLF4J binding and replacing it with the binding of your choice.
    287       </p>
    288       
    289       <p>For example, if you were using the NOP implementation and
    290       would like to switch to log4j version 1.2, simply replace
    291       <em>slf4j-nop.jar</em> with <em>slf4j-log4j12.jar</em> on
    292       your class path but do not forget to add log4j-1.2.x.jar as
    293       well. Want to switch to JDK 1.4 logging?  Just replace
    294       <em>slf4j-log4j12.jar</em> with <em>slf4j-jdk14.jar</em>.
    295       </p>
    296       
    297       
    298     </dd>
    299 
    300     <dt class="doAnchor" name="requirements">What are SLF4J's
    301     requirements?
    302     </dt>
    303     
    304     <dd>
    305       
    306       <p>As of version 1.7.0, SLF4J requires JDK 1.5 or later. Earlier
    307       SLF4J versions, namely SLF4J 1.4, 1.5. and 1.6, required JDK
    308       1.4.
    309       </p>
    310       
    311       <p>&nbsp;</p>
    312       
    313       <table class="bodyTable striped">
    314         <tr align="left">
    315           <th>Binding</th>
    316           <th>Requirements</th>
    317         </tr>
    318         
    319         <tr>
    320           <td>slf4j-nop</td>
    321           <td>JDK 1.5</td>
    322         </tr>
    323         <tr>
    324           <td>slf4j-simple</td>
    325           <td>JDK 1.5</td>
    326         </tr>
    327         
    328         <tr>
    329           <td>slf4j-log4j12</td>
    330           <td align="left">JDK 1.5, plus any other library
    331           dependencies required by the log4j appenders in use</td>
    332         </tr>
    333         <tr>
    334           <td>slf4j-jdk14</td>
    335           <td>JDK 1.5 or later</td>
    336         </tr>
    337         <tr>
    338           <td>logback-classic</td>
    339           <td>JDK 1.5 or later, plus any other library dependencies
    340           required by the logback appenders in use</td>
    341         </tr>
    342         
    343       </table>
    344       
    345       
    346     </dd>
    347 
    348     <!-- ==================================================== -->
    349     <!-- entry has order dependees -->
    350 
    351     <dt class="doAnchor" name="compatibility">Are SLF4J versions
    352     backward compatible?
    353     </dt>
    354 
    355     <dd>
    356       <p>From the clients perspective, the SLF4J API is backward
    357       compatible for all versions. This means than you can upgrade
    358       from SLF4J version 1.0 to any later version without
    359       problems. Code compiled with <em>slf4j-api-versionN.jar</em>
    360       will work with <em>slf4j-api-versionM.jar</em> for any versionN
    361       and any versionM. <b>To date, binary compatibility in slf4j-api
    362       has never been broken.</b></p>
    363 
    364       <p>However, while the SLF4J API is very stable from the client's
    365       perspective, SLF4J bindings, e.g. slf4j-simple.jar or
    366       slf4j-log4j12.jar, may require a specific version of slf4j-api.
    367       Mixing different versions of slf4j artifacts can be problematic
    368       and is strongly discouraged. For instance, if you are using
    369       slf4j-api-1.5.6.jar, then you should also use
    370       slf4j-simple-1.5.6.jar, using slf4j-simple-1.4.2.jar will not
    371       work.
    372       </p>        
    373 
    374       <p>At initialization time, if SLF4J suspects that there may be a
    375       version mismatch problem, it emits a warning about the said
    376       mismatch. 
    377       </p>
    378 
    379       
    380     </dd>
    381 
    382     <!-- ==================================================== -->
    383 
    384     <dt class="doAnchor" name="IllegalAccessError">I am getting
    385     <code>IllegalAccessError</code> exceptions when using SLF4J. Why
    386     is that?
    387     </dt>
    388 
    389     <dd>
    390 
    391       <p>Here are the exception details.</p>
    392 
    393       <pre class="source">Exception in thread "main" java.lang.IllegalAccessError: tried to access field
    394 org.slf4j.impl.StaticLoggerBinder.SINGLETON from class org.slf4j.LoggerFactory
    395    at org.slf4j.LoggerFactory.&lt;clinit>(LoggerFactory.java:60)</pre>
    396 
    397       <p>This error is caused by the static initializer of the
    398       <code>LoggerFactory</code> class attempting to directly access
    399       the SINGLETON field of
    400       <code>org.slf4j.impl.StaticLoggerBinder</code>. While this was
    401       allowed in SLF4J 1.5.5 and earlier, in 1.5.6 and later the
    402       SINGLETON field has been marked as private access.
    403       </p>
    404 
    405 
    406       <p>If you get the exception shown above, then you are using an
    407       older version of slf4j-api, e.g. 1.4.3, with a new version of a
    408       slf4j binding, e.g. 1.5.6. Typically, this occurs when your
    409       Maven <em>pom.ml</em> file incorporates hibernate 3.3.0 which
    410       declares a dependency on slf4j-api version 1.4.2. If your
    411       <em>pom.xml</em> declares a dependency on an slf4j binding, say
    412       slf4j-log4j12 version 1.5.6, then you will get illegal access
    413       errors.
    414       </p>
    415 
    416       <p>To see which version of slf4j-api is pulled in by Maven, use
    417       the maven dependency plugin as follows.</p>
    418 
    419       <p class="source">mvn dependency:tree</p>
    420 
    421       <p>If you are using Eclipse, please do not rely on the dependency
    422       tree shown by <a
    423       href="http://m2eclipse.codehaus.org/">m2eclipse</a>.</p>
    424 
    425       <p>In your <em>pom.xml</em> file, explicitly declaring a
    426       dependency on slf4j-api matching the version of the declared
    427       binding will make the problem go away.
    428       </p>
    429 
    430       <p>Please also read the FAQ entry on <a
    431       href="#compatibility">backward compatibility</a> for a more
    432       general explanation.</p>
    433 
    434       
    435     </dd>
    436     
    437 
    438     <!-- ==================================================== -->
    439 
    440     <dt class="doAnchor" name="license">Why is SLF4J licensed under
    441     X11 type license instead of the Apache Software License?
    442     </dt>
    443     
    444     <dd>
    445       <p>SLF4J is licensed under a permissive X11 type license
    446       instead of the <a
    447       href="http://www.apache.org/licenses/">ASL</a> or the <a
    448       href="http://www.gnu.org/copyleft/lesser.html">LGPL</a>
    449       because the X11 license is deemed by both the Apache Software
    450       Foundation as well as the Free Software Foundation as
    451       compatible with their respective licenses.
    452       </p>
    453       
    454       
    455     </dd>
    456 
    457     <!-- ==================================================== -->
    458     <dt class="doAnchor" name="where_is_binding">Where can I get a
    459     particular SLF4J binding?
    460     </dt>
    461     
    462     <dd>
    463       
    464       <p>SLF4J bindings for <a
    465       href="api/org/slf4j/impl/SimpleLogger.html">SimpleLogger</a>,
    466       <a href="api/org/slf4j/impl/NOPLogger.html">NOPLogger</a>, <a
    467       href="api/org/slf4j/impl/Log4jLoggerAdapter.html">Log4jLoggerAdapter</a>
    468       and <a
    469       href="api/org/slf4j/impl/JDK14LoggerAdapter.html">JDK14LoggerAdapter</a>
    470       are contained within the files <em>slf4j-nop.jar</em>,
    471       <em>slf4j-simple.jar</em>, <em>slf4j-log4j12.jar</em>, and
    472       <em>slf4j-jdk14.jar</em>. These files ship with the <a
    473       href="download.html">official SLF4J distribution</a>. Please
    474       note that all bindings depend on <em>slf4j-api.jar</em>.
    475       </p>
    476       
    477       <p>The binding for logback-classic ships with the <a
    478       href="http://logback.qos.ch/download.html">logback
    479       distribution</a>. However, as with all other bindings, the
    480       logback-classic binding requires <em>slf4j-api.jar</em>.
    481       </p>
    482       
    483       
    484     </dd>
    485     
    486     <dt class="doAnchor" name="configure_logging">Should my library
    487     attempt to configure logging?
    488     </dt>
    489     
    490     <dd>
    491       <p><b>Embedded components such as libraries not only do not need
    492       to configure the underlying logging framework, they really
    493       should not do so</b>. They should invoke SLF4J to log but should
    494       let the end-user configure the logging environment. When
    495       embedded components try to configure logging on their own, they
    496       often override the end-user's wishes. At the end of the day, it
    497       is the end-user who has to read the logs and process them. She
    498       should be the person to decide how she wants her logging
    499       configured.
    500       </p>      
    501       
    502       
    503     </dd>
    504     
    505     <!-- ======================================================= -->
    506 
    507     <dt class="doAnchor" name="optional_dependency">In order to reduce
    508     the number of dependencies of our software we would like to make
    509     SLF4J an optional dependency. Is that a good idea?      
    510     </dt>
    511 
    512     <dd>
    513       <p><a
    514       href="http://stackoverflow.com/questions/978670/is-it-worth-wrapping-a-logging-framework-in-an-additional-layer">This
    515       question pops up</a> whenever a software project reaches a point
    516       where it needs to devise a logging strategy.
    517       </p>
    518 
    519       <p>Let Wombat be a software library with very few
    520       dependencies. If SLF4J is chosen as Wombat's logging API, then a
    521       new dependency on <em>slf4j-api.jar</em> will be added to
    522       Wombat's list of dependencies. Given that writing a logging
    523       wrapper does not seem that hard, some developers will be tempted
    524       to wrap SLF4J and link with it only if it is already present on
    525       the classpath, making SLF4J an optional dependency of Wombat. In
    526       addition to solving the dependency problem, the wrapper will
    527       isolate Wombat from SLF4J's API ensuring that logging in Wombat
    528       is future-proof. 
    529       </p>
    530 
    531       <p>On the other hand, any SLF4J-wrapper by definition depends on
    532       SLF4J. It is bound to have the same general API. If in the
    533       future a new and significantly different logging API comes
    534       along, code that uses the wrapper will be equally difficult to
    535       migrate to the new API as code that used SLF4J directly. Thus,
    536       the wrapper is not likely to future-proof your code, but to make
    537       it more complex by adding an additional indirection on top of
    538       SLF4J, which is an indirection in itself. 
    539       </p>
    540 
    541       <p><span class="label">increased vulnerability</span> It is
    542       actually worse than that. Wrappers will need to depend on
    543       certain internal SLF4J interfaces which change from time to
    544       time, contrary to the client-facing API which never
    545       changes. Thus, wrappers are usually dependent on the major
    546       version they were compiled with. A wrapper compiled against
    547       SLF4J version 1.5.x will not work with SLF4J 1.6 whereas client
    548       code using <code>org.slf4j.Logger</code>,
    549       <code>LoggerFactory</code>, <code>MarkerFactory</code>,
    550       <code>org.slf4j.Marker</code>, and <code>MDC</code> will work
    551       fine with any SLF4J version from version 1.0 and onwards.
    552       </p>
    553 
    554       <p>It is reasonable to assume that in most projects Wombat will
    555       be one dependency among many.  If each library had its own
    556       logging wrapper, then each wrapper would presumably need to be
    557       configured separately. Thus, instead of having to deal with one
    558       logging framework, namely SLF4J, the user of Wombat would have
    559       to detail with Wombat's logging wrapper as well.  The problem
    560       will be compounded by each framework that comes up with its own
    561       wrapper in order to make SLF4J optional.  (Configuring or
    562       dealing with the intricacies of five different logging wrappers
    563       is not exactly exciting nor endearing.) 
    564       </p>
    565 
    566       <p>The <a
    567       href="http://velocity.apache.org/engine/devel/developer-guide.html#Configuring_Logging">logging
    568       strategy adopted by the Velocity project</a> is a good example
    569       of the "custom logging abstraction" anti-pattern. By adopting an
    570       independent logging abstraction strategy, Velocity developers
    571       have made life harder for themselves, but more importantly, they
    572       made life harder for their users.
    573       </p>
    574 
    575       <p>Some projects try to detect the presence of SLF4J on the
    576       class path and switch to it if present. While this approach
    577       seems transparent enough, it will result in erroneous location
    578       information. Underlying logging frameworks will print the
    579       location (class name and line number) of the wrapper instead of
    580       the real caller. Then there is the question of API coverage as
    581       SLF4J support MDC and markers in addition to parameterized
    582       logging.  While one can come up with a seemingly working
    583       SLF4J-wrapper within hours, many technical issues will emerge
    584       over time which Wombat developers will have to deal with. Note
    585       that SLF4J has evolved over several years and has 260 bug
    586       reports filed against it.</p>
    587 
    588       <p>For the above reasons, developers of frameworks should resist
    589       the temptation to write their own logging wrapper. Not only is
    590       it a waste of time of the developer, it will actually make life
    591       more difficult for the users of said frameworks and make logging
    592       code paradoxically more vulnerable to change.
    593       </p>
    594     </dd>
    595 
    596 
    597    <!-- ======================================================= -->
    598 
    599     <dt class="doAnchor" name="maven2">What about Maven transitive
    600     dependencies?
    601     </dt>
    602     
    603     <dd>
    604       <p>As an author of a library built with Maven, you might want to
    605       test your application using a binding, say slf4j-log4j12 or
    606       logback-classic, without forcing log4j or logback-classic as a
    607       dependency upon your users. This is rather easy to accomplish.
    608       </p>
    609 
    610       <p>Given that your library's code depends on the SLF4J API, you
    611       will need to declare slf4j-api as a compile-time (default scope)
    612       dependency.
    613       </p>
    614       <pre class="prettyprint source">&lt;dependency&gt;
    615   &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
    616   &lt;artifactId&gt;slf4j-api&lt;/artifactId&gt;
    617   &lt;version&gt;${project.version}&lt;/version&gt;
    618 &lt;/dependency&gt;</pre>
    619       
    620       <p>Limiting the transitivity of the SLF4J binding used in your
    621       tests can be accomplished by declaring the scope of the
    622       SLF4J-binding dependency as "test".  Here is an example:</p>
    623       
    624       <pre class="prettyprint source">&lt;dependency&gt;
    625   &lt;groupId&gt;org.slf4j&lt;/groupId&gt;
    626   &lt;artifactId&gt;slf4j-log4j12&lt;/artifactId&gt;
    627   &lt;version&gt;${project.version}&lt;/version&gt;
    628   <b>&lt;scope&gt;test&lt;/scope&gt;</b>
    629 &lt;/dependency&gt;</pre>
    630       
    631       <p>Thus, as far as your users are concerned you are exporting
    632       slf4j-api as a transitive dependency of your library, but not
    633       any SLF4J-binding or any underlying logging system.
    634       </p>
    635       
    636       <p>Note that as of SLF4J version 1.6, in the absence of an SLF4J
    637       binding, slf4j-api will default to a no-operation
    638       implementation.
    639       </p>
    640 
    641       
    642       
    643     </dd>
    644     
    645     <!-- ====================================================== -->
    646     <dt class="doAnchor" name="excludingJCL">How do I exclude
    647     commons-logging as a Maven dependency?
    648     </dt>
    649     
    650     <dd>
    651       <p><b>alternative 1) explicit exclusion</b></p>
    652 
    653       <p>Many software projects using Maven declare commons-logging as
    654       a dependency. Therefore, if you wish to migrate to SLF4J or use
    655       jcl-over-slf4j, you would need to exclude commons-logging in all
    656       of your project's dependencies which transitively depend on
    657       commons-logging. <a
    658       href="http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html">Dependency
    659       exclusion</a> is described in the Maven documentation. Excluding
    660       commons-logging explicitly for multiple dependencies distributed
    661       on several <em>pom.xml</em> files can be a cumbersome and a
    662       relatively error prone process.
    663       </p>
    664 
    665       <p><b>alternative 2) provided scope</b></p>
    666 
    667       <p>Commons-logging can be rather simply and conveniently
    668       excluded as a dependency by declaring it in the
    669       <em>provided</em> scope within the pom.xml file of your
    670       project. The actual commons-logging classes would be provided by
    671       jcl-over-slf4j. This translates into the following pom file
    672       snippet:</p>
    673       
    674          <pre class="prettyprint source">&lt;dependency>
    675   &lt;groupId>commons-logging&lt;/groupId>
    676   &lt;artifactId>commons-logging&lt;/artifactId>
    677   &lt;version>1.1.1&lt;/version>
    678   &lt;scope>provided&lt;/scope>
    679 &lt;/dependency>
    680 
    681 &lt;dependency>
    682   &lt;groupId>org.slf4j&lt;/groupId>
    683   &lt;artifactId>jcl-over-slf4j&lt;/artifactId>
    684   &lt;version>${project.version}&lt;/version>
    685 &lt;/dependency></pre>
    686 
    687       <p>The first dependency declaration essentially states that
    688       commons-logging will be "somehow" provided by your
    689       environment. The second declaration includes jcl-over-slf4j into
    690       your project. As jcl-over-slf4j is a perfect binary-compatible
    691       replacement for commons-logging, the first assertion becomes
    692       true.
    693       </p>
    694 
    695       <p>Unfortunately, while declaring commons-logging in the
    696       provided scope gets the job done, your IDE, e.g. Eclipse, will
    697       still place <em>commons-logging.jar</em> on your project's class
    698       path as seen by your IDE. You would need to make sure that
    699       <em>jcl-over-slf4j.jar</em> is visible before
    700       <em>commons-logging.jar</em> by your IDE.
    701       </p>
    702 
    703       <p><b>alternative 3) empty artifacts</b></p>
    704       
    705       <p>An alternative approach is to depend on an <b>empty</b>
    706       <em>commons-logging.jar</em> artifact. This clever <a
    707       href="http://day-to-day-stuff.blogspot.com/2007/10/announcement-version-99-does-not-exist.html">approach
    708       first was imagined</a> and initially supported by Erik van
    709       Oosten.
    710       </p>
    711 
    712       <p>The empty artifact is available from a <a
    713       href="http://version99.qos.ch">http://version99.qos.ch</a> a
    714       high-availability Maven repository, replicated on several hosts
    715       located in different geographical regions.</p>
    716 
    717       <p>The following declaration adds the version99 repository to
    718       the set of remote repositories searched by Maven. This
    719       repository contains empty artifacts for commons-logging and
    720       log4j. By the way, if you use the version99 repository, please
    721       drop us a line at &lt;version99 AT qos.ch&gt;.
    722       </p>
    723 
    724       <pre class="prettyprint source">&lt;repositories>
    725   &lt;repository>
    726     &lt;id>version99&lt;/id>
    727     &lt;!-- highly available repository serving empty artifacts --&gt;
    728     &lt;url>http://version99.qos.ch/</url>
    729   &lt;/repository>
    730 &lt;/repositories></pre>
    731       
    732     <p>Declaring version 99-empty of commons-logging in the
    733     <code>&lt;dependencyManagement></code> section of your project
    734     will direct all transitive dependencies for commons-logging to
    735     import version 99-empty, thus nicely addressing the
    736     commons-logging exclusion problem. The classes for commons-logging
    737     will be provided by jcl-over-slf4j. The following lines declare
    738     commons-logging version 99-empty (in the dependency management
    739     section) and declare jcl-over-slf4j as a dependency.
    740     </p>
    741     
    742 <pre class="prettyprint source">&lt;dependencyManagement>
    743   &lt;dependencies>
    744     &lt;dependency>
    745       &lt;groupId>commons-logging&lt;/groupId>
    746       &lt;artifactId>commons-logging&lt;/artifactId>
    747       &lt;version><b>99-empty</b>&lt;/version>
    748     &lt;/dependency>
    749     ... other declarations...
    750   &lt;/dependencies>
    751 &lt;/dependencyManagement>
    752 
    753 &lt;!-- Do not forget to declare a dependency on jcl-over-slf4j in the        --&gt;
    754 &lt;!-- dependencies section. Note that the dependency on commons-logging     --&gt;
    755 &lt;!-- will be imported transitively. You don't have to declare it yourself. --&gt;
    756 &lt;dependencies>
    757   &lt;dependency>
    758     &lt;groupId>org.slf4j&lt;/groupId>
    759     &lt;artifactId>jcl-over-slf4j&lt;/artifactId>
    760     &lt;version>${project.version}&lt;/version>
    761   &lt;/dependency>
    762   ... other dependency declarations
    763 &lt;/dependencies>
    764 </pre>
    765 
    766 
    767     </dd>
    768     
    769     
    770     
    771   </dl>
    772   
    773   
    774   <h2>About the SLF4J API</h2>
    775   
    776   <dl>
    777     
    778     <dt class="doAnchor" name="string_or_object">Why don't the
    779     printing methods in the Logger interface accept message of type
    780     Object, but only messages of type String?
    781     </dt>
    782     
    783     <dd>
    784       
    785       <p>In SLF4J 1.0beta4, the printing methods such as debug(),
    786       info(), warn(), error() in the <a
    787       href="api/org/slf4j/Logger.html">Logger interface</a> were
    788       modified so as to accept only messages of type String
    789       instead of Object.
    790       </p>
    791       
    792       <p>Thus, the set of printing methods for the DEBUG level
    793       became:</p>
    794       
    795       <pre class="prettyprint source">debug(String msg); 
    796 debug(String format, Object arg); 
    797 debug(String format, Object arg1, Object arg2);           
    798 debug(String msg, Throwable t);</pre>
    799       
    800       <p>Previously, the first argument in the above methods was of
    801       type <code>Object</code>.</p>
    802       
    803       <p>This change enforces the notion that logging systems are
    804       about decorating and handling messages of type String, and not
    805       any arbitrary type (Object).
    806       </p>
    807       
    808       <p>Just as importantly, the new set of method signatures offer
    809       a clearer differentiation between the overloaded methods
    810       whereas previously the choice of the invoked method due to
    811       Java overloading rules were not always easy to follow.</p>
    812       
    813       <p>It was also easy to make mistakes. For example, previously
    814       it was legal to write:</p>
    815       
    816       <pre class="prettyprint source">logger.debug(new Exception("some error"));</pre>
    817       
    818       <p>Unfortunately, the above call did not print the stack trace
    819       of the exception. Thus, a potentially crucial piece of
    820       information could be lost. When the first parameter is
    821       restricted to be of type String, then only the method
    822       </p>
    823       
    824       <pre class="prettyprint source">debug(String msg, Throwable t);</pre>
    825       
    826       <p>can be used to log exceptions. Note that this method
    827       ensures that every logged exception is accompanied with a
    828       descriptive message.</p>
    829       
    830       
    831     </dd>
    832     
    833     <!-- ====================================================== -->
    834 
    835     <dt class="doAnchor" name="exception_message">Can I log an
    836     exception without an accompanying message?
    837     </dt>
    838 
    839     <dd>
    840       <p>In short, no.</p>
    841       
    842       <p>If <code>e</code> is an <code>Exception</code>, and you
    843       would like to log an exception at the ERROR level, you must
    844       add an accompanying message. For example,</p>
    845       
    846       <pre class="prettyprint source">logger.error("some accompanying message", e);</pre>
    847       
    848       <p>You might legitimately argue that not all exceptions have a
    849       meaningful message to accompany them. Moreover, a good exception
    850       should already contain a self explanatory description. The
    851       accompanying message may therefore be considered redundant.
    852       </p>
    853       
    854       
    855       <p>While these are valid arguments, there are three opposing
    856       arguments also worth considering. First, on many, albeit not
    857       all occasions, the accompanying message can convey useful
    858       information nicely complementing the description contained
    859       in the exception. Frequently, at the point where the
    860       exception is logged, the developer has access to more
    861       contextual information than at the point where the exception
    862       is thrown. Second, it is not difficult to imagine more or
    863       less generic messages, e.g. "Exception caught", "Exception
    864       follows", that can be used as the first argument for
    865       <code>error(String msg, Throwable t)</code> invocations.
    866       Third, most log output formats display the message on a
    867       line, followed by the exception on a separate line. Thus,
    868       the message line would look inconsistent without a message.
    869       </p>
    870       
    871       <p>In short, if the user were allowed to log an exception
    872       without an accompanying message, it would be the job of the
    873       logging system to invent a message. This is actually what
    874       the <a href="http://tinyurl.com/cr9kg">throwing(String
    875       sourceClass, String sourceMethod, Throwable thrown)</a>
    876       method in java.util.logging package does. (It decides on its
    877       own that accompanying message is the string "THROW".)
    878       </p>
    879       
    880       <p>It may initially appear strange to require an accompanying
    881       message to log an exception. Nevertheless, this is common
    882       practice in <em>all</em> log4j derived systems such as
    883       java.util.logging, logkit, etc. and of course log4j itself. It
    884       seems that the current consensus considers requiring an
    885       accompanying message as a good a thing (TM).
    886       </p>
    887       
    888     </dd>     
    889     
    890     <!-- ====================================================== -->
    891     
    892     
    893     <dt class="doAnchor" name="logging_performance">What is the
    894     fastest way of (not) logging?
    895     </dt>
    896 
    897     <dd>    
    898       <p>SLF4J supports an advanced feature called parameterized
    899       logging which can significantly boost logging performance for
    900       <em>disabled</em> logging statement.</p>
    901       
    902       <p> For some Logger <code>logger</code>, writing,</p>
    903       <pre class="prettyprint source">logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));</pre>
    904       
    905       <p>incurs the cost of constructing the message parameter, that
    906       is converting both integer <code>i</code> and
    907       <code>entry[i]</code> to a String, and concatenating
    908       intermediate strings. This, regardless of whether the message
    909       will be logged or not.
    910       </p>        
    911       
    912       <p>One possible way to avoid the cost of parameter
    913       construction is by surrounding the log statement with a
    914       test. Here is an example.</p>
    915       
    916       <pre class="prettyprint source">if(logger.isDebugEnabled()) {
    917   logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
    918 }</pre>
    919       
    920       
    921       <p>This way you will not incur the cost of parameter
    922       construction if debugging is disabled for
    923       <code>logger</code>. On the other hand, if the logger is
    924       enabled for the DEBUG level, you will incur the cost of
    925       evaluating whether the logger is enabled or not, twice: once in
    926       <code>debugEnabled</code> and once in <code>debug</code>.  This
    927       is an insignificant overhead because evaluating a logger takes
    928       less than 1% of the time it takes to actually log a statement.
    929       </p>
    930       
    931       <p><b>Better yet, use parameterized messages</b></p>
    932       
    933       <p>There exists a very convenient alternative based on message
    934       formats. Assuming <code>entry</code> is an object, you can write:
    935       </p>
    936       
    937       
    938       <pre class="prettyprint source">Object entry = new SomeObject();
    939 logger.debug("The entry is {}.", entry);</pre>
    940       
    941       <p>After evaluating whether to log or not, and only if the
    942       decision is affirmative, will the logger implementation format
    943       the message and replace the '{}' pair with the string value of
    944       <code>entry</code>. In other words, this form does not incur
    945       the cost of parameter construction in case the log statement is
    946       disabled.
    947       </p>
    948       
    949       <p>The following two lines will yield the exact same
    950       output. However, the second form will outperform the first
    951       form by a factor of at least 30, in case of a
    952       <em>disabled</em> logging statement.
    953       </p>
    954       
    955       <pre class="prettyprint source">logger.debug("The new entry is "+entry+".");
    956 logger.debug("The new entry is {}.", entry);</pre>
    957       
    958       
    959       <p>A <a
    960       href="apidocs/org/slf4j/Logger.html#debug(java.lang.String,%20java.lang.Object%2C%20java.lang.Object)">two
    961       argument</a> variant is also available. For example, you can
    962       write:</p>
    963       
    964       
    965       <pre class="prettyprint source">logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);</pre>
    966       
    967       <p>If three or more arguments need to be passed, you can make
    968       use of the <a
    969       href="apidocs/org/slf4j/Logger.html#debug(java.lang.String%2C%20java.lang.Object...)"><code>Object...</code>
    970       variant</a> of the printing methods. For example, you can
    971       write:</p>
    972       
    973       <pre class="prettyprint source">logger.debug("Value {} was inserted between {} and {}.", newVal, below, above);</pre>
    974       
    975       <p>This form incurs the hidden cost of construction of an
    976       Object[] (object array) which is usually very small. The one and
    977       two argument variants do not incur this hidden cost and exist
    978       solely for this reason (efficiency). The slf4j-api would be
    979       smaller/cleaner with only the Object... variant.</p>
    980      
    981       
    982       <p>Array type arguments, including multi-dimensional arrays,
    983       are also supported.</p>
    984       
    985       <p>SLF4J uses its own message formatting implementation which
    986       differs from that of the Java platform. This is justified by
    987       the fact that SLF4J's implementation performs about 10 times
    988       faster but at the cost of being non-standard and less
    989       flexible.
    990       </p>
    991       
    992       <p><b>Escaping the "{}" pair</b></p>
    993       
    994       <p>The "{}" pair is called the <em>formatting anchor</em>. It
    995       serves to designate the location where arguments need to be
    996       substituted within the message pattern.
    997       </p>
    998       
    999       <p>SLF4J only cares about the <em>formatting anchor</em>, that
   1000       is the '{' character immediately followed by '}'. Thus, in
   1001       case your message contains the '{' or the '}' character, you
   1002       do not have to do anything special unless the '}' character
   1003       immediately follows '}'. For example,
   1004       </p>
   1005       
   1006       <pre class="prettyprint source">logger.debug("Set {1,2} differs from {}", "3");</pre>
   1007       
   1008       <p>which will print as "Set {1,2} differs from 3". </p>
   1009       
   1010       <p>You could have even written,</p>
   1011       <pre class="prettyprint source">logger.debug("Set {1,2} differs from {{}}", "3");</pre>
   1012       <p>which would have printed as "Set {1,2} differs from {3}". </p>
   1013       
   1014       <p>In the extremely rare case where the the "{}" pair occurs
   1015       naturally within your text and you wish to disable the special
   1016       meaning of the formatting anchor, then you need to escape the
   1017       '{' character with '\', that is the backslash character. Only
   1018       the '{' character should be escaped. There is no need to
   1019       escape the '}' character. For example,
   1020       </p>
   1021       
   1022       <pre class="prettyprint source">logger.debug("Set \\{} differs from {}", "3");</pre>
   1023       
   1024       <p>will print as "Set {} differs from 3". Note that within
   1025       Java code, the backslash character needs to be written as
   1026       '\\'.</p>
   1027       
   1028       <p>In the rare case where the "\{}" occurs naturally in the
   1029       message, you can double escape the formatting anchor so that
   1030       it retains its original meaning. For example,</p>
   1031       
   1032       
   1033       <pre class="prettyprint source">logger.debug("File name is C:\\\\{}.", "file.zip");</pre>
   1034       <p>will print as "File name is C:\file.zip".</p>
   1035       
   1036     </dd>
   1037     
   1038     <!-- ================================================= -->
   1039     
   1040     <dt class="doAnchor" name="string_contents">How can I log the
   1041     string contents of a single (possibly complex) object?</dt>
   1042     
   1043     <dd>
   1044       <p> In relatively rare cases where the message to be logged
   1045       is the string form of an object, then the parameterized
   1046       printing method of the appropriate level can be
   1047       used. Assuming <code>complexObject</code> is an object of
   1048       certain complexity, for a log statement of level DEBUG, you
   1049       can write:
   1050       </p>
   1051       
   1052       <pre class="prettyprint source">logger.debug("{}", complexObject);</pre>
   1053       
   1054       
   1055       <p>The logging system will invoke
   1056       <code>complexObject.toString()</code> method only after it
   1057       has ascertained that the log statement was
   1058       enabled. Otherwise, the cost of
   1059       <code>complexObject.toString()</code> conversion will be
   1060       advantageously avoided.
   1061       </p>
   1062       
   1063       
   1064       
   1065     </dd>
   1066     
   1067     <!-- ================================================= -->
   1068     
   1069     
   1070     <dt class="doAnchor" name="fatal">Why doesn't the
   1071     <code>org.slf4j.Logger</code> interface have methods for the FATAL
   1072     level?
   1073     </dt>
   1074     
   1075     <dd>      
   1076       <p>The <a href="apidocs/org/slf4j/Marker.html">Marker</a>
   1077       interface, part of the <code>org.slf4j</code> package, renders
   1078       the FATAL level largely redundant. If a given error requires
   1079       attention beyond that allocated for ordinary errors, simply mark
   1080       the logging statement with a specially designated marker which
   1081       can be named "FATAL" or any other name to your liking.
   1082       </p>
   1083 
   1084       <p>Here is an example,</p>
   1085     
   1086 <pre class="prettyprint">import org.slf4j.Logger;
   1087 import org.slf4j.LoggerFactory;
   1088 import org.slf4j.Marker;
   1089 import org.slf4j.MarkerFactory;
   1090 
   1091 class Bar {
   1092   void foo() {
   1093     <b>Marker fatal = MarkerFactory.getMarker("FATAL");</b>
   1094     Logger logger = LoggerFactory.getLogger("aLogger");
   1095 
   1096     try {
   1097       ... obtain a JDBC connection
   1098     } catch (JDBException e) {
   1099       logger.error(<b>fatal</b>, "Failed to obtain JDBC connection", e);
   1100     }
   1101   }
   1102 }</pre>
   1103 
   1104 
   1105       <p>While markers are part of the SLF4J API, only logback
   1106       supports markers off the shelf. For example, if you add the
   1107       <code>%marker</code> conversion word to its pattern, logback's
   1108       <code>PatternLayout</code> will add marker data to its
   1109       output. Marker data can be used to <a
   1110       href="http://logback.qos.ch/manual/filters.html">filter
   1111       messages</a> or even <a
   1112       href="http://logback.qos.ch/manual/appenders.html#OnMarkerEvaluator">trigger</a>
   1113       an outgoing email <a
   1114       href="http://logback.qos.ch/recipes/emailPerTransaction.html">at
   1115       the end of an individual transaction</a>.
   1116       </p>
   1117 
   1118       <p>In combination with logging frameworks such as log4j and
   1119       java.util.logging which do not support markers, marker data will
   1120       be silently ignored.</p>
   1121 
   1122       <p>Markers add a new dimension with infinite possible values for
   1123       processing log statements compared to five values, namely ERROR,
   1124       WARN, INFO, DEBUG and TRACE, allowed by levels. At present time,
   1125       only logback supports marker data. However, nothing prevents
   1126       other logging frameworks from making use of marker data.
   1127       </p>
   1128       
   1129     </dd>
   1130     
   1131     <!-- ======================================================= -->
   1132     <dt class="doAnchor" name="trace">Why was the TRACE level
   1133     introduced only in SLF4J version 1.4.0?</dt>
   1134     
   1135     <dd>
   1136       
   1137       <p>The addition of the TRACE level has been frequently and
   1138       hotly debated request. By studying various projects, we
   1139       observed that the TRACE level was used to disable logging
   1140       output from certain classes <em>without</em> needing to
   1141       configure logging for those classes. Indeed, the TRACE level
   1142       is by default disabled in log4j and logback as well most other
   1143       logging systems. The same result can be achieved by adding the
   1144       appropriate directives in configuration files.
   1145       </p>
   1146       
   1147       <p>Thus, in many of cases the TRACE level carried the same
   1148       semantic meaning as DEBUG. In such cases, the TRACE level
   1149       merely saves a few configuration directives. In other, more
   1150       interesting occasions, where TRACE carries a different meaning
   1151       than DEBUG, <a href="api/org/slf4j/Marker.html">Marker</a>
   1152       objects can be put to use to convey the desired
   1153       meaning. However, if you can't be bothered with markers and
   1154       wish to use a logging level lower than DEBUG, the TRACE level
   1155       can get the job done.
   1156       </p>
   1157       
   1158       <p>Note that while the cost of evaluating a disabled log
   1159       request is in the order of a few <code>nanoseconds</code>, the
   1160       use of the TRACE level (or any other level for that matter) is
   1161       discouraged in tight loops where the log request might be
   1162       evaluated millions of times. If the log request is enabled,
   1163       then it will overwhelm the target destination with massive
   1164       output. If the request is disabled, it will waste resources.
   1165       </p>
   1166       
   1167       <p>In short, although we still discourage the use of the TRACE
   1168       level because alternatives exist or because in many cases log
   1169       requests of level TRACE are wasteful, given that people kept
   1170       asking for it, we decided to bow to popular demand.
   1171       </p>
   1172       
   1173       
   1174     </dd>
   1175 
   1176     <!-- ================================================= -->
   1177     <dt class="doAnchor" name="i18n">Does the SLF4J logging API
   1178     support I18N (internationalization)?
   1179     </dt>
   1180     
   1181     <dd>
   1182       <p>Yes, as of version 1.5.9, SLF4J ships with a package called
   1183       <code>org.slf4j.cal10n</code> which adds <a
   1184       href="localization.html">localized/internationalized logging</a>
   1185       support as a thin layer built upon the <a
   1186       href="http://cal10n.qos.ch">CAL10N API</a>.</p>
   1187 
   1188       
   1189     </dd>          
   1190 
   1191     <!-- ================================================= -->
   1192 
   1193     <dt class="doAnchor" name="noLoggerFactory">Is it possible to
   1194     retrieve loggers without going through the static methods in
   1195     <code>LoggerFactory</code>?
   1196     </dt>
   1197 
   1198     <dd>
   1199 
   1200       <p>Yes. <code>LoggerFactory</code> is essentially a wrapper
   1201       around an <a
   1202       href="xref/org/slf4j/ILoggerFactory.html"><code>ILoggerFactory</code></a>
   1203       instance. The <code>ILoggerFactory</code> instance in use is
   1204       determined according to the static binding conventions of the
   1205       SLF4J framework. See the <a
   1206       href="xref/org/slf4j/LoggerFactory.html#217">getSingleton()</a>
   1207       method in <code>LoggerFactory</code> for details.
   1208       </p>
   1209 
   1210       <p>However, nothing prevents you from using your own
   1211       <code>ILoggerFactory</code> instance. Note that you can also
   1212       obtain a reference to the <code>ILoggerFactory</code> that the
   1213       <code>LoggerFactory</code> class is using by invoking the <a
   1214       href="apidocs/org/slf4j/LoggerFactory.html#getILoggerFactory()">
   1215       <code>LoggerFactory.getILoggerFactory()</code></a> method.
   1216       </p>
   1217 
   1218       <p>Thus, if SLF4J binding conventions do not fit your needs, or
   1219       if you need additional flexibility, then do consider using the
   1220       <code>ILoggerFactory</code> interface as an alternative to
   1221       inventing your own logging API.</p>
   1222     </dd>
   1223     
   1224     <!-- ================================================= -->
   1225 
   1226     <dt class="doAnchor" name="paramException">In the presence of an
   1227     exception/throwable, is it possible to parameterize a logging
   1228     statement?</dt>
   1229 
   1230 
   1231     <dd>
   1232       <p>Yes, as of SLF4J 1.6.0, but not in previous versions. The
   1233       SLF4J API supports parametrization in the presence of an
   1234       exception, assuming the exception is the last parameter. Thus,
   1235     </p>
   1236     <pre class="prettyprint">String s = "Hello world";
   1237 try {
   1238   Integer i = Integer.valueOf(s);
   1239 } catch (NumberFormatException e) {
   1240   logger.error("Failed to format {}", s, e);
   1241 }</pre>
   1242 
   1243      <p>will print the <code>NumberFormatException</code> with its
   1244      stack trace as expected. The java compiler will invoke the <a
   1245      href="http://www.slf4j.org/apidocs/org/slf4j/Logger.html#error%28java.lang.String,%20java.lang.Object,%20java.lang.Object%29">error
   1246      method taking a String and two Object arguments</a>. SLF4J, in
   1247      accordance with the programmer's most probable intention, will
   1248      interpret <code>NumberFormatException</code> instance as a
   1249      throwable instead of an unused <code>Object</code> parameter. In
   1250      SLF4J versions prior to 1.6.0, the
   1251      <code>NumberFormatException</code> instance was simply ignored.
   1252      </p>
   1253 
   1254      <p>If the exception is not the last argument, it will be treated
   1255      as a plain object and its stack trace will NOT be printed.
   1256      However, such situations should not occur in practice.
   1257      </p>
   1258     
   1259     </dd>
   1260   </dl>
   1261 
   1262 
   1263   
   1264   <h2>Implementing the SLF4J API</h2>
   1265   
   1266   <dl>
   1267 
   1268     <!-- ============================================================= -->
   1269 
   1270     <dt class="doAnchor" name="slf4j_compatible">How do I make my
   1271     logging framework SLF4J compatible?
   1272     </dt>
   1273     
   1274     
   1275     <dd>
   1276       
   1277       <p>Adding supporting for the SLF4J is surprisingly
   1278       easy. Essentially, you coping an existing binding and tailoring
   1279       it a little (as explained below) does the trick.
   1280       </p>
   1281       
   1282       <p>Assuming your logging system has notion of a
   1283       logger, called say <code>MyLogger</code>, you need to provide
   1284       an adapter for <code>MyLogger</code> to
   1285       <code>org.slf4j.Logger</code> interface. Refer to slf4j-jcl,
   1286       slf4j-jdk14, and slf4j-log4j12 modules for examples of
   1287       adapters.
   1288       </p>
   1289       
   1290       <p>Once you have written an appropriate adapter, say
   1291       <code>MyLoggerAdapter</code>, you need to provide a factory
   1292       class implementing the <code>org.slf4j.ILoggerFactory</code>
   1293       interface. This factory should return instances
   1294       <code>MyLoggerAdapter</code>. Let <code>MyLoggerFactory</code>
   1295       be the name of your factory class.
   1296       </p>
   1297       
   1298       <p>Once you have the adapter, namely
   1299       <code>MyLoggerAdapter</code>, and a factory, namely
   1300       <code>MyLoggerFactory</code>, the last remaining step is to
   1301       modify the <code>StaticLoggerBinder</code> class so that it
   1302       returns an new instance of <code>MyLoggerFactory</code>. You
   1303       will also need to modify the
   1304       <code>loggerFactoryClassStr</code> variable.
   1305       </p>
   1306       
   1307       <p>For Marker or MDC support, you could use the one of the
   1308       existing NOP implementations.
   1309       </p>
   1310       
   1311       <p>In summary, to create an SLF4J binding for your logging
   1312       system, follow these steps:</p>
   1313       
   1314       <ol>
   1315         <li>start with a copy of an existing module,</li>
   1316         <li>create an adapter between your logging system and
   1317         <code>org.slf4j.Logger</code> interface
   1318         </li>
   1319         <li>create a factory for the adapter created in the previous step,</li>
   1320         <li>modify <code>StaticLoggerBinder</code> class to use the
   1321         factory you created in the previous step</li>
   1322       </ol>
   1323       
   1324       
   1325     </dd>
   1326 
   1327     <!-- ============================================================= -->
   1328 
   1329     <dt class="doAnchor" name="marker_interface">How can my logging
   1330     system add support for the <code>Marker</code> interface?
   1331     </dt>
   1332     <dd>
   1333       
   1334       <p>Markers constitute a revolutionary concept which is
   1335       supported by logback but not other existing logging
   1336       systems. Consequently, SLF4J conforming logging systems are
   1337       allowed to ignore marker data passed by the user.
   1338       </p>
   1339       
   1340       <p>However, even though marker data may be ignored, the user
   1341       must still be allowed to specify marker data. Otherwise, users
   1342       would not be able to switch between logging systems that
   1343       support markers and those that do not.  
   1344       </p>
   1345       
   1346       <p>The <code>MarkerIgnoringBase</code> class can serve as a
   1347       base for adapters or native implementations of logging
   1348       systems lacking marker support. In
   1349       <code>MarkerIgnoringBase</code>, methods taking marker data
   1350       simply invoke the corresponding method without the Marker
   1351       argument, discarding any Marker data passed as
   1352       argument. Your SLF4J adapters can extend
   1353       <code>MarkerIgnoringBase</code> to quickly implement the
   1354       methods in <code>org.slf4j.Logger</code> which take a
   1355       <code>Marker</code> as the first argument.
   1356       </p>
   1357       
   1358       
   1359     </dd>
   1360     
   1361     <!-- ============================================================= -->
   1362 
   1363     <dt class="doAnchor" name="version_checks">How does SLF4J's
   1364     version check mechanism work?
   1365     </dt>
   1366     
   1367     <dd>
   1368       <p>The version check performed by SLF4J API during its
   1369       initialization is an <em>elective</em> process. Conforming SLF4J
   1370       implementations may choose <em>not</em> to participate, in which
   1371       case, no version check will be performed.
   1372       </p>
   1373       
   1374       <p>However, if an SLF4J implementation decides to participate,
   1375       than it needs to declare a variable called
   1376       REQUESTED_API_VERSION within its copy of the
   1377       <code>StaticLoggerBinder</code> class. The value of this
   1378       variable should be equal to the version of the slf4j-api.jar
   1379       it is compiled with. If the implementation is upgraded to a
   1380       newer version of slf4j-api, than you also need to update the
   1381       value of REQUESTED_API_VERSION. 
   1382       </p>
   1383       
   1384       <p>For each version, SLF4J API maintains a list of compatible
   1385       versions. SLF4J will emit a version mismatch warning only if
   1386       the requested version is not found in the compatibility
   1387       list. So even if your SLF4J binding has a different release
   1388       schedule than SLF4J, assuming you update the SLF4J version you
   1389       use every 6 to 12 months, you can still participate in the
   1390       version check without incurring a mismatch warning. For
   1391       example, logback has a different release schedule but still
   1392       participates in version checks.</p>
   1393       
   1394       <p><b>As of SLF4J 1.5.5</b>, all bindings shipped within the
   1395       SLF4J distribution, e.g. slf4j-log4j12, slf4j-simple and
   1396       slf4j-jdk14, declare the REQUESTED_API_VERSION field with a
   1397       value equal to their SLF4J version. It follows that, for example
   1398       if slf4j-simple-1.5.8.jar is mixed with slf4j-api-1.6.0.jar,
   1399       given that 1.5.8 is not on the compatibility list of SLF4J
   1400       version 1.6.x, a version mismatch warning will be issued.
   1401       </p>
   1402 
   1403       <p>Note that SLF4J versions prior to 1.5.5 did not have a
   1404       version check mechanism.  Only slf4j-api-1.5.5.jar and later can
   1405       emit version mismatch warnings.
   1406       </p>
   1407 
   1408       
   1409     </dd>
   1410     
   1411   </dl>
   1412   
   1413   <h2>General questions about logging</h2>
   1414   
   1415   
   1416 
   1417   <dl>
   1418 
   1419     <!-- ============================================================= -->
   1420     <dt class="doAnchor" name="declared_static">Should Logger members
   1421     of a class be declared as static?
   1422     </dt>
   1423     <dd>
   1424       
   1425       <p>We <code>used</code> to recommend that loggers members be
   1426       declared as instance variables instead of static. After further
   1427       analysis, <b>we no longer recommend one approach over the
   1428       other.</b>
   1429       </p>
   1430       
   1431       <p>Here is a summary of the pros and cons of each approach.
   1432       </p>
   1433       
   1434       <table class="bodyTable">
   1435         <tr valign="top">
   1436           <th width="50%">Advantages for declaring loggers as static</th>       
   1437           <th width="50%">Disadvantages for declaring loggers as static</th>              
   1438         </tr>
   1439         <tr  valign="top" class="alt">
   1440           <td>
   1441             <ol>
   1442               <li>common and well-established idiom</li>
   1443               <li>less CPU overhead: loggers are retrieved and
   1444               assigned only once, at hosting class
   1445               initialization</li>
   1446               <li>less memory overhead: logger declaration will
   1447               consume one reference per class</li>            
   1448             </ol>
   1449           </td>
   1450           
   1451           <td> <!-- static con -->
   1452             <ol>
   1453               <li>For libraries shared between applications, not
   1454               possible to take advantage of repository selectors. It
   1455               should be noted that if the SLF4J binding and the
   1456               underlying API ships with each application (not shared
   1457               between applications), then each application will still
   1458               have its own logging environment.  
   1459               </li>
   1460               <li>not IOC-friendly</li>
   1461             </ol>
   1462           </td>
   1463         </tr>
   1464         
   1465         <tr>
   1466           <th width="50%">Advantages for declaring loggers as instance variables</th>       
   1467           <th width="50%">Disadvantages for declaring loggers as
   1468           instance variables</th>
   1469         </tr>
   1470         
   1471         <tr class="alt" valign="top">
   1472           <td> <!-- instance pros -->
   1473             <ol>
   1474               <li>Possible to take advantage of repository selectors
   1475               even for libraries shared between applications. However,
   1476               repository selectors only work if the underlying logging
   1477               system is logback-classic. Repository selectors do not
   1478               work for the SLF4J+log4j combination.
   1479               </li>
   1480               <li>IOC-friendly</li>
   1481             </ol>
   1482           </td>
   1483           
   1484           <td> <!-- instance cons -->
   1485             <ol>
   1486               <li>Less common idiom than declaring loggers as static
   1487               variables</li>
   1488               
   1489               <li>higher CPU overhead: loggers are retrieved and
   1490               assigned for each instance of the hosting class</li>
   1491               
   1492               <li>higher memory overhead: logger declaration will
   1493               consume one reference per instance of the hosting class</li>                   
   1494             </ol>
   1495           </td>
   1496         </tr>        
   1497       </table>
   1498       
   1499       
   1500       <h3>Explanation</h3>
   1501       
   1502       <p>Static logger members cost a single variable reference for
   1503       all instances of the class whereas an instance logger member
   1504       will cost a variable reference for every instance of the
   1505       class. For simple classes instantiated thousands of times
   1506       there might be a noticeable difference.
   1507       </p>
   1508       
   1509       <p>However, more recent logging systems, e.g log4j or logback,
   1510       support a distinct logger context for each application running
   1511       in the application server. Thus, even if a single copy of
   1512       <em>log4j.jar</em> or <em>logback-classic.jar</em> is deployed
   1513       in the server, the logging system will be able to differentiate
   1514       between applications and offer a distinct logging environment
   1515       for each application.
   1516       </p>
   1517       
   1518       <p>More specifically, each time a logger is retrieved by
   1519       invoking <code>LoggerFactory.getLogger()</code> method, the
   1520       underlying logging system will return an instance appropriate
   1521       for the current application. Please note that within the
   1522       <em>same</em> application retrieving a logger by a given name
   1523       will always return the same logger. For a given name, a
   1524       different logger will be returned only for different
   1525       applications.
   1526       </p>
   1527       
   1528       <p>If the logger is static, then it will only be retrieved once
   1529       when the hosting class is loaded into memory. If the hosting
   1530       class is used in only in one application, there is not much to
   1531       be concerned about. However, if the hosting class is shared
   1532       between several applications, then all instances of the shared
   1533       class will log into the context of the application which
   1534       happened to first load the shared class into memory - hardly the
   1535       behavior expected by the user.
   1536       </p>
   1537       
   1538       <p>Unfortunately, for non-native implementations of the SLF4J
   1539       API, namely with slf4j-log4j12, log4j's repository selector will
   1540       not be able to do its job properly because slf4j-log4j12, a
   1541       non-native SLF4J binding, will store logger instances in a map,
   1542       short-circuiting context-dependent logger retrieval. For native
   1543       SLF4J implementations, such as logback-classic, repository
   1544       selectors will work as expected.
   1545       </p>          
   1546       
   1547       <p>The Apache Commons wiki contains an <a
   1548       href="http://wiki.apache.org/jakarta-commons/Logging/StaticLog">informative
   1549       article</a> covering the same question.</p>
   1550       
   1551       <p><b>Logger serialization</b></p>
   1552       
   1553       <p>Contrary to static variables, instance variables are
   1554       serialized by default. As of SLF4J version 1.5.3, logger
   1555       instances survive serialization. Thus, serialization of the host
   1556       class no longer requires any special action, even when loggers
   1557       are declared as instance variables. In previous versions, logger
   1558       instances needed to be declared as <code>transient</code> in the
   1559       host class. </p>
   1560       
   1561       <p><b>Summary</b></p>
   1562       
   1563       <p>In summary, declaring logger members as static variables
   1564       requires less CPU time and have a slightly smaller memory
   1565       footprint. On the other hand, declaring logger members as
   1566       instance variables requires more CPU time and have a slightly
   1567       higher memory overhead.  However, instance variables make it
   1568       possible to create a distinct logger environment for each
   1569       application, even for loggers declared in shared
   1570       libraries. Perhaps more important than previously mentioned
   1571       considerations, instance variables are IOC-friendly whereas
   1572       static variables are not.
   1573       </p>    
   1574      
   1575       <p>See also <a
   1576       href="http://wiki.apache.org/jakarta-commons/Logging/StaticLog">related
   1577       discussion</a> in the commons-logging wiki.
   1578       </p>
   1579       
   1580     </dd>       
   1581   </dl>
   1582   
   1583   <!-- ============================================================= -->
   1584   <dl>
   1585     <dt class="doAnchor" name="declaration_pattern">Is there a
   1586     recommended idiom for declaring a logger in a class?
   1587     </dt>
   1588     
   1589     <dd>
   1590       <p>The following is the recommended logger declaration
   1591       idiom. For reasons <a href="#declared_static">explained
   1592       above</a>, it is left to the user to determine whether loggers
   1593       are declared as static variables or not.</p>
   1594       
   1595       <pre class="prettyprint source">package some.package;
   1596 import org.slf4j.Logger;
   1597 import org.slf4j.LoggerFactory;
   1598       
   1599 public class MyClass {
   1600   <b>final (static) Logger logger = LoggerFactory.getLogger(MyClass.class);</b>
   1601   ... etc
   1602 }</pre>
   1603       
   1604       <p>Unfortunately, give that the name of the hosting class is
   1605       part of the logger declaration, the above logger declaration
   1606       idiom is not is <em>not</em> resistant to cut-and-pasting
   1607       between classes.
   1608       </p>
   1609     </dd>
   1610   </dl>
   1611     
   1612   <script src="templates/footer.js" type="text/javascript"></script>
   1613 </div>
   1614 </body>
   1615 </html>
   1616