Bonjour,

I found a bug in the class "org.apache.catalina.loader.WebappClassLoader":

The method "findClassInternal" cannot return "null" when the required class
is not in one of the "local repositories" but in one of the "external
repositories". 
This implies that the call to "super.findClass(name);"  in the method
"findClass(String name)" (line 954) cannot be done.

I try to use the capabitity of standard WebappClassLoader to add an
"external repository" to be able to load shared classes stored in a folder
out side of the "WEB-INF/classes" folder tree.

To minimize the dependence between my WebApp and catalina, I use the
reflexion to call upon the method "addDirectory(String aRepository)".

See behind :
- the config of my workstation.
- the log found in the stdout of tomcat
- the source code of my method which add an external repository in the
WebAppClassLoader.


I think that I found an other bug but I do'nt know "where" it is (...) :  
Before using the reflexion, I tried to write a extend of the catalina
"WebappClassLoader" but when you set a "Loader" tag in the config file
"server.xml" like the followed one, the created "loader" is an instance of
"com.adonix.x3.x3web.tomcat.loader.CAdapiLoader", but the associated
classLoader is an instance of "org.apache.catalina.loader.WebappClassLoader"
and not an instance of
"com.adonix.x3.x3web.tomcat.loader.CAdapiClassLoader" !

                <Loader
className="com.adonix.x3.x3web.tomcat.loader.CAdapiLoader"
                                                delegate="false" 
                                                reloadable="false" 
                                                checkInterval="15" 
                                                debug="9" 
 
loaderClass="com.adonix.x3.x3web.tomcat.loader.CAdapiClassLoader"  />

Craig and Remy could be the best to answer me ?  

Note: I put at the end of this contribution the two exchanges of mall which
I had yesterday with Craig to illustrate the context of my developments

Thanks a lot in advance.

Olivier Gattaz 
----------------------------------------------------------------------------
----
Adonix - 5 avenue Victor Hugo - 38130 Echirolles - France


My plaform :
 - W2000 SP2
 - Apache httpd 2.0.39 + Mod_jk
 - Sun JDK 1.3.1_03
 - Tomcat 4.0.4 running like a service and configured for
   multiple instances by setting $CATALINA_BASE
   - set CATALINA_LOG=D:\Adonix\X3Web\data\SERVERSLOGS\TOMCAT
   - set CATALINA_HOME=C:\Program Files\Apache Tomcat 4.0
   - set CATALINA_BASE=C:\Program files\Adonix\X3Web\SERVERS_BASE
   - set JAVA_HOME=C:\jdk1.3.1_03

Log in the stdout (debug=9)

        WebappClassLoader:
loadClass(com.adonix.adapidatasources.gx3app.screen.rec.CAdapiRecEWK2WEB3D,
false)
        WebappClassLoader:   Searching local repositories
        WebappClassLoader:
findClass(com.adonix.adapidatasources.gx3app.screen.rec.CAdapiRecEWK2WEB3D)
        WebappClassLoader:
findClassInternal(com.adonix.adapidatasources.gx3app.screen.rec.CAdapiRecEWK
2WEB3D)
        WebappClassLoader:     --> Passing on ClassNotFoundException
        java.lang.ClassNotFoundException:
com.adonix.adapidatasources.gx3app.screen.rec.CAdapiRecEWK2WEB3D
                at
org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLo
ader.java:1586)
                at
org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.jav
a:937)
                at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav
a:1372)
                at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav
a:1254)
                at
java.lang.ClassLoader.loadClassInternal(ClassLoader.java:310)
                at java.lang.Class.forName0(Native Method)
                at java.lang.Class.forName(Class.java:115)
                at
com.adonix.adapi.CAdapiRecord.instanciateRecord(CAdapiRecord.java:885)
                at
com.adonix.adapi.CAdapiRecord.instanciateRecord(CAdapiRecord.java:819)
                at
com.adonix.adapi.protocol.CAdapiSeg.addData(CAdapiSeg.java:187)
                at
com.adonix.adapi.protocol.CAdapiConn.readSeg(CAdapiConn.java:534)
                at
com.adonix.adapi.protocol.CAdapiConn.run(CAdapiConn.java:701)
        WebappClassLoader:   Delegating to parent classloader




Source of my method "setClassLoader", 

        
//--------------------------------------------------------------------
        private static String CATALINA_LOADER =
"org.apache.catalina.loader.WebappClassLoader";
        private static String CATALINA_LOADER_METHOD_ADDREP =
"addRepository";
        private static String CATALINA_LOADER_METHOD_GETURLS = "getURLs";
        
//--------------------------------------------------------------------
        /**
        * invoke the method "public void addRepository(String repository)"
        * if it is an instance of
"org.apache.catalina.loader.WebappClassLoader"
        */
        private void setClassLoader(String aRepository) throws
