You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Nicolas De Loof <ni...@cgey.com> on 2004/01/15 15:26:50 UTC

[OT] Classloader troubles

Hi all,

I'm posting on Struts list because I know they're is lot's of J2EE experts here.

I want to test my webapp on Tomcat, but it depends on some external system. I've got a jar that emulates it. When I
package it with the webapp (WEB-INF/lib) it works fine.

I would like to test the webapp packaged without this emulator jar. I tried putting it in $TOMCAT/common/lib. I get a
ClassCastException. I think it comes from this :

webapp requires the external API, let's say a class named "ExternalSystem". It is configured to search for an
implementation class named "ExternalSystemMockImpl" (using reflexion API).

Webapp classloader doesn't find it, and delegate class searh to it's parent classloader (tomcat ones). Parent
classloader finds the class from my emulator jar, run it and return some "MockResult" object, that implements
"ExternalResult" from the external API

Calling webapp tries to cast resulting object to "ExternalResult", class that is visible to webapp classloader.

Then my code is doing :

ExternalResult result = (ExternalResult) obj;

where obj is my MockResult instance, that implements ExternalResult from parent-Classloader, and casting it to a
webapp-Classloader ExternalResult fails !


How can I solve this ClasLoader conflict ?

Nico.


---------------------------------------------------------------------
To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-user-help@jakarta.apache.org


Re: [OT] Classloader troubles

Posted by Nicolas De Loof <ni...@cgey.com>.
Api is in a separate jar (api.jar) that is both in webapp & commons :
when I don't put it in commons, I get a NoClassDefFoundError from line (1) :

    Class clazz = Class.forName(className);

I can't exclude it from webapp (WEB-INF/lib) as it is part of webapp with the production implementation jar.

I need some way to force ClassLoading to search webapp first, even when it delegates a class search to commons
ClassLoader. Perhaps they're is no solution...

Nico.


> Where is the JAR file that contains IExternalSystem?
>
> Quoting Nicolas De Loof <ni...@cgey.com>:
>
> > the webapp hasn't trouble to load ExternalSystemMockImpl. It uses reflexion
> > to do it from some configuration data that
> > is use to set implementation (production | mock).
> >
> > The problem is that the resulting object has to be casted to an interface
> > from the API : IExternalSystem:
> >
> > (1)    Class clazz = Class.forName(className);
> > (2)    return (IExternalSystem) clazz.newInstance();
> >
> > from webapp, I think IExternalSystem is loaded by webapp ClassLoader. As
> > ExternalSystemMockImpl is loaded from tomcat
> > "commons" ClassLoader, it doesn implements the IExternalSystem loaded by this
> > commons-ClassLoader, that cannot be casted
> > in IExternalSystem  loaded by webapp-ClassLoader.
> >
> > I get a ClassCastException on line 2.
> >
> > Nico.
> >
> >
> >
> > > If ExternalSystemMockImpl is contained in a JAR file that's in
> > > $CATALINA_HOME/common/lib, I don't see why the app wouldn't be able to load
> > it.
> > > For example, I've got a JAR file for the Oracle JDBC driver in common/lib
> > and I
> > > can do the following just fine in a JSP:
> > >
> > > <%
> > > ClassLoader cl = getClass().getClassLoader();
> > > Class clazz = cl.loadClass("oracle.jdbc.OracleDriver");
> > > Object obj = clazz.newInstance();
> > > %>
> > >
> > > If there's code in the external JAR file that needs to make use of a
> > class
> > > loader, it should probably use the result of
> > > Thread.currentThread().getContextClassLoader(). Can you provide a little
> > more
> > > detail on how the app is using reflection to locate
> > ExternalSystemMockImpl?
> > >
> > > Quoting Nicolas De Loof <ni...@cgey.com>:
> > >
> > > > Hi all,
> > > >
> > > > I'm posting on Struts list because I know they're is lot's of J2EE
> > experts
> > > > here.
> > > >
> > > > I want to test my webapp on Tomcat, but it depends on some external
> > system.
> > > > I've got a jar that emulates it. When I
> > > > package it with the webapp (WEB-INF/lib) it works fine.
> > > >
> > > > I would like to test the webapp packaged without this emulator jar. I
> > tried
> > > > putting it in $TOMCAT/common/lib. I get a
> > > > ClassCastException. I think it comes from this :
> > > >
> > > > webapp requires the external API, let's say a class named
> > "ExternalSystem".
> > > > It is configured to search for an
> > > > implementation class named "ExternalSystemMockImpl" (using reflexion
> > API).
> > > >
> > > > Webapp classloader doesn't find it, and delegate class searh to it's
> > parent
> > > > classloader (tomcat ones). Parent
> > > > classloader finds the class from my emulator jar, run it and return
> > some
> > > > "MockResult" object, that implements
> > > > "ExternalResult" from the external API
> > > >
> > > > Calling webapp tries to cast resulting object to "ExternalResult", class
> > that
> > > > is visible to webapp classloader.
> > > >
> > > > Then my code is doing :
> > > >
> > > > ExternalResult result = (ExternalResult) obj;
> > > >
> > > > where obj is my MockResult instance, that implements ExternalResult
> > from
> > > > parent-Classloader, and casting it to a
> > > > webapp-Classloader ExternalResult fails !
> > > >
> > > >
> > > > How can I solve this ClasLoader conflict ?
> > > >
> > > > Nico.
> > >
> > > -- 
> > > Kris Schneider <ma...@dotech.com>
> > > D.O.Tech       <http://www.dotech.com/>
>
> -- 
> Kris Schneider <ma...@dotech.com>
> D.O.Tech       <http://www.dotech.com/>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: struts-user-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-user-help@jakarta.apache.org


