You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by Mark Palmer <bi...@yahoo.com> on 2005/07/26 18:49:16 UTC

Log4j in tomcat common/lib and in WEB-INF/lib

I have written a open source version of jta for tomcat
that can be used with and the existing version of
apache DBCP. (to be released shortly)

I am using log4j of course:-)

My code and needs to be common/lib (i.e. don't want to
modify the web application war file in any way)

This means log4j needs to be in common/lib as well.

However some of the web application are bundled with
log4j.

As a result I get:

log4j:ERROR [StandardClassLoader
  delegate: true
  repositories:
    file:C:\tomcat\common\classes\

----------> Parent Classloader:
sun.misc.Launcher$AppClassLoader@53ba3d
] whereas object of type 
log4j:ERROR "org.apache.log4j.RollingFileAppender" was
loaded by [WebappClassLoader
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
StandardClassLoader
  delegate: true
  repositories:
    file:C:\tomcat\\classes\
----------> Parent Classloader:
StandardClassLoader
  delegate: true
  repositories:
    file:C:\tomcat\common\classes\
    ...

Any ideas on how to get around this class loader
issue?

I don't mind writer some custom log4j code to help

-Mark 


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

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


Re: Log4j in tomcat common/lib and in WEB-INF/lib

Posted by Ceki Gülcü <ce...@qos.ch>.
At 01:25 PM 7/27/2005, Simon Kitching wrote:

>You might want to read a little rant I wrote recently about misusing
>classloader hierarchies in containers. It's not entirely relevant to
>your current issue but some of it might be useful:
>   http://wiki.apache.org/jakarta-commons/Logging/UndeployMemoryLeak

Simon, I've enjoyed reading your article. Cognizant of the memory leak
problem you mention, the version of log4j which is currently CVS HEAD,
does "not" include a context selector based on class loaders. The only
selector which is included is based on JNDI. Unless I am missing
something, ContextJNDISelector does not cause memory leaks. Previous
versions of log4j (e.g. 1.2) did not ship with any selectors.


>Regards,
>
>Simon

-- 
Ceki Gülcü

   The complete log4j manual: http://www.qos.ch/log4j/



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


Re: Log4j in tomcat common/lib and in WEB-INF/lib

Posted by Simon Kitching <sk...@apache.org>.
On Wed, 2005-07-27 at 03:16 -0700, Mark Palmer wrote:

> What I need is a way to programatically append to the
> webapps logging context.

Hmm. So given a webapp which might have log4j bundled with it, when that
webapp calls into your code which is deployed
within the container's classpath you want to be able to:
* fetch logger configuration from out of the TCCL
* add objects to it


I think you're into some heavy reflection work there. As you've noticed,
all the objects that the webapp sees have types which are Class objects
as loaded from the webapp's context classloader. So you can't
instantiate objects as normal from your code; they will be of types as
loaded from the container's classloader which aren't compatible.

When calling methods, creating new objects, etc. associated with the
logging stuff you got out of the TCCL you'll always need to use
reflection. Very heavy reflection. I hope this code isn't going to be on
anyone's critical path.

This isn't anything that log4j can do anything about. 

You might want to read a little rant I wrote recently about misusing
classloader hierarchies in containers. It's not entirely relevant to
your current issue but some of it might be useful:
  http://wiki.apache.org/jakarta-commons/Logging/UndeployMemoryLeak

Regards,

Simon


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


Re: Log4j in tomcat common/lib and in WEB-INF/lib

Posted by Mark Palmer <bi...@yahoo.com>.
Simon,

Thankyou for taking the time to reply.

I am not using the Contextual Repository Selector. One
of my goals was not to change the web application in
any way, and allow the web application to be bundled
with log4j (any version) including it's configuration.
i.e. I wanted to be able to work with third party
applications.

>From my understanding, I would not be able to use the
CRS. To complicate matters, the thread that is running
in my code, is the worker thread running in the web
application. 

I am happing to use the version of log4j that gets
bundled with a webapp, and to use the webapps logging
context.

What I need is a way to programatically append to the
webapps logging context.

regards

Mark



--- Simon Kitching <sk...@apache.org> wrote:

> On Tue, 2005-07-26 at 09:49 -0700, Mark Palmer
> wrote:
> > I have written a open source version of jta for
> tomcat
> > that can be used with and the existing version of
> > apache DBCP. (to be released shortly)
> > 
> > I am using log4j of course:-)
> > 
> > My code and needs to be common/lib (i.e. don't
> want to
> > modify the web application war file in any way)
> > 
> > This means log4j needs to be in common/lib as
> well.
> > 
> > However some of the web application are bundled
> with
> > log4j.
> > 
> > As a result I get:
> > 
> > log4j:ERROR [StandardClassLoader
> >   delegate: true
> >   repositories:
> >     file:C:\tomcat\common\classes\
> > 
> > ----------> Parent Classloader:
> > sun.misc.Launcher$AppClassLoader@53ba3d
> > ] whereas object of type 
> > log4j:ERROR "org.apache.log4j.RollingFileAppender"
> was
> > loaded by [WebappClassLoader
> >   delegate: false
> >   repositories:
> >     /WEB-INF/classes/
> > ----------> Parent Classloader:
> > StandardClassLoader
> >   delegate: true
> >   repositories:
> >     file:C:\tomcat\\classes\
> > ----------> Parent Classloader:
> > StandardClassLoader
> >   delegate: true
> >   repositories:
> >     file:C:\tomcat\common\classes\
> >     ...
> > 
> > Any ideas on how to get around this class loader
> > issue?
> > 
> > I don't mind writer some custom log4j code to help
> 
> You appear to have omitted the previous three error
> messages which are
> extremely important to understanding the meaning of
> this one.
> 
> After some investigation made trickier by this
> omission, it appears that
> the message is coming from log4j's
> OptionConverter.instantiateByClassname method.
> 
> I expect that the full messages are complaining
> about
> RollingFileAppender not being compatible with type
> Appender.
> 
> The cause of this is the helpers.Loader class
> looking in the thread
> context classloader (TCL aka TCCL) to find classes
> whose names are in
> the log4j.properties or log4j.xml file. It finds a
> class of the
> requested name, but that class is bound to the
> Appender class loaded
> from the TCCL not from the one that the calling
> class has bound to.
> 
> Are you or the container using the Contextual
> Repository Selector? I'm
> presuming not. In this case, log4j is actually going
> to get initialised
> just once - and this will happen the first time any
> log4j method is
> called. It's doubly-bad therefore when that first
> call happens in the
> context of *some arbitrary* webapp, and that log4j's
> Loader class then
> tries to load classes whose names are in the log4j
> configuration file
> from that arbitrary webapp.
> 
> If you could ensure that log4j was initialised
> before any webapp tries
> to call it that would fix the problem. Putting a
> call to a log4j method
> in the static initialiser of one of your classes
> might be worth trying:
>   class SomeClass {
>     static {  
>       // force log4j initialisation outside of the
> context of a webapp
>       Logger.getLog("");
>     }
>   }
> however that relies on something causing that class
> to be loaded.
> 
> Maybe you could write a Tomcat "valve" class that
> gets put into the
> tomcat configuration file that has the dummy static
> block. Valves should
> get loaded on tomcat startup. Anyway, there's bound
> to be some variant
> of that idea that works.
> 
> Regards,
> 
> Simon
> 
> 
> 
>
---------------------------------------------------------------------
> To unsubscribe, e-mail:
> log4j-dev-unsubscribe@logging.apache.org
> For additional commands, e-mail:
> log4j-dev-help@logging.apache.org
> 
> 


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

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


Re: Log4j in tomcat common/lib and in WEB-INF/lib

Posted by Simon Kitching <sk...@apache.org>.
On Tue, 2005-07-26 at 09:49 -0700, Mark Palmer wrote:
> I have written a open source version of jta for tomcat
> that can be used with and the existing version of
> apache DBCP. (to be released shortly)
> 
> I am using log4j of course:-)
> 
> My code and needs to be common/lib (i.e. don't want to
> modify the web application war file in any way)
> 
> This means log4j needs to be in common/lib as well.
> 
> However some of the web application are bundled with
> log4j.
> 
> As a result I get:
> 
> log4j:ERROR [StandardClassLoader
>   delegate: true
>   repositories:
>     file:C:\tomcat\common\classes\
> 
> ----------> Parent Classloader:
> sun.misc.Launcher$AppClassLoader@53ba3d
> ] whereas object of type 
> log4j:ERROR "org.apache.log4j.RollingFileAppender" was
> loaded by [WebappClassLoader
>   delegate: false
>   repositories:
>     /WEB-INF/classes/
> ----------> Parent Classloader:
> StandardClassLoader
>   delegate: true
>   repositories:
>     file:C:\tomcat\\classes\
> ----------> Parent Classloader:
> StandardClassLoader
>   delegate: true
>   repositories:
>     file:C:\tomcat\common\classes\
>     ...
> 
> Any ideas on how to get around this class loader
> issue?
> 
> I don't mind writer some custom log4j code to help

You appear to have omitted the previous three error messages which are
extremely important to understanding the meaning of this one.

After some investigation made trickier by this omission, it appears that
the message is coming from log4j's
OptionConverter.instantiateByClassname method.

I expect that the full messages are complaining about
RollingFileAppender not being compatible with type Appender.

The cause of this is the helpers.Loader class looking in the thread
context classloader (TCL aka TCCL) to find classes whose names are in
the log4j.properties or log4j.xml file. It finds a class of the
requested name, but that class is bound to the Appender class loaded
from the TCCL not from the one that the calling class has bound to.

Are you or the container using the Contextual Repository Selector? I'm
presuming not. In this case, log4j is actually going to get initialised
just once - and this will happen the first time any log4j method is
called. It's doubly-bad therefore when that first call happens in the
context of *some arbitrary* webapp, and that log4j's Loader class then
tries to load classes whose names are in the log4j configuration file
from that arbitrary webapp.

If you could ensure that log4j was initialised before any webapp tries
to call it that would fix the problem. Putting a call to a log4j method
in the static initialiser of one of your classes might be worth trying:
  class SomeClass {
    static {  
      // force log4j initialisation outside of the context of a webapp
      Logger.getLog("");
    }
  }
however that relies on something causing that class to be loaded.

Maybe you could write a Tomcat "valve" class that gets put into the
tomcat configuration file that has the dummy static block. Valves should
get loaded on tomcat startup. Anyway, there's bound to be some variant
of that idea that works.

Regards,

Simon



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


Re: Log4j in tomcat common/lib and in WEB-INF/lib

Posted by Simon Kitching <sk...@apache.org>.
On Tue, 2005-07-26 at 11:35 -0700, Elias Ross wrote:
> On Tue, 2005-07-26 at 09:49 -0700, Mark Palmer wrote:
> 
> > My code and needs to be common/lib (i.e. don't want to
> > modify the web application war file in any way)
> > 
> > This means log4j needs to be in common/lib as well.
> 
> This is more of a user question (and a FAQ really), but here's an idea
> I'd like to share that's somewhat related.
> 
> You can add a custom appender from a classloader that log4j doesn't see
> upon start-up by first loading the base "generic" configuration, and
> when your model boots, add the appender to the category/logger tree,
> e.g.
> 
> Logger.getRootLogger().addAppender(new MyWarFileAppender())
> 
> But this gets hard to configure.  So, it would be nice to have a model
> that allows you to "merge" a log4j.xml file with an existing
> configuration.  So, you could have:
> 
> log4j.xml (base)
> log4j-custom.xml (gets loaded by a servlet)
> 
> And declared categories/appenders etc. would be overlaid onto an
> existing configuration rather than replacing the existing configuration
> outright.
> 

Log4j has the ability to be configured with custom repository
(hierarchy) selectors. If a Contextual Repository Selector is used then
log4j will set up a separate logging enviroment for each distinct Thread
Context Class Loader (TCCL) - and each webapp has its own TCCL. The
Contextual Repository Selector also looks for the initial log4j
configuration files in the TCCL path so that log4j.xml or
log4j.properties in the webapp's path will be used instead of the one in
the container's path.

The container does need to explicitly set up log4j to use such a
selector however.

See http://www.qos.ch/logging/sc.jsp

Note that I don't personally agree with all of Ceki's arguments in the
above link.

> And maybe people wouldn't feel as compelled to bundle log4j.jar into
> every .war deployment...

I've never understood this view of the world. A standard servlet or j2ee
container has a set of libraries that it is *required* to provide to
components. But log4j is *not* part of that set. Therefore components
*should* bundle log4j if they want to use it.

To me, it's ugly and evil for jars to be added to shared classpaths in a
container. The container is the container, and the component is the
component, and bits of the component do not belong in the container.


Regards,


Simon


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


Re: Log4j in tomcat common/lib and in WEB-INF/lib

Posted by Elias Ross <er...@m-qube.com>.
On Tue, 2005-07-26 at 09:49 -0700, Mark Palmer wrote:

> My code and needs to be common/lib (i.e. don't want to
> modify the web application war file in any way)
> 
> This means log4j needs to be in common/lib as well.

This is more of a user question (and a FAQ really), but here's an idea
I'd like to share that's somewhat related.

You can add a custom appender from a classloader that log4j doesn't see
upon start-up by first loading the base "generic" configuration, and
when your model boots, add the appender to the category/logger tree,
e.g.

Logger.getRootLogger().addAppender(new MyWarFileAppender())

But this gets hard to configure.  So, it would be nice to have a model
that allows you to "merge" a log4j.xml file with an existing
configuration.  So, you could have:

log4j.xml (base)
log4j-custom.xml (gets loaded by a servlet)

And declared categories/appenders etc. would be overlaid onto an
existing configuration rather than replacing the existing configuration
outright.

And maybe people wouldn't feel as compelled to bundle log4j.jar into
every .war deployment...



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