App Servers and Thread.contextClassLoader

Hello, Slightly odd question, but it is logback related. I'm writing a library to redirect System.out and System.err to SLF4J. I'm envisaging this being used in application servers. I'd like it to work "correctly" with SLF4J implementations like Logback, so if the app server has child first class loading and SLF4J and logback are in webapp A's lib dir, a call to System.out.println within webapp A will be handled as per the logback.xml in webapp A's classes folder, regardless of other webapps with different config. The only way that is possible (as far as I can see) is to work out from the thread calling the System.out methods which web app it was that made the call - and I've found the method getContextClassLoader on Thread which looks hopeful! However, I'm not completely confident that app servers that implement child first class loading will set that to the a web app specific class loader. Does anyone know? Do some app servers use this, and others not? Might save me considerable experimentation time if this is well known info that I just don't happen to know yet. Thanks, Rob

Hi Robert, Robert Elliot wrote:
Slightly odd question, but it is logback related. I'm writing a library to redirect System.out and System.err to SLF4J. I'm envisaging this being used in application servers. I'd like it to work "correctly" with SLF4J implementations like Logback, so if the app server has child first class loading and SLF4J and logback are in webapp A's lib dir, a call to System.out.println within webapp A will be handled as per the logback.xml in webapp A's classes folder, regardless of other webapps with different config.
A per class-loader approach is similar to that of commons-logging. As you know, SLF4J has a different philosophy whereby it will ignore the value returned by Thread.currentThread().getContextClassLoader() and only use the class loader which loaded SLF4J itself (i.e. the class loader which loaded the SLF4J classes). The general problem is called the logging separation problem which is deemed to be exceedingly difficult to solve correctly for all environments. As such, my recommendation would be to ignore the logging separation issue by delegating it to SLF4J.
The only way that is possible (as far as I can see) is to work out from the thread calling the System.out methods which web app it was that made the call - and I've found the method getContextClassLoader on Thread which looks hopeful! However, I'm not completely confident that app servers that implement child first class loading will set that to the a web app specific class loader.
Yes, as far as I know, the app server will set the web app specific class loader for the current thread. If you generalize the context, for example to include build systems (Ant, Maven, Ivy, etc), then things get a little muddier. For example, I believe that earlier versions of Ant did not set the thread context class loader. As for your goal, most application servers have their own way of capturing and redirecting the console. So you may be facing a big hurdle in order to get an app server to adopt your library. Anyway, is it correct to assume that you wish to tackle bug 110 [1] outside SLF4J? [1] http://bugzilla.slf4j.org/show_bug.cgi?id=110 -- Ceki Gülcü Logback: The reliable, generic, fast and flexible logging framework for Java. http://logback.qos.ch

Hi Ceki, On 30 Jul 2009, at 14:45, Ceki Gulcu wrote:
my recommendation would be to ignore the logging separation issue by delegating it to SLF4J.
I intend to - the problem I'm trying to solve is that the webapp which replaces System.out will replace it with an instance of a class loaded by that webapp's classloader, which will load SLF4J and whatever binding it is loading. So which ever web app is the last to replace System.out will get all System.out calls in all webapps (and indeed in the app server) redirected to the logging system specific to that webapp. Which isn't what I want. I've got a theory about it, hopefully I can get something working soon and show it, as real code is a better basis for discussion.
Yes, as far as I know, the app server will set the web app specific class loader for the current thread.
Great, thanks.
As for your goal, most application servers have their own way of capturing and redirecting the console. So you may be facing a big hurdle in order to get an app server to adopt your library.
Oh, I'm not aiming that high! Just to allow the writer of a webapp to configure where System.out goes without it screwing up every other webapp deployed on the app server.
Anyway, is it correct to assume that you wish to tackle bug 110 [1] outside SLF4J?
No, I'd still like to donate it if you want it - just life has got in the way, I've embarked on a fairly major refactor and encountered issues like the one described above and a classloader memory leak that would mean anyone using the library and redeploying the webapp dynamically would have got PermGen issues. I've got another idea about the exception handling issue, too. Hopefully have something out soon. Rob

Robert Elliot wrote:
Hi Ceki,
On 30 Jul 2009, at 14:45, Ceki Gulcu wrote:
my recommendation would be to ignore the logging separation issue by delegating it to SLF4J.
I intend to - the problem I'm trying to solve is that the webapp which replaces System.out will replace it with an instance of a class loaded by that webapp's classloader, which will load SLF4J and whatever binding it is loading. So which ever web app is the last to replace System.out will get all System.out calls in all webapps (and indeed in the app server) redirected to the logging system specific to that webapp. Which isn't what I want. I've got a theory about it, hopefully I can get something working soon and show it, as real code is a better basis for discussion.
Real code is indeed a good basis for discussion. I see several possible techniques which may or may not help you in your design. T1) Once System.out is redirected from a web-app, you will be redirecting System.out for all web-apps, which may be deemed somewhat pushy. However, as long as you revert to the original System.out when your web-app is stopped, it should be OK/acceptable. Note that application servers, just hijack System.out for all hosted applications. T2) If logback is the underlying logging system, without any change in code (in your System.out redirection implementation and assuming you use SLF4J as the logging API) logback could redirect System.out on a per web-application basis. See the Chapter 9 of the logback manual on "Context Selectors": http://logback.qos.ch/manual/loggingSeparation.html . T3) After redirection, the original System.out may continue to be fed with data. (Nothing says that the data flow to the original System.out must be dried out.)
As for your goal, most application servers have their own way of capturing and redirecting the console. So you may be facing a big hurdle in order to get an app server to adopt your library.
Oh, I'm not aiming that high! Just to allow the writer of a webapp to configure where System.out goes without it screwing up every other webapp deployed on the app server.
I understand. One way to achieve this is after hijacxking System.out, to redirect the console to SLF4J within your web-app and to redirect to the original System.out outside your web-app. It's a variant of technique number 3 (T3) mentioned above. You would need to put things back to their original state when your application is stopped (T1).
Anyway, is it correct to assume that you wish to tackle bug 110 [1] outside SLF4J?
No, I'd still like to donate it if you want it - just life has got in the way, I've embarked on a fairly major refactor and encountered issues like the one described above and a classloader memory leak that would mean anyone using the library and redeploying the webapp dynamically would have got PermGen issues. I've got another idea about the exception handling issue, too. Hopefully have something out soon.
I am very happy to see you working on this topic and would like to see the results donated to the SLF4J project, subject of course to your agreement.
Rob -- Ceki Gülcü Logback: The reliable, generic, fast and flexible logging framework for Java. http://logback.qos.ch
participants (2)
-
Ceki Gulcu
-
Robert Elliot