Re: Question re: JBoss / Log4J / RepositorySelector / Web-apps

2003-08-24 Thread prhodes







Hi all, I'm trying to work with JBoss and Log4J, and have run
into a question that I can't seem to find the answer to. In the
course of trying to figure out how to specify per-application
Log4J configuration for web-apps running under JBoss,
I found this reference to the RepositorySelector mechanism:
https://www.qos.ch/logging/sc.html

What I don't know however is:

1. Does JBoss even support this mechanism?

Is JBoss written in Java?  Yes, I think it is.  Yep, it is
supported.  Repository selectors just need some unique characteristic that

can differentiate logger repositories.  There are a couple of different
obvious choices to use.  One is keying on different classloaders.  The
other, under a J2EE environment, is keying on a JNDI namespace.
Obviously,
both of these can be used in JBoss since it uses classloaders and is a
J2EE
container.

Sorry, I should have worded my question a little better. What I meant was
more like Does JBoss directly support this, via providing a relevant
RepositorySelector class, and does it set a RepositorySelector when it
initializes Log4J?  Or something along those lines.  Based on some
reading I'd done, I was under the impression that setting a
RepositorySelector
had to be done by the container, when operating in a container environment.

If it is the case that the container does not have to set the
RespositorySelector
in order to use this approach, would that not mean however, that my client
code would
have to call setRepositorySelector()?


2. If so, how do I utilize it in my client code, to retrieve the app
specific
 Log4J instance?

My initial thought, based on a quick perusal of the javadoc gives me the
idea I'd need something like this:


public class ControllerServlet
{
   private static Logger logger;
   private ServletConfig config;

   public void init(ServletConfig config ) throws ServletException
   {
 this.config = config;
 LoggerRepository repos = LogManager.getLoggerRepository();
 logger = repos.getLogger( (ControllerServlet.class
).toString());

   }

   snip
}


is this anything close to correct?

It is actually easier than that.  Your logger code doesn't need to change
at all.  Just.  Once the logger repository selector is used in the
initialization of Log4j, you will be using a unique logger repository.

Aaah, that's the catch... do you have any idea how, in the JBoss
environment,
to ensure that the correct RepositorySelector class is used when Log4J is
initialized?  That seems to be the major thing I'm not understanding
here...
If JBoss initializes Log4J itself, wouldn't that prevent me from being
able to modify the selector? Or am I missing something badly here?

3. assuming the above (or something similar) is used to retrieve the app
specific instance of Log4J,
is there anything special I need to do to tell Log4J where to find
the
app-specific log4j.xml?  Or is
simply putting log4j.xml under WEB-INF/classes sufficent?  Would I still
need to call DOMConfigurator.configure()?

If you use the default initialization mechanism, you will be logging in
the
default logger repository.  If you put both log4j.jar and your log4j.xml
in
the webapp's WEB-INF/lib and WEB-INF/classes, then you should be able to
use this mechanism since the servlet spec makes it so that the webapp
class
loader is checked first for classes and resources.  Only after that does
it
check parent classloader.  Note that this is converse to the normal Java2
class loader hierarchy.  If you put log4j.jar in a parent classloader
(outside of WEB-INF/lib), however, you will need to use a repository
selector to keep your logging separated from other apps.

Hmm... so are you saying that if I put log4j.jar in WEB-INF/lib, since the
class-loader for my web-app will look there first, it doesn't matter that
JBoss has already initialized an instance of Log4J (presumably in a
separate
class-loader)?  If so, this starts to make a little bit more sense.  I
thought
I read something on the 'net somewhere, though, which indicated that
putting
log4j.jar in WEB-INF/lib was a bad idea, which is why I've been thinking
pretty much exclusively in terms of relying on the Log4J instance loaded by
JBoss's boot process.


4. is there any configuration at the JBoss level that needs to be done to
support app-specific Log4J
instances? I know about the log4.xml under server/default/conf/ which
specifies the global Log4J
properties for the container itself...  it wouldn't need to be touched
for
this would it?

