You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-user@logging.apache.org by chuanjiang lo <lo...@gmail.com> on 2006/12/26 10:02:25 UTC

Loading sequence of log4j

Hi all

I have this start up servlet that does the initializing some system
parameters.

 <load-on-startup>1</load-on-startup>
And i place this servlet on the first priority

In the servlet i have something..
System.setProperty("admin-console-abs-home",
getServletContext().getRealPath("")+getServletConfig().getInitParameter("adminConsoleLog"));

So the log4j.xml uses something like
<param name="File" value="${admin-console-abs-home}"/>

Sometimes the Start up servlet runs first and initalize the property. But at
times log4j starts first and giving an error
log4j:ERROR setFile(null,true) call failed.

So how can i ensure that log4j initalizes only after my start up servlet
finishes initalizing?

Re: Loading sequence of log4j

Posted by Maarten Bosteels <mb...@gmail.com>.
Be aware that system properties are shared by all webapps running inside one
tomcat instance.
That means, if you call System.setProperty("foo","bar") in a listener of
webapp1
all other webapps will get "bar" when they call System.getProperty("foo")

Not all servlet containers behave this way.

Maarten

On 12/26/06, Jacob Kjome <ho...@visi.com> wrote:
>
>
> Don't use a init servlet.  The servlet spec makes no guarantee as to
> when the servlet initialization will happen.  It may or may not be at
> container startup.  Use a serlvet context listener.  It has methods
> that are guaranteed to be called at application startup and
> application shutdown.  Here's what I suggest...
>
> Assuming you are using Tomcat...
>
> 1.  Put log4j.jar in WEB-INF/lib and a dummy Log4j config file (see
> below) in WEB-INF/classes.  The dummy config file is meant to cover
> for autoconfiguration if it runs before your manual configuration
> runs, avoiding various bogus logging, warning messages from Log4j, or
> other errors.
>
> 2.  Put your real config file under WEB-INF, but not in WEB-INF/classes
>
> 3.  Implement a servlet context listener  and implement the
> contextInitialized() method (off the top of my head, I think that's
> what it is called).  Set you system property first and then manually
> configure log4j, pointing it to your real config file somewhere under
> WEB-INF.
>
> BTW, I don't recommend logging to a directory directly under the
> application directory.  The servlet spec makes no guarantee that you
> have write access to the file system other than the provided
> System.getProperty("java.io.temp") directory.  I suggest you set the
> system property via the command line using a -D parameter when you
> start up the appserver.  With Tomcat, you can provide this in the
> CATALINA_OPTS system property...
>
> CATALINA_OPTS=-Dadmin-console-abs-home=/my/path/to/logs
>
> If you do this, you can bypass the dummy Log4j config file and skip
> manual initialization.  Just put your real config file in
> WEB-INF/classes and let Log4j auto-configure itself, since the system
> property is now guaranteed to be there before Log4j initializes itself.
>
>
>
> Here's an example of a dummy Log4j config file to suppress Log4j
> errors until you perform your manual initialization......
>
> <?xml version="1.0" encoding="UTF-8" ?>
> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
>
> <!-- This file is meant to satisfy/supress auto-configuration of the
> default logger repository
>       when log4j.jar is included in WEB-INF/lib.  This assumes that
> manual configuration will be
>       performed later, usually on a non-default logger repository as
> specified by a repository selector.
>       The purpose of supression is to avoid Log4j auto-configuration
> finding a Log4j config file in a
>       parent classloader when it can't find one locally, which can
> lead to either bogus
>       (but generally harmless) configuration of the default
> repository or even a nasty stacktrace
>       if an incompatible Log4j config file is found (such as when
> using Log4j-1.2.x in WEB-INF/lib
>       and Log4j-1.3 in the server's classpath.  The XML formats are
> generally incompatible!).
>       This file should be copied to WEB-INF/classes as "log4j.xml"
> when building the .war file. -->
> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
> debug="false" threshold="debug">
>      <root>
>          <level value="off"/>
>      </root>
> </log4j:configuration>
>
>
> Jake
>
> At 03:02 AM 12/26/2006, you wrote:
> >Hi all
> >
> >I have this start up servlet that does the initializing some system
> >parameters.
> >
> > <load-on-startup>1</load-on-startup>
> >And i place this servlet on the first priority
> >
> >In the servlet i have something..
> >System.setProperty("admin-console-abs-home",
> >getServletContext().getRealPath("")+getServletConfig().getInitParamete
> >r("adminConsoleLog"));
> >
> >So the log4j.xml uses something like
> ><param name="File" value="${admin-console-abs-home}"/>
> >
> >Sometimes the Start up servlet runs first and initalize the property. But
> at
> >times log4j starts first and giving an error
> >log4j:ERROR setFile(null,true) call failed.
> >
> >So how can i ensure that log4j initalizes only after my start up servlet
> >finishes initalizing?
> >
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
> For additional commands, e-mail: log4j-user-help@logging.apache.org
>
>