Re: [OT] Classloader troubles

Posted by Kris Schneider <kr...@dotech.com>.
Where is the JAR file that contains IExternalSystem?

Quoting Nicolas De Loof <ni...@cgey.com>:

> the webapp hasn't trouble to load ExternalSystemMockImpl. It uses reflexion
> to do it from some configuration data that
> is use to set implementation (production | mock).
> 
> The problem is that the resulting object has to be casted to an interface
> from the API : IExternalSystem:
> 
> (1)    Class clazz = Class.forName(className);
> (2)    return (IExternalSystem) clazz.newInstance();
> 
> from webapp, I think IExternalSystem is loaded by webapp ClassLoader. As
> ExternalSystemMockImpl is loaded from tomcat
> "commons" ClassLoader, it doesn implements the IExternalSystem loaded by this
> commons-ClassLoader, that cannot be casted
> in IExternalSystem  loaded by webapp-ClassLoader.
> 
> I get a ClassCastException on line 2.
> 
> Nico.
> 
> 
> 
> > If ExternalSystemMockImpl is contained in a JAR file that's in
> > $CATALINA_HOME/common/lib, I don't see why the app wouldn't be able to load
> it.
> > For example, I've got a JAR file for the Oracle JDBC driver in common/lib
> and I
> > can do the following just fine in a JSP:
> >
> > <%
> > ClassLoader cl = getClass().getClassLoader();
> > Class clazz = cl.loadClass("oracle.jdbc.OracleDriver");
> > Object obj = clazz.newInstance();
> > %>
> >
> > If there's code in the external JAR file that needs to make use of a
> class
> > loader, it should probably use the result of
> > Thread.currentThread().getContextClassLoader(). Can you provide a little
> more
> > detail on how the app is using reflection to locate
> ExternalSystemMockImpl?
> >
> > Quoting Nicolas De Loof <ni...@cgey.com>:
> >
> > > Hi all,
> > >
> > > I'm posting on Struts list because I know they're is lot's of J2EE
> experts
> > > here.
> > >
> > > I want to test my webapp on Tomcat, but it depends on some external
> system.
> > > I've got a jar that emulates it. When I
> > > package it with the webapp (WEB-INF/lib) it works fine.
> > >
> > > I would like to test the webapp packaged without this emulator jar. I
> tried
> > > putting it in $TOMCAT/common/lib. I get a
> > > ClassCastException. I think it comes from this :
> > >
> > > webapp requires the external API, let's say a class named
> "ExternalSystem".
> > > It is configured to search for an
> > > implementation class named "ExternalSystemMockImpl" (using reflexion
> API).
> > >
> > > Webapp classloader doesn't find it, and delegate class searh to it's
> parent
> > > classloader (tomcat ones). Parent
> > > classloader finds the class from my emulator jar, run it and return
> some
> > > "MockResult" object, that implements
> > > "ExternalResult" from the external API
> > >
> > > Calling webapp tries to cast resulting object to "ExternalResult", class
> that
> > > is visible to webapp classloader.
> > >
> > > Then my code is doing :
> > >
> > > ExternalResult result = (ExternalResult) obj;
> > >
> > > where obj is my MockResult instance, that implements ExternalResult
> from
> > > parent-Classloader, and casting it to a
> > > webapp-Classloader ExternalResult fails !
> > >
> > >
> > > How can I solve this ClasLoader conflict ?
> > >
> > > Nico.
> >
> > -- 
> > Kris Schneider <ma...@dotech.com>
> > D.O.Tech       <http://www.dotech.com/>

-- 
Kris Schneider <ma...@dotech.com>
D.O.Tech       <http://www.dotech.com/>

---------------------------------------------------------------------
To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-user-help@jakarta.apache.org


Re: [OT] Classloader troubles

Posted by Nicolas De Loof <ni...@cgey.com>.
the webapp hasn't trouble to load ExternalSystemMockImpl. It uses reflexion to do it from some configuration data that
is use to set implementation (production | mock).

The problem is that the resulting object has to be casted to an interface from the API : IExternalSystem:

(1)    Class clazz = Class.forName(className);
(2)    return (IExternalSystem) clazz.newInstance();

