You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by bu...@apache.org on 2004/10/14 21:32:16 UTC
DO NOT REPLY [Bug 31721] New: -
LogManager.createLogSystem does not use contextClassLoader
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=31721>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND
INSERTED IN THE BUG DATABASE.
http://issues.apache.org/bugzilla/show_bug.cgi?id=31721
LogManager.createLogSystem does not use contextClassLoader
Summary: LogManager.createLogSystem does not use
contextClassLoader
Product: Velocity
Version: 1.4
Platform: All
OS/Version: Linux
Status: NEW
Severity: Normal
Priority: Other
Component: Source
AssignedTo: velocity-dev@jakarta.apache.org
ReportedBy: srevilak@f7.net
We use velocity-1.4 as part of a web application; it processes
templates that are served to clients as html files. The servlet
container used is tomcat 5.0.18. Things are laid out like this:
* CATALINA_HOME/shared/lib/velocity.jar
(along with other third-party libraries)
Our class files:
* CATALINA_HOME/webapps/<context>/WEB-INF/classes
* CATALINA_HOME/webapps/<context>/WEB-INF/lib
Recently, we attempted to add our own logging class
(implements org.apache.velocity.runtime.log.LogSystem). In doing so,
I believe I have discovered a bug in velocity's LogManager class.
Our logger is com.r9.nucleus.velocity.Logger
runtime.log.logsystem.class=com.r9.nucleus.velocity.Logger
com.r9.nucleus.velocity.Logger lives in a jar in WEB-INF/lib.
A servlet (in the same jar file) can locate, instantiate, and use this
class directly. However, when velocity attempts to use it, we get
this:
java.lang.ClassNotFoundException: com.r9.nucleus.velocity.Logger
at org.apache.catalina.loader.StandardClassLoader.loadClass(StandardClassLoader.java:891)
at org.apache.catalina.loader.StandardClassLoader.loadClass(StandardClassLoader.java:756)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
at org.apache.velocity.runtime.log.LogManager.createLogSystem(LogManager.java:123)
at org.apache.velocity.runtime.RuntimeInstance.initializeLogger(RuntimeInstance.java:553)
at org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:226)
at org.apache.velocity.runtime.RuntimeInstance.init(RuntimeInstance.java:461)
at org.apache.velocity.app.VelocityEngine.init(VelocityEngine.java:106)
at com.r9.nucleus.velocity.VelocityUtils.createVelocityEngine(VelocityUtils.java:83)
at com.r9.seeker.template.FormTemplate.getEngine(FormTemplate.java:519)
at com.r9.seeker.template.FormTemplate.parse(FormTemplate.java:99)
at com.r9.seeker.scrape.AirScraper.populateAndParseTemplate(AirScraper.java:200)
at com.r9.seeker.scrape.AirScraper.retrieveResultsPage(AirScraper.java:174)
at com.r9.seeker.scrape.AirScraper.specificSearch(AirScraper.java:104)
at com.r9.seeker.core.MultiSearcher.search(MultiSearcher.java:167)
at com.r9.seeker.core.SearchThreadPool$RunnableSearch.run(SearchThreadPool.java:82)
at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Thread.java:534)
Here is the relevant section of LogManager.createLogSystem (w/line
numbers).
107 /*
108 * now run through the list, trying each. It's ok to
109 * fail with a class not found, as we do this to also
110 * search out a default simple file logger
111 */
112
113 for( Iterator ii = classes.iterator(); ii.hasNext(); )
114 {
115 String claz = (String) ii.next();
116
117 if (claz != null && claz.length() > 0 )
118 {
119 rsvc.info("Trying to use logger class " + claz );
120
121 try
122 {
123 >>> HERE >>> o = Class.forName( claz ).newInstance();
124
125 if ( o instanceof LogSystem )
126 {
127 ((LogSystem) o).init( rsvc );
128
129 rsvc.info("Using logger class " + claz );
130
131 return (LogSystem) o;
132 }
133 else
134 {
135 rsvc.error("The specifid logger class " + claz +
136 " isn't a valid LogSystem");
137 }
138 }
139 catch( NoClassDefFoundError ncdfe )
140 {
141 rsvc.debug("Couldn't find class " + claz
142 + " or necessary supporting classes in "
143 + "classpath. Exception : " + ncdfe);
144 }
145 }
146 }
This is what appears to be happening:
- velocity.jar is loaded by tomcat's shared loader.
- a servlet can instantiate and use our Logger class directly; they
both fall under the same tomcat WebAppClassLoader.
- LogManager fails because it's using Class.forName() - attempting to
use the Shared classloader that loaded velocity.jar. This
classloader cannot has no visibility into the webapp classloader
repository.
Would it be possible to consider changing this:
123 >>> HERE >>> o = Class.forName( claz ).newInstance();
to something like:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = getClass().getClassLoader();
}
o = Class.forName(claz, true, loader).newInstance();
This should allow LogManager to have the same class visibility as the
executing servlet thread.
---------------------------------------------------------------------
To unsubscribe, e-mail: velocity-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: velocity-dev-help@jakarta.apache.org