Summary: | ConfigurableClasspathWebappLoader | ||
---|---|---|---|
Product: | Tomcat 5 | Reporter: | Sriram Narayanan <sriramnrn> |
Component: | Catalina | Assignee: | Tomcat Developers Mailing List <dev> |
Status: | RESOLVED WONTFIX | ||
Severity: | enhancement | ||
Priority: | P4 | ||
Version: | 5.5.14 | ||
Target Milestone: | --- | ||
Hardware: | Other | ||
OS: | other | ||
Attachments: |
Files demonstrating how this convenience class might be used
Configurable webapp loader that can add to the web application classpath Picks classpath from an XML file |
Description
Sriram Narayanan
2006-01-11 17:04:09 UTC
Created attachment 17383 [details]
Files demonstrating how this convenience class might be used
1. Extract testing.zip at some location.
2. Follow the instructions gives in the readme.txt file that is kept within
this zip.
Created attachment 17402 [details]
Configurable webapp loader that can add to the web application classpath
Sriram: Thanks for the pointer.
I didn't much like the implementation though - (a) I don't like the need to
create a properties file: though it will greatly simplify the setup if you
have multiple web applications with the same requirements, for me this is
needed for development work only and I don't want developers to get too
comfortable with this hack, and (b) I didn't like the fact that the attached
file doesn't have the source for the class loader, so I couldn't see for myself
how it does this and fix my first problem.
So I created a new class, based on WebappLoader (not WebappClassLoader), which
very simply offers a 'classpath' attribute for the loader, which when filled
with classpath entries (colon separated or whatever your platform likes) it
adds them to the list of repositories in WebappLoader.
So my context looks like this:
<Context path="/my/webapp" docBase="/path/to/my/webapp" debug="0"
privileged="true" reloadable="true">
<Loader
className="org.apache.catalina.loader.ConfigurableWebappClassLoader"
classpath="/path/to/extra/classes:/path/to/more/classes"/>
</Context>
I've tested it to work nicely with Tomcat 5.0.30
I license this code under triple licenses: GPL, LGPL and Apache. I won't mind
if this be added to the Tomcat distribution, though at this point I don't mind
- I only build development servers once in quite a while and the current one is
all done :-)
(In reply to comment #2) > Created an attachment (id=17402) [edit] > Configurable webapp loader that can add to the web application classpath > > Sriram: Thanks for the pointer. > > I didn't much like the implementation though - (a) I don't like the need to > create a properties file: though it will greatly simplify the setup if you > have multiple web applications with the same requirements, for me this is > needed for development work only and I don't want developers to get too > comfortable with this hack, This is indeed too much a feature for production use. I added the properties file support because you'd mentioned in your email that you've a large numebr of paths to add to the CLASSPATH. You'd mentioned fifteen lines, and fifteen lines worth of CLASSPATH entries are better added individually and separately, than clubbed together in one large string. > and (b) I didn't like the fact that the attached > file doesn't have the source for the class loader, so I couldn't see for myself > how it does this and fix my first problem. > The attachment contains a zip file which contains the Eclipse project (complete with .project and .classpath files). I just checked the attachment and I see that it contains this particular zip file as well. So, you have everything in my attachment to see if how I've addressed the problem. See what you think of the source. > So I created a new class, based on WebappLoader (not WebappClassLoader), which > very simply offers a 'classpath' attribute for the loader, which when filled > with classpath entries (colon separated or whatever your platform likes) it > adds them to the list of repositories in WebappLoader. > > So my context looks like this: > <Context path="/my/webapp" docBase="/path/to/my/webapp" debug="0" > privileged="true" reloadable="true"> > <Loader > className="org.apache.catalina.loader.ConfigurableWebappClassLoader" > classpath="/path/to/extra/classes:/path/to/more/classes"/> > </Context> > > I've tested it to work nicely with Tomcat 5.0.30 > > I license this code under triple licenses: GPL, LGPL and Apache. I won't mind > if this be added to the Tomcat distribution, though at this point I don't mind > - I only build development servers once in quite a while and the current one is > all done :-) > Sorry, I didn't see your sources at first
> I added the properties file support because you'd mentioned in your
> email that you've a large numebr of paths to add to the CLASSPATH.
> You'd mentioned fifteen lines, and fifteen lines worth of CLASSPATH
> entries are better added individually and separately, than clubbed
> together in one large string.
I agree. The main problem is that I want to add only a small number of
required projects for each webapp, but have many webapps with different
requirements, which made the class path quite large as it had to address all
the requirements in one place.
I agree that clobbering everything in a single classpath element might be a
problem. Is it possible to have child tags similar to an ant's fileset tag to
include additional paths each with its own element ? from a quick look at the
digester's interaction with the loader I couldn't see such a thing.
Your code looks nice - I see you've implemented addRepository() - what is its
use, except for interface completion ? I saw the bean-info object relate to
something called "events" which lists 'add' methods.
(In reply to comment #4) > Sorry, I didn't see your sources at first Heh, I guess you were excited to try out the files :) No problems :) > > > I added the properties file support because you'd mentioned in your > > email that you've a large numebr of paths to add to the CLASSPATH. > > You'd mentioned fifteen lines, and fifteen lines worth of CLASSPATH > > entries are better added individually and separately, than clubbed > > together in one large string. > > I agree. The main problem is that I want to add only a small number of > required projects for each webapp, but have many webapps with different > requirements, which made the class path quite large as it had to address all > the requirements in one place. > Oh... that'd have also caused you problems where only the first set of classes of two different versions of the same classes in the CLASSPATH would be loaded. e.g. CLASSPATH=jdom1.0.jar;jdom2.0.jar would cause only jdom1.0.jar to be searched for the class org.jdom.Dummy which would be present in both the jars. You've had to contend with a lot of problems all this while ! > I agree that clobbering everything in a single classpath element might be a > problem. Is it possible to have child tags similar to an ant's fileset tag to > include additional paths each with its own element ? from a quick look at the > digester's interaction with the loader I couldn't see such a thing. > This is possible, but would involve you playing with the org.apache.catalina.startup.ContextRuleSet class. I'm working on another approach where the settings are loaded from an XML file. I'll upload this version once I finish it. > Your code looks nice - I see you've implemented addRepository() - what is its > use, except for interface completion ? I saw the bean-info object relate to > something called "events" which lists 'add' methods. This is a method that I'd added for tracing purposes. The idea is for users of this class to try it, and see the debug messages in case they face any problems. Created attachment 17439 [details]
Picks classpath from an XML file
You can specify the classpath via an XML file that can be placed anywhere on
the file system.
The context.xml contains:
<Context docBase="d:\temp\testing" reloadable="true" >
<Loader
className="com.thoughtworks.tomcat.loader.ConfigurableClasspathWebappLoader"
classpathEntriesFile="d:\\temp\\configurations.xml"
/>
</Context>
The XML structure is as follows:
<configuration>
<classpaths>
<path>
file:/d:/temp/bin/
</path>
<path>
file:/c:/temp/deleteThis/
</path>
</classpaths>
</configuration>
Hi. I've tried to get your latest code to work with my Tomcat 5.0.30. I of course recompiled the source, as I'm using JDK 1.4.2. I also had to change the digester from tomcat.util.digester to commons-digester as the former package is not available on my installation (tomcat 5.5 only ?). Now when I load my web application, everytime I try to access something which is handled by the default servlet (such as images or static html), I get a 404 error - "servlet default is not available". Apparently, with the configurable web app class loader loaded, tomcat can't find DefaultServlet from servlets-default.jar. I'm not sure why is that, but with my implementation it does the same. I enabled full debug logging for tomcat, and Here are the class loader hierarchy for a normal web application: DEBUG [main] org.apache.commons.modeler.BaseModelMBean - preRegister WebappClassLoader delegate: false repositories: /WEB-INF/classes/ ----------> Parent Classloader: StandardClassLoader delegate: true repositories: file:/var/lib/tomcat5/server/classes/ file:/var/lib/tomcat5/server/lib/catalina-i18n-es.jar file:/usr/share/java/regexp-1.3.jar file:/var/lib/tomcat5/server/lib/tomcat-jk2.jar file:/var/lib/tomcat5/server/lib/tomcat-coyote.jar file:/var/lib/tomcat5/server/lib/servlets-webdav.jar file:/usr/share/java/jakarta-commons-fileupload-1.0.jar file:/usr/share/java/mx4j/mx4j-jmx-3.0.1.jar file:/var/lib/tomcat5/server/lib/tomcat-util.jar file:/var/lib/tomcat5/server/lib/catalina.jar file:/var/lib/tomcat5/server/lib/catalina-i18n-fr.jar file:/var/lib/tomcat5/server/lib/tomcat-http11.jar file:/usr/java/j2sdk1.4.2_09/jre/lib/rt.jar file:/usr/share/java/catalina-ant-5.0.30.jar file:/usr/share/java/jakarta-commons-digester-1.7.jar file:/var/lib/tomcat5/server/lib/servlets-default.jar file:/usr/share/java/jakarta-commons-modeler-1.1.jar file:/var/lib/tomcat5/server/lib/servlets-invoker.jar file:/usr/share/java/jakarta-commons-logging-1.0.4.jar file:/var/lib/tomcat5/server/lib/catalina-cluster.jar file:/var/lib/tomcat5/server/lib/catalina-i18n-ja.jar file:/usr/share/java/jakarta-commons-beanutils-1.7.0.jar file:/usr/share/java/jakarta-commons-el-1.0.jar file:/var/lib/tomcat5/server/lib/catalina-optional.jar file:/var/lib/tomcat5/server/lib/tomcat-jk.jar file:/var/lib/tomcat5/server/lib/servlets-common.jar file:/var/lib/tomcat5/server/lib/tomcat-jni.jar ----------> Parent Classloader: StandardClassLoader delegate: true repositories: file:/var/lib/tomcat5/common/classes/ file:/usr/share/java/xml-commons-apis-1.3.02.jar file:/usr/share/java/xerces-j2-2.7.1.jar file:/usr/share/java/jta-1.0.1.jar file:/usr/java/j2sdk1.4.2_09/jre/lib/rt.jar file:/usr/share/java/mx4j/mx4j-jmx-3.0.1.jar file:/usr/share/java/jakarta-commons-pool-1.2.jar file:/usr/java/j2sdk1.4.2_09/jre/lib/rt.jar file:/usr/share/java/jasper5-compiler-5.0.30.jar file:/usr/share/java/ant-1.6.2.jar file:/usr/share/java/servletapi5-5.0.30.jar file:/var/lib/tomcat5/common/lib/naming-java.jar file:/var/lib/tomcat5/common/lib/naming-resources.jar file:/usr/share/java/jaf-1.0.2.jar file:/usr/share/java/ant-launcher-1.6.2.jar file:/usr/share/java/jspapi-5.0.30.jar file:/usr/share/java/javamail-1.3.3_01.jar file:/usr/share/java/jakarta-commons-el-1.0.jar file:/usr/share/java/jakarta-commons-collections-3.1.jar file:/usr/share/java/jakarta-commons-logging-api-1.0.4.jar file:/var/lib/tomcat5/common/lib/naming-factory.jar file:/var/lib/tomcat5/common/lib/naming-common.jar file:/usr/share/java/jasper5-runtime-5.0.30.jar file:/usr/share/java/jakarta-commons-dbcp-1.2.1.jar ----------> Parent Classloader: sun.misc.Launcher$AppClassLoader@7b7072 And here is the same output for a web application loaded with your configurable class loader implementation (the output looks identical to the one with my implementation, I think) DEBUG [main] org.apache.commons.modeler.BaseModelMBean - preRegister WebappClassLoader delegate: false repositories: /WEB-INF/classes/ ----------> Parent Classloader: StandardClassLoader delegate: true repositories: file:/var/lib/tomcat5/shared/classes/ ----------> Parent Classloader: StandardClassLoader delegate: true repositories: file:/var/lib/tomcat5/common/classes/ file:/usr/share/java/xml-commons-apis-1.3.02.jar file:/usr/share/java/xerces-j2-2.7.1.jar file:/usr/share/java/jta-1.0.1.jar file:/usr/java/j2sdk1.4.2_09/jre/lib/rt.jar file:/usr/share/java/mx4j/mx4j-jmx-3.0.1.jar file:/usr/share/java/jakarta-commons-pool-1.2.jar file:/usr/java/j2sdk1.4.2_09/jre/lib/rt.jar file:/usr/share/java/jasper5-compiler-5.0.30.jar file:/usr/share/java/ant-1.6.2.jar file:/usr/share/java/servletapi5-5.0.30.jar file:/var/lib/tomcat5/common/lib/naming-java.jar file:/var/lib/tomcat5/common/lib/naming-resources.jar file:/usr/share/java/jaf-1.0.2.jar file:/usr/share/java/ant-launcher-1.6.2.jar file:/usr/share/java/jspapi-5.0.30.jar file:/usr/share/java/javamail-1.3.3_01.jar file:/usr/share/java/jakarta-commons-el-1.0.jar file:/usr/share/java/jakarta-commons-collections-3.1.jar file:/usr/share/java/jakarta-commons-logging-api-1.0.4.jar file:/var/lib/tomcat5/common/lib/naming-factory.jar file:/var/lib/tomcat5/common/lib/naming-common.jar file:/usr/share/java/jasper5-runtime-5.0.30.jar file:/usr/share/java/jakarta-commons-dbcp-1.2.1.jar ----------> Parent Classloader: sun.misc.Launcher$AppClassLoader@7b7072 As you can see, for some reason one level of StandardClassLoader, which contains the servlets-default.jar is missing for some reason. Can you guess what's going on ? (In reply to comment #7) > Hi. I've tried to get your latest code to work with my Tomcat 5.0.30. I of > course recompiled the source, as I'm using JDK 1.4.2. Ack. I'll chance the JDK compatibility level in my Eclipse IDE. And I'm testing against Tomcat 5.5.15 Beta. > I also had to change the digester from tomcat.util.digester to commons-digester > as the former package is not available on my installation (tomcat 5.5 only ?). > Ack. This is interesting. Tomcat 5.5.15 has tomcat.util.digester instead of commons-digester. I don't know why this is the reason - a search in the archives should yield some answer, and I'll try to find out this answer. > Now when I load my web application, everytime I try to access something which is > handled by the default servlet (such as images or static html), I get a 404 > error - "servlet default is not available". > Ack. I just tested this on both Tomcat 5.5.15 as well as 5.0.30. I'm able to run the "testing" and the documentation web apps. I'm also able to view the images and HTML from within these apps on both the Tomcat versions. > Apparently, with the configurable web app class loader loaded, tomcat can't find > DefaultServlet from servlets-default.jar. I'm not sure why is that, but with my > implementation it does the same. > > I enabled full debug logging for tomcat, and Here are the class loader hierarchy > for a normal web application: > <snip/> > > As you can see, for some reason one level of StandardClassLoader, which contains > the servlets-default.jar is missing for some reason. > > Can you guess what's going on ? I've to leave for the day, and will look into this tomorrow. -- Sriram (In reply to comment #8) > (In reply to comment #7) > > Hi. I've tried to get your latest code to work with my Tomcat 5.0.30. I of > > course recompiled the source, as I'm using JDK 1.4.2. > > Ack. I'll chance the JDK compatibility level in my Eclipse IDE. And I'm testing > against Tomcat 5.5.15 Beta. > > > I also had to change the digester from tomcat.util.digester to commons-digester > > as the former package is not available on my installation (tomcat 5.5 only ?). > > > > Ack. This is interesting. Tomcat 5.5.15 has tomcat.util.digester instead of > commons-digester. I don't know why this is the reason - a search in the archives > should yield some answer, and I'll try to find out this answer. > > > Now when I load my web application, everytime I try to access something which is > > handled by the default servlet (such as images or static html), I get a 404 > > error - "servlet default is not available". > > > > Ack. I just tested this on both Tomcat 5.5.15 as well as 5.0.30. I'm able to run > the "testing" and the documentation web apps. I'm also able to view the images > and HTML from within these apps on both the Tomcat versions. > > > Apparently, with the configurable web app class loader loaded, tomcat can't find > > DefaultServlet from servlets-default.jar. I'm not sure why is that, but with my > > implementation it does the same. > > > > I enabled full debug logging for tomcat, and Here are the class loader hierarchy > > for a normal web application: > > > <snip/> > > > > As you can see, for some reason one level of StandardClassLoader, which contains > > the servlets-default.jar is missing for some reason. > > > > Can you guess what's going on ? > > I've to leave for the day, and will look into this tomorrow. > > -- Sriram Sriram: thanks for contributing this. It's an interesting idea and I can see how it'd be useful to some specific applications. However, I don't see it as generally necessary and I don't like that it's not Spec-compliant. We already have some configurtability around the classloaders and their repositories (see the conf/catalina.properties file that ships with Tomcat), so I think this feature, while nice, doesn't have a place in the Tomcat core distribution. Accordingly, I'm closing this as WONTFIX. Of course, if other Tomcat developers are interested in adding this, we can reopen this issue and/or discuss it on the dev mailing list. Oded and anyone else interested: feel free to continue developing, using, and discussing this on the Tomcat user mailing lists or any other forum of your choice. FYI, something similar to this exists in the "DevLoader" component of the Sysdeo Tomcat Plugin for Eclipse. http://www.sysdeo.com/eclipse/tomcatplugin |