ServletException
        {
                ClassLoader wClassLoader =
Thread.currentThread().getContextClassLoader();
                String wClassLoaderName = wClassLoader.getClass().getName();

                log("---setClassLoader:");
        
log(CStringFacilities.toStringDescr("ClassLoaderName",wClassLoaderName));
                
                /* this test replace "instanceof" which return false if the
tested class is
                instancied by an other class loader (other name space !)*/
                if (wClassLoaderName.equals(CATALINA_LOADER)){
                        
                        /* build the URL of the external repository */
                        String wUrl = "file:"+ aRepository;
        
                        /* invoke addRepository(String aRep) */
                        try {
                                Class[] wParameterTypes  = new
Class[]{String.class};
                                Object[] wArguments = new Object[] {wUrl};
                                Method wMethodAddRepository =
wClassLoader.getClass().getMethod(CATALINA_LOADER_METHOD_ADDREP,wParameterTy
pes );
                                wMethodAddRepository.invoke(wClassLoader,
wArguments);
                        } catch (Exception e) {
                                log("Can't invoke addRepository(String
aRep)\n" + CStringFacilities.eToString(e));
                        }
                        
                        /* invoke getURLs() */
                        try {
                                Method wMethodGetUrl =
wClassLoader.getClass().getMethod(CATALINA_LOADER_METHOD_GETURLS,new
Class[0] );
                                RL[] wUrls = (URL[])
wMethodGetUrl.invoke(wClassLoader, new Object[0] );
                                int wMax = wUrls.length;
                                for (int wI=0;wI<wMax;wI++){
                                        log(CStringFacilities.toStringDescr(
"external repository ["+wI+"]",wUrls[wI].toString() ));
                                }
                        } catch (Exception e) {
                                log("Can't invoke getURLs()\n" +
CStringFacilities.eToString(e));
                        }
                }
        }




On Tue, 23 Jul 2002, Gattaz, Olivier wrote:

> Date: Tue, 23 Jul 2002 17:23:04 +0200
> From: "Gattaz, Olivier" <[EMAIL PROTECTED]>
> To: 'Craig R. McClanahan' <[EMAIL PROTECTED]>
> Subject: RE: problem with a custom WebAppClassLoader
>
> Craig,
>
> Thanks a lot for your response !
>
> Yes I see that I will be dependant of tomcat if I develop a custom
> WebAppClassLoader
> but the standard implementation does'nt authorize me to load classes
stored
> out of
> the standard class directoy of the WebApps ("WEF-INF/classes") !
>
> Could the plublic description of the "Loader component" disappear from the
> configuration  file "server.xml" in the future ?  Could the "Loader
> component"
> concept disappear from Tomcat ?
>

Anything is possible.  For example, the efforts to build Tomcat 5 (to
support the upcoming Servlet 2.4 and JSP 2.0 specs) is just getting
started, and refactoring some of the internal interfaces for better code
organization is definitely one of the topics of discussion.

> It is certain that the simplest way would be to have a new attribute in
the
> tag "loader" to pass a "classpath" to add to the set of places the
standard
> WebAppClassLoader can look for classes to be loaded.
>
> NOTE: it is the first thing what I want to do with my custom
> WebAppClassLoader !
>
> Could I use the method "addRepository()" to simulate this "new" attribute
?
>
> How can I retrive the current WebAppClassLoader of my WebApp ?  With the
> static
> method "Thread.currentThread()" ?
>
> The second thing what I want to do with my custom WebAppClassLoader,
> is to monitor the classes generated from the ERP to reload the new one.
> If I use the standard WebAppClassLoader I can't monitor my generated
classes
> and do'nt monitor the webapp classes which change only when I install a
> new vesrion.
>
> Have you an other idea that develop a specialized lassLoader to solve my
> problems ?
>

I'm afraid that I cannot in good conscience encourage anybody to take this
approach.  Class loaders are about the worst black magic in all of Java --
you are going to be really sorry if you get yourself sucked into this
approach.

Wouldn't it be easier to just create a regular class loader inside your
webapp, instead of trying to modify Tomcat's?  After all, you can
explicitly ask it to load classes for you.

Craig