Not entirely sure about JBoss specifics, but if you put log4j.jar in
WEB-INF/lib, that jar will be loaded by the webapp rather than the jar
provided by the global JBoss classloader (although I'm not totally sure
about JBoss' single classloader scheme, but it seems that would violate
the
servlet spec if they didn't allow for a separate webapp class loader).

However, if you want to use the global log4j.jar and use separate logger
repositories, 

Re: Question re: JBoss / Log4J / RepositorySelector / Web-apps

2003-08-24 Thread Jacob Kjome
At 09:00 PM 8/23/2003 -0400, you wrote:

Hi all, I'm trying to work with JBoss and Log4J, and have run
into a question that I can't seem to find the answer to. In the
course of trying to figure out how to specify per-application
Log4J configuration for web-apps running under JBoss,
I found this reference to the RepositorySelector mechanism:
https://www.qos.ch/logging/sc.html

What I don't know however is:

1. Does JBoss even support this mechanism?
Is JBoss written in Java?  Yes, I think it is.  Yep, it is
supported.  Repository selectors just need some unique characteristic that
can differentiate logger repositories.  There are a couple of different
obvious choices to use.  One is keying on different classloaders.  The
other, under a J2EE environment, is keying on a JNDI namespace.
Obviously,
both of these can be used in JBoss since it uses classloaders and is a
J2EE
container.
Sorry, I should have worded my question a little better. What I meant was
more like Does JBoss directly support this, via providing a relevant
RepositorySelector class, and does it set a RepositorySelector when it
initializes Log4J?  Or something along those lines.  Based on some
reading I'd done, I was under the impression that setting a
RepositorySelector
had to be done by the container, when operating in a container environment.
That is normally the caseand I'm not sure if JBoss has implemented this 
or not.  You'll probably find out more info on their list.  The way I have 
things set up in my repository selectors and my InitContextListener get 
around this limitation.  Of course, the caveat is that the first 
application to use a repostiory selector forces that selector on all other 
appsat least if those apps are using the same instance of Log4j (from a 
parent classloader instead of the webapp class loader).

To see a case where the container takes care of this, see the experimental 
Log4jHelper addon application for Tomcat-3.3.x...
http://cvs.apache.org/viewcvs/jakarta-tomcat/proposals/Log4jHelper/

If it is the case that the container does not have to set the
RespositorySelector
in order to use this approach, would that not mean however, that my client
code would
have to call setRepositorySelector()?
Yep, in your initialization.  See my InitContextListener for an example.


2. If so, how do I utilize it in my client code, to retrieve the app
specific
 Log4J instance?

My initial thought, based on a quick perusal of the javadoc gives me the
idea I'd need something like this:


public class ControllerServlet
{
   private static Logger logger;
   private ServletConfig config;

   public void init(ServletConfig config ) throws ServletException
   {
 this.config = config;
 LoggerRepository repos = LogManager.getLoggerRepository();
 logger = repos.getLogger( (ControllerServlet.class
).toString());

   }

   snip
}


is this anything close to correct?
It is actually easier than that.  Your logger code doesn't need to change
at all.  Just.  Once the logger repository selector is used in the
initialization of Log4j, you will be using a unique logger repository.
Aaah, that's the catch... do you have any idea how, in the JBoss
environment,
to ensure that the correct RepositorySelector class is used when Log4J is
initialized?  That seems to be the major thing I'm not understanding
here...
If JBoss initializes Log4J itself, wouldn't that prevent me from being
able to modify the selector? Or am I missing something badly here?
Yes, probably so, since you would need to have a handle on the original 
guard object that was used when setting the repository selector.  Without 
that, further calls to LogManager.setRepositorySelector() will fail to set 
your preferred selector.  But that isn't a problem if the existing selector 
works for you.  There isn't any reason it shouldn't.

3. assuming the above (or something similar) is used to retrieve the app
specific instance of Log4J,
is there anything special I need to do to tell Log4J where to find
the
app-specific log4j.xml?  Or is
simply putting log4j.xml under WEB-INF/classes sufficent?  Would I still
need to call DOMConfigurator.configure()?
If you use the default initialization mechanism, you will be logging in
the
default logger repository.  If you put both log4j.jar and your log4j.xml
in
the webapp's WEB-INF/lib and WEB-INF/classes, then you should be able to
use this mechanism since the servlet spec makes it so that the webapp
class
loader is checked first for classes and resources.  Only after that does
it
check parent classloader.  Note that this is converse to the normal Java2
class loader hierarchy.  If you put log4j.jar in a parent classloader
(outside of WEB-INF/lib), however, you will need to use a repository
selector to keep your logging separated from other apps.
Hmm... so are you saying that if I put log4j.jar in WEB-INF/lib, since the
class-loader for my web-app will look there first, it doesn't matter