Will, I recently ran into a variant of this, only worse. We solved the problem by placing log4j in the system classpath, so it's shared by all applications, and by all server-level components.
We are using an oldish version of WebLogic, with ColdFusion MX running inside of it. ColdFusion has an evil webservices.jar file that includes a PRE-1.0 version of commons-logging. We had to move webservices.jar up to the server level as well to insure that the current version of JCL is used in all applications. I think the best solution would be a JCL configuration option that caused it to ignore the thread-context classloader. .T. > -----Original Message----- > From: Will Jaynes [mailto:[EMAIL PROTECTED] > Sent: Thursday, October 9, 2003 03:02 PM > To: [EMAIL PROTECTED] > Subject: Re: commons-logging & classloading > > >> Why does LogFactoryImpl in commons-logging > >> try to load the Log implementation class first > >> from thread classloader and then loader that loaded this class? > >> > >> Is there some kind of design pattern behind this? > >> > > > >One very common :-) use case for commons-logging is inside web > >applications, where the servlet container provides a class loader per > >webapp (pointing at the classes in /WEB-INF/classes and /WEB-INF/lib), > >plus normally a parent class loader for shared classes and resources. > >The container is required to set the Thead context class loader for the > >current webapp prior to handing the request off to the servlet. > > > >The lookup design pattern in LogFactoryImpl allows webapps to use their > >own version of the log implementation classes. > > With regard to this web app use case, the problem I'm seeing is that I > can't share components at the server level if they use commons-logging. > What must the configuration of jars and property files look like if I > have components that use commons-loggin both at the server and web app > levels? > > So far, nothing works properly unless all components are at the web app > level (in WEB-INF/lib). > > > Here's an example of what can go wrong: > I have slide and HttpClient in at the server level in resin/lib. > HttpClient uses commons-logging, so I have to add commons-logging to > resin/lib. My web app uses Struts, so I've got commons-logging in > WEB-INF/lib, and I use log4j, so log4j.jar is also in WEB-INF/lib. (by > the way, I'm using Java 1.4) > > As soon as my web app trys to use HttpClient I get a exception : "Class > org.apache.commons.logging.impl.Log4JLogger does not implement Log". I > believe that what is happening is this: HttpClient loads with the server > classloader. HttpClient wants to log, so it causes Log and LogFactory to > be loaded with the server classloader. LogFactory specifically uses the > thread context classloader to look a log factory. The thread context > classloader is the web app's classloader, so it finds LogFactoryImpl and > log4j and then loads Log4JLogger, but it is still using the thread > context classloader, so it finds the Log4JLogger in the WEB-INF/lib. It > then does a check with Log.class.isAssignableFrom() on Log4JLogger, but > since Log and Log4JLogger were loaded with different classloaders the > test fails and the exception is thrown. > > After a lot of experimentation, the only configuration of jars that > works properly is to put everything in the WEB-INF/lib of each web app. > Commons-loggin has made it impossible to deploy slide and HttpClient > at the server level. > > Am I missing something in how to configure this use case? > > Will > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
