Logging library selection
Is short, the recommended setup in contemporary application
(as of 2015) is using SLF4J API for logging everywhere. To get
FreeMarker 2.3.x. to use SLF4J, simply add the
org.slf4j:log4j-over-slf4j
dependency to your
project, and ensure that log4j:log4j
isn't
present. (Starting from FreeMarker 2.4.x you don't need
log4j-over-slf4j
anymore, though it does no harm
either.)
Read on if you are curious about the details, or if you can't use SLF4J...
FreeMarker integrates with the following logging libraries:
SLF4J, Apache Commons
Logging, Log4J 1.x, Avalon
LogKit, and java.util.logging
.
By default, FreeMarker will look for the these logging libraries in
the following order, and will automatically use the first one it
finds (in 2.3.x): Log4J (will use SLF4J instead if it's a
properly installed log4j-over-slf4j
, since
2.3.22), Apache Avalon LogKit, java.util.logging
.
As you can see, Log4j has the highest priority. The presence of
Log4j is simply detected from the presence of the
org.apache.log4j.Logger
class, which means that
Log4j redirections like log4j-over-slf4j
or
log4j-1.2-api
will also get the highest
priority.
Prior to FreeMarker 2.4, SLF4J and Apache Commons Logging
aren't searched automatically due to backward compatibility
constraints. But if you have
org.slf4j:log4j-over-slf4j
properly installed
(means, you have no real Log4j in your class path, and SLF4J has a
backing implementation like logback-classic
),
then FreeMarker will use the SLF4J API directly instead of the Log4j
API (since FreeMarker 2.3.22).
Note that a similar trick can be applied for logging into
Log4j2: If org.apache.logging.log4j:log4j-1.2-api
is present, FreeMarker 2.3.x will pick that as it looks like Log4j,
but all the messages will actually go to Log4j2.
If the auto detection doesn't give you the result that you
want, you can set the
org.freemarker.loggerLibrary
system property to
select a logger library explicitly (since 2.3.22), like:
java ... -Dorg.freemarker.loggerLibrary=SLF4J
The supported system property values are:
SLF4J
, CommonsLogging
,
JUL
(for java.util.logging
),
Avalon
, auto
(the default
behavior), none
(disables logging).
Note that for reliable operation, the system property should be set when the JVM starts (like above), not later from Java code.
Using SLF4J is recommended, as it works best with FreeMarker, and also because it will be the highest priority auto detected logger starting from FreeMarker 2.4.
Logging categories
All log messages produced by FreeMarker are logged with a
logger category that starts with freemarker.
. The
currently used logger categories are:
Log category name | Purpose |
---|---|
freemarker.beans |
Logs messages of the Beans wrapper module. |
freemarker.cache |
Logs messages related to template loading and caching. |
freemarker.runtime |
Logs messages related to template execution that doesn't fit any of the more specific categories. Most importantly, it logs template exceptions thrown during template processing (however that should be disabled in modern application; see later). |
freemarker.runtime.attempt |
Logs template exceptions thrown during template processing
and caught by
attempt /recover
directives, with DEBUG severity. Note that such exceptions
will be still also logged with their normal logger (like
freemarker.runtime ). |
freemarker.servlet |
Logs messages of the FreemarkerServlet
class. |
freemarker.jsp |
Logs messages of the FreeMarker JSP support. |
freemarker.configuration |
Logs messages related to configuring FreeMarker, and not fitting any other categories. |
One quirk relating this is that FreeMarker will log exceptions
during template execution under the
freemarker.runtime
category even if the exception
continues propagating and so eventually will be thrown by
Template.process
or
Environment.process
anyway. (Those are the API
calls with which the template was invoked from the application or
the application framework.) Well behaving applications log the
exceptions thrown at them, or rarely, handle them and deliberately
don't want to log them. But as FreeMarker has already logged that
exception, you will end up one more log entry than expected. To fix
that (since 2.3.22), set the
log_template_exceptions
(Configurable.setLogTemplateExceptions(boolean)
)
setting to false
.