Here is a list of commonly encountered problems when using log4j:
ClassCastException when instantiating a Category subclasses.
My EJB-Servlet-JSP says log4j class not found or not defined.
log4j:WARN No such property [xyz] in some.appender.or.layout
log4j: No appenders could be found for category (some.category.name). log4j: Please initialize the log4j system properly.
Log4j does not have a default logging target. It is the user's responsibility to ensure that all categories can inherit an appender. This can be easily achieved by attaching an appender to the root category.
The reason for observing duplicates in log4j output is either due to having added the same appender multiple times to the same category (typically root) or having added the same appender to different categories ignoring the fact that appenders are inherited cumulatively.
log4j does not eliminate appender duplicates. In other words, if you add the same appender to a category n times, that appender will be invoked n times to append to its target.
A slightly different cause is adding different appenders
all sharing the same underlying output target to some
category. In the most common occurrence of this phenomenon,
the BasicConfigurator.configure() method is invoked multiple
times. Each time it is invoked, this method adds an appender
with a System.out
target to the root
category.
One other common mistake is to forget that appenders are
inherited cumulatively from the hierarchy. For example, if
you add an appender, say A
, to the root
category, all other categories will inherit A
as an appender. Thus, if you add A
to a
category, say C
, then an enabled statement of
category C
, will print to A
twice,
once because A
is in root and once because it
is in C
.
The PropertyConfigurator relies on
java.util.Properties
class to read in the
configuration file. This class preserves spaces in
options. For example,
fruit=orangeis returned as an option having the key
"fruit"
and the
value "orange "
.
The spaces in the value, i.e. "orange "
, are due to
invisible spaces at the end of the example shown above. Thus, some of
the options might not be interpreted correctly due to trailing
spaces.
You can remedy this problem by disabling the JIT compiler and by compiling the code without the -O option.
In wrappers or subclasses of Category
Wrappers or subclasses of Category
need supply their
fully qualified class name to the Category.log
method or
to Category.forcedLog
methods so that the caller location
information can be extracted correctly.
This approach will work correctly in all cases except if
the class invoking the extended category instance has the
same prefix as the extended category class. For example,
calling an instance of com.foo.BarCategory
from the com.foo.BarCategoryTest
class will
not yield the correct caller information. To circumvent
this "bug", either perform the tests from a class with a
different name or add a dot to the fully qualified name of
the extending class that you supply to
Category.log
to
Category.forcedLog
methods. For the
com.foo.BarCategory
example, supply the
string "com.foo.BarCategory."
.
ClassCastException
when
instantiating a Category
subclasses.
This exception is thrown because log4j does not support
homonyms. For example, the following will systematically throw a
ClassCastException
Category c1 = Category.getInstance("bad"); MyCategory c2 = (MyCategory) MyCategory.getInstance("bad");where
MyCategory
is a subclass of
Category
. The problem occurs because the second
getInstance
invocation will retrieve the category created
in the fist invocation. This instance is a Category
object and cannot be cast to MyCategory
.
By default, the PropertyConfigurator
will
create and configure
org.apache.log4j.Category
objects. Thus, if
you try to instantiate a category subclass for an already
existing category, and try to cast it to the subclass
type, you will systematically get a
ClassCastException
.
To address this problem, the
PropertyConfigurator
admits the
log4j.categoryFactory
key. The value of this
key will be used as the factory to invoke when
instantiating Category objects.
The DOMConfigurator
has a finer grain
method for setting the class of the category object to instantiate.
Naturally you should check the classpath. But you should also
be aware of the presence of multiple classloaders in the JVM:
If you place log4j.jar in the Servlet, JSP and EJB containers inside of application servers
usually have their own special classloaders in addition to the
three mentioned above. While this provides for a greater
degree of separation for different webapps, EJB containers and the
application server runtime itself, it can provide headaches to the
uninitiated.
Classloaders are usually hierarchically related. The bootstrap
loader forms the root with the extension loader as its child. The
application loader is the child of the extension loader and it's
this "app loader" that we use by default when we write standalone
Java programs.
Upon receiving a class load request, the classloader usually
delegates it to the parent before attempting to service the request.
This allows the bootstrap and extension loaders to deliver any classes
that are part of the JDK or its extensions. Only after this delegation
fails will the classloader attempt to find the class itself. Note that
classloaders do not delegate requests to children.
Application servers often use the application loader for its runtime
classes and create separate classloaders for its webapp and EJB
containers. These additional classloaders may descend directly
from the app server's runtime classloader. If log4j is placed in the
classpath of a webapp classloader, another webapp classloader will not
necessarily see it. EJBs wouldn't see it either. If log4j is intended
to be made available to all objects participating in the app server, it
should be included in the classpath of a classloader high enough in the
classloader hierarchy to be seen by all classloaders.
A good article on classloaders with examples using IBM's WebSphere
application server can be found
here
in PDF format.
I cannot log to syslogd under linux.
If you are trying to log to the Unix syslog under Linux using the SyslogAppender,
then the Linux syslog daemon must be configured to accept log input
from the network. Otherwise, you will get an This can be done by adding the Log4j class not found/defined
jre/lib/ext
directory
but place user-defined extensions to log4j in the application
classloader classpath, log4j configurators will not find them.
IOException:
connection refused
.
-r
option when starting
the daemon. Or more precisely:
root
user
/etc/rc/init.d/syslog
case "$1" in
start)
echo -n "Starting system logger: "
daemon syslogd -r
/etc/rc/init.d/syslog restart