Re: Loading sequence of log4j

Posted by Jacob Kjome <ho...@visi.com>.
At 04:04 AM 12/27/2006, you wrote:
 >On 12/27/06, chuanjiang lo <lo...@gmail.com> wrote:
 >>
 >> I am using PropertyConfigurator.configure in the Listener class
 >>
 >>  PropertyConfigurator.configure(event.getServletContext
 >> ().getRealPath("")+"/WEB-INF/foo.xml");
 >>

2 things...

1. Never ever use this.  Always load as a resource.  As I stated 
before, the servlet spec makes no guarantee that you will be a "real 
path".  If your webapp is served directly from the .WAR file instead 
of an "exploded" WAR, getRealPath("/") will return null.  Instead use 
context.getResource("/WEB-INF/foo.xml").  This will return a URL, 
which you can pass to the configure() method that takes a URL.  See...

http://java.sun.com/j2ee/sdk_1.2.1/techdocs/api/javax/servlet/ServletContext.html#getResource(java.lang.String)

2.  You can't use PropertyConfigurator with an XML config file.  Use 
DOMConfigurator for XML config files

 >> Log4j is picking up foo.xml, However it seems like the logging events does
 >> not behave as what foo.xml specifies. Nothing has changed.
 >> Appreciate any kind advice.
 >
 >
 >
 >Learnt the mistake here.
 >I should be using DOMConfigurator.configure()
 >