from webapp, I think IExternalSystem is loaded by webapp ClassLoader. As ExternalSystemMockImpl is loaded from tomcat
"commons" ClassLoader, it doesn implements the IExternalSystem loaded by this commons-ClassLoader, that cannot be casted
in IExternalSystem  loaded by webapp-ClassLoader.

I get a ClassCastException on line 2.

Nico.



> If ExternalSystemMockImpl is contained in a JAR file that's in
> $CATALINA_HOME/common/lib, I don't see why the app wouldn't be able to load it.
> For example, I've got a JAR file for the Oracle JDBC driver in common/lib and I
> can do the following just fine in a JSP:
>
> <%
> ClassLoader cl = getClass().getClassLoader();
> Class clazz = cl.loadClass("oracle.jdbc.OracleDriver");
> Object obj = clazz.newInstance();
> %>
>
> If there's code in the external JAR file that needs to make use of a class
> loader, it should probably use the result of
> Thread.currentThread().getContextClassLoader(). Can you provide a little more
> detail on how the app is using reflection to locate ExternalSystemMockImpl?
>
> Quoting Nicolas De Loof <ni...@cgey.com>:
>
> > Hi all,
> >
> > I'm posting on Struts list because I know they're is lot's of J2EE experts
> > here.
> >
> > I want to test my webapp on Tomcat, but it depends on some external system.
> > I've got a jar that emulates it. When I
> > package it with the webapp (WEB-INF/lib) it works fine.
> >
> > I would like to test the webapp packaged without this emulator jar. I tried
> > putting it in $TOMCAT/common/lib. I get a
> > ClassCastException. I think it comes from this :
> >
> > webapp requires the external API, let's say a class named "ExternalSystem".
> > It is configured to search for an
> > implementation class named "ExternalSystemMockImpl" (using reflexion API).
> >
> > Webapp classloader doesn't find it, and delegate class searh to it's parent
> > classloader (tomcat ones). Parent
> > classloader finds the class from my emulator jar, run it and return some
> > "MockResult" object, that implements
> > "ExternalResult" from the external API
> >
> > Calling webapp tries to cast resulting object to "ExternalResult", class that
> > is visible to webapp classloader.
> >
> > Then my code is doing :
> >
> > ExternalResult result = (ExternalResult) obj;
> >
> > where obj is my MockResult instance, that implements ExternalResult from
> > parent-Classloader, and casting it to a
> > webapp-Classloader ExternalResult fails !
> >
> >
> > How can I solve this ClasLoader conflict ?
> >
> > Nico.
>
> -- 
> Kris Schneider <ma...@dotech.com>
> D.O.Tech       <http://www.dotech.com/>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: struts-user-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-user-help@jakarta.apache.org


Re: [OT] Classloader troubles

Posted by Kris Schneider <kr...@dotech.com>.
If ExternalSystemMockImpl is contained in a JAR file that's in
$CATALINA_HOME/common/lib, I don't see why the app wouldn't be able to load it.
For example, I've got a JAR file for the Oracle JDBC driver in common/lib and I
can do the following just fine in a JSP:

<%
ClassLoader cl = getClass().getClassLoader();
Class clazz = cl.loadClass("oracle.jdbc.OracleDriver");
Object obj = clazz.newInstance();
%>

If there's code in the external JAR file that needs to make use of a class
loader, it should probably use the result of
Thread.currentThread().getContextClassLoader(). Can you provide a little more
detail on how the app is using reflection to locate ExternalSystemMockImpl?

Quoting Nicolas De Loof <ni...@cgey.com>:

> Hi all,
> 
> I'm posting on Struts list because I know they're is lot's of J2EE experts
> here.
> 
> I want to test my webapp on Tomcat, but it depends on some external system.
> I've got a jar that emulates it. When I
> package it with the webapp (WEB-INF/lib) it works fine.
> 
> I would like to test the webapp packaged without this emulator jar. I tried
> putting it in $TOMCAT/common/lib. I get a
> ClassCastException. I think it comes from this :
> 
> webapp requires the external API, let's say a class named "ExternalSystem".
> It is configured to search for an
> implementation class named "ExternalSystemMockImpl" (using reflexion API).
> 
> Webapp classloader doesn't find it, and delegate class searh to it's parent
> classloader (tomcat ones). Parent
> classloader finds the class from my emulator jar, run it and return some
> "MockResult" object, that implements
> "ExternalResult" from the external API
> 
> Calling webapp tries to cast resulting object to "ExternalResult", class that
> is visible to webapp classloader.
> 
> Then my code is doing :
> 
> ExternalResult result = (ExternalResult) obj;
> 
> where obj is my MockResult instance, that implements ExternalResult from
> parent-Classloader, and casting it to a
> webapp-Classloader ExternalResult fails !
> 
> 
> How can I solve this ClasLoader conflict ?
> 
> Nico.

-- 
Kris Schneider <ma...@dotech.com>
D.O.Tech       <http://www.dotech.com/>

---------------------------------------------------------------------
To unsubscribe, e-mail: struts-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: struts-user-help@jakarta.apache.org