RE: How to have multiple loggers with shared code also using the logger?

2009-01-24 Thread removeps-groups
Here's an update on the logger issue.  It too me long to figure out because I 
ran into an issue about privileged servlets and had to write my own 
log4j.properties parser.

The original code posted earlier in this thread works in that it creates a 
different logger for web application, and allows the user to stop and restart 
the application.

   public static Logger getLogger()
   {
  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  URL log4j_properties = classLoader.getResource(log4j_app.properties);
  String loggerName = log4j_properties.toString(); // throws 
NullPointerException if log4j_app.properties does not exist
  synchronized (MyLog.class)
  {
 Logger logger = 
Logger.getRootLogger().getLoggerRepository().exists(loggerName);
 if (logger == null)
 {
logger = Logger.getLogger(loggerName);
PropertyConfigurator.configure(log4j_properties);
System.out.println(Created logger: loggerName= + loggerName);
 }
 return logger;
  }
   }

One bug with the above is the line

PropertyConfigurator.configure(log4j_properties);


The above re-configures the root logger with the new log4j.properties, so 
basically the new configuration applies to all loggers.  What would be nice is

PropertyConfigurator.configure(logger, log4j_properties);

that configures only the specified logger with the log4j_properties.  
Unfortunately, log4j does not have such a function, so I wrote my own (but it 
only supports the properties used in my log4j_app.properties files).

Now, if web application 1 calls MyLog.getLogger() or calls common code that 
calls MyLog.getLogger() then the first logger will be used, and similarly for 
web application 2.

Finally, I create a servlet 

   import org.apache.catalina.manager.ManagerServlet;

   public class TomcatManagerServlet extends ManagerServlet

The servlet is called for /reload, and it calls super.doGet() after doing 
some checks.

It turns out that only privileged web applications can instantiate 
ManagerServlet, so one has to have the following in context.xml:

   Context privileged=true

I'm not sure what is the practical impact of setting privileged=true, though 
the docs said something about the catalina and shared class loaders.

So upon calling

http://localhost/mywebservice/reload?path=/

the ROOT application is stopped and started.  After the application restart, 
all users are logged out and they have to log in again, but the logger 
continues to work.  A call to MyLog.getLogger() does not re-create the logger.

The logger is really owned by the common code in ${catalina.home}/lib.  The 
code 

  URL log4j_properties = classLoader.getResource(log4j_app.properties);

just gets the URL of the log4j.properties file.  However, there is no pointer 
to anything in the webapp, so it's possible to stop the webapp.  And the line

PropertyConfigurator.configure(log4j_properties);

opens the URL (by calling log4j_properties.getInputStream()), reads it, and 
closes it.  So no stream in the webapp is open, and it's possible to stop the 
webapp.



--- On Thu, 1/15/09, Caldarale, Charles R chuck.caldar...@unisys.com wrote:

 From: Caldarale, Charles R chuck.caldar...@unisys.com
 Subject: RE: How to have multiple loggers with shared code also using the 
 logger?
 To: Tomcat Users List users@tomcat.apache.org
 Date: Thursday, January 15, 2009, 11:28 AM
  From: removeps-gro...@yahoo.com
 [mailto:removeps-gro...@yahoo.com]
  Subject: RE: How to have multiple loggers with shared
 code
  also using the logger?
 
  How does one redploy a single application?  Strange, I
  could not find any information on this seemingly basic
  task on google.
 
 Read the real docs first, then Google only if needed.
 http://tomcat.apache.org/tomcat-6.0-doc/deployer-howto.html#Deploying%20on%20a%20running%20Tomcat%20server
 http://tomcat.apache.org/tomcat-6.0-doc/manager-howto.html
 
  - Chuck
 
 
 THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR
 OTHERWISE PROPRIETARY MATERIAL and is thus for use only by
 the intended recipient. If you received this in error,
 please contact the sender and delete the e-mail and its
 attachments from all computers.
 
 -
 To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
 For additional commands, e-mail:
 users-h...@tomcat.apache.org

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-15 Thread removeps-groups
Thanks, this makes sense.  However, I'd like to find out what is being held 
onto by the log4j.jar.  So I'd like to test it out.  How does one redploy a 
single application?  Strange, I could not find any information on this 
seemingly basic task on google.  Thanks again.


