• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
394org.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/&lt;/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);
796debug(String format, Object arg);
797debug(String format, Object arg1, Object arg2);
798debug(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();
939logger.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+".");
956logger.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;
1087import org.slf4j.LoggerFactory;
1088import org.slf4j.Marker;
1089import org.slf4j.MarkerFactory;
1090
1091class 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";
1237try {
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;
1596import org.slf4j.Logger;
1597import org.slf4j.LoggerFactory;
1598
1599public 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