Depends on what your config is.  If this works, it means you have a 
log4j.xml somewhere in the classpath and it is using that for 
configuration.  This is clearly not what you want because your config 
file is named "foo.xml" and it doesn't even exist in the 
classpath.  You are picking up someone elses config file.  What you 
should be doing is calling configure(myFooXMLURL) with the URL you 
loaded (see above).

 >One thing i notice for PropertiesConfigurator
 >
 >for e.g.
 > Properties props = new Properties();
 >props.put("admin-console-abs-home", path);
 > in = this.getClass().getClassLoader().getResourceAsStream("foo.properties
 >");
 >props.load(in);
 > PropertyConfigurator.configure(props);
 >
 >In this case in foo.properties, we are able to use ${admin-console-abs-home}
 >as a variable.
 >Is there any method for DOMConfigurator?
 >

The only difference between the 2 configurators, as far as property 
references are concerned, is that you can't define the property 
inside the XML file where you can inside the properties 
file.  However, in both cases, you can reference the property inside 
the respective config files.  so, your property reference of 
${admin-console-abs-home} will work in both cases.


Also note what one responder mentioned.  If you defined a system 
property, it is available to all applications.  I suggest that any 
property you set either generically named *and* generically points to 
a single location where you are ok with any app running within the 
container logging to this directory OR name your properties very 
specifically, such as "fooApp.log.home", where "fooApp" is the name 
of a specific application.  Naming your properties specifically 
reduces the chance that you will clash with other apps that might be 
setting or depending on their own properties.

What I suggest is that you just log to tomcat's default logging 
directory.  Tomcat already sets ${catalina.home} and ${catalina.base} 
properties.  I suggest using the latter (read up on Tomcat to find 
out why).  This will simplify your life.  If you refer to these 
properties to provide the directory for logging, then you don't need 
to mess with any manual log4j config process nor do you need to set a 
custom -D parameter to specify your logging home.  Just put your 
log4j.xml or log4j.properties (use those names, specifically) in 
WEB-INF/classes and log4j.jar in WEB-INF/lib and you are done.


Jake

Jake



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Re: Loading sequence of log4j

Posted by chuanjiang lo <lo...@gmail.com>.
On 12/27/06, chuanjiang lo <lo...@gmail.com> wrote:
>
> I am using PropertyConfigurator.configure in the Listener class
>
>  PropertyConfigurator.configure(event.getServletContext
> ().getRealPath("")+"/WEB-INF/foo.xml");
>
> Log4j is picking up foo.xml, However it seems like the logging events does
> not behave as what foo.xml specifies. Nothing has changed.
> Appreciate any kind advice.



Learnt the mistake here.
I should be using DOMConfigurator.configure()

One thing i notice for PropertiesConfigurator

for e.g.
 Properties props = new Properties();
props.put("admin-console-abs-home", path);
 in = this.getClass().getClassLoader().getResourceAsStream("foo.properties
");
props.load(in);
 PropertyConfigurator.configure(props);

In this case in foo.properties, we are able to use ${admin-console-abs-home}
as a variable.
Is there any method for DOMConfigurator?

Re: Loading sequence of log4j

Posted by chuanjiang lo <lo...@gmail.com>.
On 12/27/06, chuanjiang lo <lo...@gmail.com> wrote:
>
>
>
> Appreciate your advice.
>
> How do i manually configure the log4j config file to point to WEB-INF?
>
>
>
I am using PropertyConfigurator.configure in the Listener class

 PropertyConfigurator.configure(event.getServletContext
().getRealPath("")+"/WEB-INF/foo.xml");

Log4j is picking up foo.xml, However it seems like the logging events does
not behave as what foo.xml specifies. Nothing has changed.
Appreciate any kind advice.

Re: Loading sequence of log4j

Posted by chuanjiang lo <lo...@gmail.com>.
On 12/27/06, Jacob Kjome <ho...@visi.com> wrote:
>
>
> 3.  Implement a servlet context listener  and implement the
> contextInitialized() method (off the top of my head, I think that's
> what it is called).  Set you system property first and then manually
> configure log4j, pointing it to your real config file somewhere under
> WEB-INF.


Appreciate your advice.

How do i manually configure the log4j config file to point to WEB-INF?

Re: Loading sequence of log4j

Posted by Jacob Kjome <ho...@visi.com>.
Don't use a init servlet.  The servlet spec makes no guarantee as to 
when the servlet initialization will happen.  It may or may not be at 
container startup.  Use a serlvet context listener.  It has methods 
that are guaranteed to be called at application startup and 
application shutdown.  Here's what I suggest...

Assuming you are using Tomcat...

1.  Put log4j.jar in WEB-INF/lib and a dummy Log4j config file (see 
below) in WEB-INF/classes.  The dummy config file is meant to cover 
for autoconfiguration if it runs before your manual configuration 
runs, avoiding various bogus logging, warning messages from Log4j, or 
other errors.

2.  Put your real config file under WEB-INF, but not in WEB-INF/classes

3.  Implement a servlet context listener  and implement the 
contextInitialized() method (off the top of my head, I think that's 
what it is called).  Set you system property first and then manually 
configure log4j, pointing it to your real config file somewhere under WEB-INF.

BTW, I don't recommend logging to a directory directly under the 
application directory.  The servlet spec makes no guarantee that you 
have write access to the file system other than the provided 
System.getProperty("java.io.temp") directory.  I suggest you set the 
system property via the command line using a -D parameter when you 
start up the appserver.  With Tomcat, you can provide this in the 
CATALINA_OPTS system property...

CATALINA_OPTS=-Dadmin-console-abs-home=/my/path/to/logs

If you do this, you can bypass the dummy Log4j config file and skip 
manual initialization.  Just put your real config file in 
WEB-INF/classes and let Log4j auto-configure itself, since the system 
property is now guaranteed to be there before Log4j initializes itself.



Here's an example of a dummy Log4j config file to suppress Log4j 
errors until you perform your manual initialization......

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<!-- This file is meant to satisfy/supress auto-configuration of the 
default logger repository
      when log4j.jar is included in WEB-INF/lib.  This assumes that 
manual configuration will be
      performed later, usually on a non-default logger repository as 
specified by a repository selector.
      The purpose of supression is to avoid Log4j auto-configuration 
finding a Log4j config file in a
      parent classloader when it can't find one locally, which can 
lead to either bogus
      (but generally harmless) configuration of the default 
repository or even a nasty stacktrace
      if an incompatible Log4j config file is found (such as when 
using Log4j-1.2.x in WEB-INF/lib
      and Log4j-1.3 in the server's classpath.  The XML formats are 
generally incompatible!).
      This file should be copied to WEB-INF/classes as "log4j.xml" 
when building the .war file. -->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" 
debug="false" threshold="debug">
     <root>
         <level value="off"/>
     </root>
</log4j:configuration>


Jake

At 03:02 AM 12/26/2006, you wrote:
 >Hi all
 >
 >I have this start up servlet that does the initializing some system
 >parameters.
 >
 > <load-on-startup>1</load-on-startup>
 >And i place this servlet on the first priority
 >
 >In the servlet i have something..
 >System.setProperty("admin-console-abs-home",
 >getServletContext().getRealPath("")+getServletConfig().getInitParamete
 >r("adminConsoleLog"));
 >
 >So the log4j.xml uses something like
 ><param name="File" value="${admin-console-abs-home}"/>
 >
 >Sometimes the Start up servlet runs first and initalize the property. But at
 >times log4j starts first and giving an error
 >log4j:ERROR setFile(null,true) call failed.
 >
 >So how can i ensure that log4j initalizes only after my start up servlet
 >finishes initalizing?
 >
 > 


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org