--- On Wed, 1/14/09, Caldarale, Charles R chuck.caldar...@unisys.com wrote:

 From: Caldarale, Charles R chuck.caldar...@unisys.com
 Subject: RE: How to have multiple loggers with shared code also using the
 logger?
 To: Tomcat Users List users@tomcat.apache.org
 Date: Wednesday, January 14, 2009, 9:27 PM
  From: removeps-gro...@yahoo.com
 [mailto:removeps-gro...@yahoo.com]
  Subject: RE: How to have multiple loggers with shared
 code
  also using the logger?
 
  And since the log4j.jar resides in the
 ${catalina.home}/lib
  folder, this root logger is used by all web apps.
 
 The log4j.jar is only there because you put it there.  It
 does not come with the Tomcat distribution, and it's
 normally placed in the WEB-INF/lib directory of each webapp
 that needs it.
 
 By having such a jar in a common location, you've
 pretty much guaranteed that you'll have to take Tomcat
 down to redeploy a single webapp - the old webapp won't
 go away because log4j will be hanging onto references to it.
  (A common cause of PermGen filling up after redeployments.)
 
 The servlet spec (and experience) strongly suggest that
 webapps be kept as isolated as possible for this kind of
 reason.
 
  - Chuck
 
 
 THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR
 OTHERWISE PROPRIETARY MATERIAL and is thus for use only by
 the intended recipient. If you received this in error,
 please contact the sender and delete the e-mail and its
 attachments from all computers.
 
 -
 To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
 For additional commands, e-mail:
 users-h...@tomcat.apache.org

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-15 Thread Caldarale, Charles R
 From: removeps-gro...@yahoo.com [mailto:removeps-gro...@yahoo.com]
 Subject: RE: How to have multiple loggers with shared code
 also using the logger?

 How does one redploy a single application?  Strange, I
 could not find any information on this seemingly basic
 task on google.

Read the real docs first, then Google only if needed.
http://tomcat.apache.org/tomcat-6.0-doc/deployer-howto.html#Deploying%20on%20a%20running%20Tomcat%20server
http://tomcat.apache.org/tomcat-6.0-doc/manager-howto.html

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY 
MATERIAL and is thus for use only by the intended recipient. If you received 
this in error, please contact the sender and delete the e-mail and its 
attachments from all computers.

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-14 Thread removeps-groups
 Because of the classloading hierarchy.  Once the logger is
 initialized with the common classloader, everybody uses that
 one.

Thanks.  I studied the Apache logger code.

When we call org.apache.log4j.Logger.getLogger(), it calls functions of 
LogManager.  The static initializer block of LogManager gets log4j.properties 
using the thread's class loader, so if the first webapp I run is mywebservice, 
then it will get log4j.properties from mywebservice, such as 
mywebservice/WEB-INF/classes/log4j.properties.  The root logger will be 
initialized using this log4j.properties file, and all new loggers will inherit 
this configuration, which does not seem very useful.

And since the log4j.jar resides in the ${catalina.home}/lib folder, this root 
logger is used by all web apps.

So what I did is

(1) Create a log4j.properties in ${catalina.home}/lib/log4j.properties or in a 
jar file here.

(2) This properties file should contain the configuration shared by all app 
loggers.  For me, the file is one line:
log4j.rootLogger=warn

(3) Rename log4j.properties in each webapp and swingapp and JUnit test app to 
log4j_app.properties.

(4) Modify MyLog.getLogger(), which is a function in a jar file that is shared 
by all apps (ie. a function in ${catalina.home}/lib) so that when a logger is 
created, initialize the logger from the appropriate log4j_app.properties.