> Best regards.
>
>
>
> -----Message d'origine-----
> De : Craig R. McClanahan [mailto:[EMAIL PROTECTED]]
> Envoyé : mardi 23 juillet 2002 17:02
> À : Gattaz, Olivier
> Objet : Re: problem with a custom WebAppClassLoader
>
>
> On Tue, 23 Jul 2002, Gattaz, Olivier wrote:
>
> > Date: Tue, 23 Jul 2002 15:04:25 +0200
> > From: "Gattaz, Olivier" <[EMAIL PROTECTED]>
> > To: "'[EMAIL PROTECTED]'" <[EMAIL PROTECTED]>
> > Subject: problem with a custom WebAppClassLoader
> >
> >
> > Bonjour Craig,
> >
> > Excuse me for this direct eMail but I had no response for my
contribution
> in
> > the mailing list "tomcat-user".
> >
> > Is my problem very complex ? Is a Bug ?
> >
> > To store a group of "special" classes , out of the standard class
directoy
> > of the WebApps ("WEF-INF/classes"), I try to write a custom
> > WebAppClassLoader, but tomcat cant load it at startup !
> >
>
> That's because any other location in the webapp violates the servlet spec.
>
> > I do'nt want to copy these "special" classes in the class directory of
the
> > webApps because they are dynamicly generated with the design tool of an
> > "ERP" and shared by multiple webapps.
> >
> > My classLoader is stored in a jar file in the lib directory of each
> WebApp.
> > Example:
> >
>
"£CATALINA_HOME\SERVERS_BASE\webapps_x3\WAWEBSERVER\WEB-INF\lib\WAWEBSERVER.
> > jar"
> >
> >
> > But Catalina delivers me an error at each startup :
> > java.lang.ClassNotFoundException
> >
> > At this time the context of my webApp "WAWEBSERVER"  does'nt exist ?
> >
>
> Sounds like you don't have the appBase or docBase parameters in server.xml
> set up correctly.
>
> > Although I read information "Normally, application classes should NOT be
> > placed here" in the "how-to" of the tomcat's classloader, I tried to
place
> > my classes in a jar file located in the directory
> > "$CATALINA_HOME/common/lib" so that they are visible for catalina, but
> that
> > does not run either!
> >
>
> The set of classes here is identified when Tomcat starts up, so you'll
> need to restart Tomcat after adding new ones.
>
> > Where must I store my custom WebAppClassLoader classes ?
> >
>
> Classes that need to be visible to the internals of Tomcat have to go in
> server/classes or server/lib.
>
> But I *strongly* advise you to give choose an alternative approach --
> building a custom class loader solution like this is going to tie you not
> only to Tomcat, but to a specific version of Tomcat.  You get no promises
> that the class loading architecture will stay constant (that is an
> internal detail), so you will have to re-implement your solution on every
> future version.
>
> Craig
>
>
>
> > See behind the details of what I did and how is configured my platform.
> >
> > Thanks a lot in advance.
> >
> > Best regards
> >
> > Olivier Gattaz
> > ---------------------------------------------------------
> > Adonix - 5 avenue Victor Hugo - 38130 Echirolles - France
> >
> >
> > 1) I created the two classes :
> > ------------------------------
> > - "com.adonix.x3.x3web.tomcat.loader.CAdapiLoader"
> >     public class CAdapiLoader extends WebappLoader
> >     {
> >       ...
> >     }
> > - "com.adonix.x3.x3web.tomcat.loader.CAdapiClassLoader"
> >     public class CAdapiClassLoader extends WebappClassLoader
> >     {
> >       ...
> >     }
> >
> >
> > ## 2) I store these classes in a Jar file :
> > -------------------------------------------
> >
>
£CATALINA_HOME\SERVERS_BASE\webapps_x3\WAWEBSERVER\WEB-INF\lib\WAWEBSERVER.j
> > ar
> >
> >
> > ## 3) I defined a "Loader" tag in the "context" of my WebApp :
> > --------------------------------------------------------------
> > <Context path="/x3webgarp"
> >   docBase="C:\Program
> > files\Adonix\X3Web\SERVERS_BASE\webapps_x3\WAWEBSERVER"
> >   debug="0"
> >   reloadable="false">
> >   <Loader className="com.adonix.x3.x3web.tomcat.loader.CX3WebLoader"
> >      delegate="false"
> >      reloadable="false"
> >      checkInterval="15"
> >      debug="9"
> >      loaderClass="com.adonix.x3.x3web.tomcat.loader.CX3WebClassLoader"
> >      AdapiClassPath="D:\Adonix\X3Web\Data\X3Classes" />
> > </Context>
> >
> > ## 4) When Tomcat start, I always get the error message in the output :
> > -----------------------------------------------------------------------
> > ERROR reading C:\Program files\Adonix\X3Web\SERVERS_BASE\conf\server.xml
> > At Line 217 /Server/Service/Engine/Host/Context/Loader/
> > className=com.adonix.x3.x3web.tomcat.loader.CX3WebLoader delegate=false
> > reloadable=false checkInterval=15 debug=9
> > loaderClass=com.adonix.x3.x3web.tomcat.loader.CX3WebClassLoader
> > Catalina.start:
> >
>
java.lang.ClassNotFoundException:com.adonix.x3.x3web.tomcat.loader.CX3WebLoa
> > der
> >
> >
> > ## 5) The configuration of my plaform :
> > ---------------------------------------
> > - W2000 SP2
> > - Apache httpd 2.0.39 + Mod_jk
> > - Sun JDK 1.3.1_03
> > - Tomcat 4.0.4 running like a service and configured for
> >   multiple instances by setting $CATALINA_BASE
> >   - set CATALINA_LOG=D:\Adonix\X3Web\data\SERVERSLOGS\TOMCAT
> >   - set CATALINA_HOME=C:\Program Files\Apache Tomcat 4.0
> >   - set CATALINA_BASE=C:\Program files\Adonix\X3Web\SERVERS_BASE
> >   - set JAVA_HOME=C:\jdk1.3.1_03
> >
> >
> > NOTE: although I set $CATALINA_BASE different of $CATALINA_HOME, the
> > directory $CATALINA_BASE/common/lib is ignored !
> >
> >
> >
> >
> >
> > Olivier Gattaz
> > Adonix - 5 avenue Victor Hugo - 38130 Echirolles - France
> >
>


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to