import org.apache.log4j.PropertyConfigurator;

   /**
* This function attempts to locate log4j_app.properties using the
* thread's classloader, and returns a logger using the location of
* log4j_app.properties as the logger name.
* The logger will be initialized with the configuration in 
log4j_app.properties.
* This allows each application within the web server will use its own 
logger.
* This function is thread-safe, and callers don't need to synchronized on 
MyLog.
* @return
* @throws NullPointerException if log4j_app.properties does not exist
*/
   public static Logger getLogger()
   {
  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  URL log4j_properties = classLoader.getResource(log4j_app.properties);
  String loggerName = log4j_properties.toString();
  synchronized (MyLog.class)
  {
 Logger logger = 
Logger.getRootLogger().getLoggerRepository().exists(loggerName);
 if (logger == null)
 {
logger = Logger.getLogger(loggerName);
PropertyConfigurator.configure(log4j_properties);
System.out.println(Created logger: loggerName= + loggerName);
 }
 return logger;
  }
   }

 
 Don't do that.  Keep just one copy of the source
 somewhere, just have your packaging script put the .class
 file in the webapp package.  No need to have an abstract
 class or subclasses.

Not sure if that would work as the log4j.jar is in ${catalina.home}/lib, so the 
root logger is shared by all apps.
 

  (1) Pass a logger from the webapp to the common code
 -- ie.
  to add a Logger argument to all the functions in the
 common
  code, but this sounds tedious.
 
 That's the cost of keeping things isolated, which is a
 worthwhile goal.
 
  (2) In each webapp have a filter that sets a thread
 local
  variable like ThreadLocalLogger threadLogger.
 
 Just make sure you clear the ThreadLocal on *every*
 possible exit path out of your request processing.  If you
 don't, you will have memory leaks in PermGen causing it
 to fill up as webapps are redeployed.



-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-14 Thread Caldarale, Charles R
 From: removeps-gro...@yahoo.com [mailto:removeps-gro...@yahoo.com]
 Subject: RE: How to have multiple loggers with shared code
 also using the logger?

 And since the log4j.jar resides in the ${catalina.home}/lib
 folder, this root logger is used by all web apps.

The log4j.jar is only there because you put it there.  It does not come with 
the Tomcat distribution, and it's normally placed in the WEB-INF/lib directory 
of each webapp that needs it.

By having such a jar in a common location, you've pretty much guaranteed that 
you'll have to take Tomcat down to redeploy a single webapp - the old webapp 
won't go away because log4j will be hanging onto references to it.  (A common 
cause of PermGen filling up after redeployments.)

The servlet spec (and experience) strongly suggest that webapps be kept as 
isolated as possible for this kind of reason.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY 
MATERIAL and is thus for use only by the intended recipient. If you received 
this in error, please contact the sender and delete the e-mail and its 
attachments from all computers.

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-13 Thread Mark Thomas
 -Original Message-
 From: removeps-gro...@yahoo.com [mailto:removeps-gro...@yahoo.com]
 
 How to have multiple loggers with shared code also using the logger?

This is more of a log4j question that a Tomcat one. From a brief look at the
log4j sources it looks as if you'll need a custom RepositorySelector that
used the context classloader to select the repository to use. I thought
log4j did that by default. I could be wrong on that or I might have read the
source code incorrectly.

Mark



-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-13 Thread Caldarale, Charles R
 From: removeps-gro...@yahoo.com [mailto:removeps-gro...@yahoo.com]
 Subject: How to have multiple loggers with shared code also
 using the logger?

 How to have multiple loggers with shared code also using the logger?
 In ${catalina.home}/lib there is a jar file that contains class MyLog.

Doctor, doctor, it hurts when I do this.

The simple fix is: don't do it.  Package your webapps so that each contains a 
copy of MyLog rather than putting that class in the common location.  You can 
still maintain the same source, just make sure the .class file is located 
locally in each webapp that uses it.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY 
MATERIAL and is thus for use only by the intended recipient. If you received 
this in error, please contact the sender and delete the e-mail and its 
attachments from all computers.

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-13 Thread removeps-groups
Why is it what I'm trying to do not working though?  It seems that my 
MyLog.getLogger function does find the correct logger name, and that 
Logger.getLogger() is always using the the first log4j.properties that was 
found.

Yeah, I had tried something like this, namely to have a class AbstractMyLog in 
the common folder, and a class MyLog in each of the webapps that derives from 
AbstractMyLog so as to minimize code changes.  But then the common code also 
needs to write to the log file, and it should use the log file of the web 
application that called it.

The other ideas I had are:

(1) Pass a logger from the webapp to the common code -- ie. to add a Logger 
argument to all the functions in the common code, but this sounds tedious.

(2) In each webapp have a filter that sets a thread local variable like 
ThreadLocalLogger threadLogger.


--- On Tue, 1/13/09, Caldarale, Charles R chuck.caldar...@unisys.com wrote:

 From: Caldarale, Charles R chuck.caldar...@unisys.com
 Subject: RE: How to have multiple loggers with shared code also using the  
 logger?
 To: Tomcat Users List users@tomcat.apache.org
 Date: Tuesday, January 13, 2009, 6:21 AM
  From: removeps-gro...@yahoo.com
 [mailto:removeps-gro...@yahoo.com]
  Subject: How to have multiple loggers with shared code
 also
  using the logger?
 
  How to have multiple loggers with shared code also
 using the logger?
  In ${catalina.home}/lib there is a jar file that
 contains class MyLog.
 
 Doctor, doctor, it hurts when I do this.
 
 The simple fix is: don't do it.  Package your webapps
 so that each contains a copy of MyLog rather than putting
 that class in the common location.  You can still maintain
 the same source, just make sure the .class file is located
 locally in each webapp that uses it.
 
  - Chuck
 
 
 THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR
 OTHERWISE PROPRIETARY MATERIAL and is thus for use only by
 the intended recipient. If you received this in error,
 please contact the sender and delete the e-mail and its
 attachments from all computers.
 
 -
 To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
 For additional commands, e-mail:
 users-h...@tomcat.apache.org

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: How to have multiple loggers with shared code also using the logger?

2009-01-13 Thread Caldarale, Charles R
 From: removeps-gro...@yahoo.com [mailto:removeps-gro...@yahoo.com]
 Subject: RE: How to have multiple loggers with shared code
 also using the logger?

 Why is it what I'm trying to do not working though?  It seems
 that my MyLog.getLogger function does find the correct logger
 name, and that Logger.getLogger() is always using the the
 first log4j.properties that was found.

Because of the classloading hierarchy.  Once the logger is initialized with the 
common classloader, everybody uses that one.

 Yeah, I had tried something like this, namely to have a class
 AbstractMyLog in the common folder, and a class MyLog in each
 of the webapps that derives from AbstractMyLog so as to
 minimize code changes.

Don't do that.  Keep just one copy of the source somewhere, just have your 
packaging script put the .class file in the webapp package.  No need to have an 
abstract class or subclasses.

 (1) Pass a logger from the webapp to the common code -- ie.
 to add a Logger argument to all the functions in the common
 code, but this sounds tedious.

That's the cost of keeping things isolated, which is a worthwhile goal.

 (2) In each webapp have a filter that sets a thread local
 variable like ThreadLocalLogger threadLogger.

Just make sure you clear the ThreadLocal on *every* possible exit path out of 
your request processing.  If you don't, you will have memory leaks in PermGen 
causing it to fill up as webapps are redeployed.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY 
MATERIAL and is thus for use only by the intended recipient. If you received 
this in error, please contact the sender and delete the e-mail and its 
attachments from all computers.

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org