Bo Xu wrote:
>
> Andrey Myatlyuk wrote:
>
> > Hello Vladimir,
> >
> > Thank you for your help.
> >
> > And I'm still have some questions.
> >
> > Why do we need to implement "some interface"? java.io.Serializable I
> > think? But anyway I implemented this interface - it doesn't work. This
> > approach works for EJB. :)
> >
> > And my question is: Is there any way to use "some shared" object with
> > reloadable servlets without Tomcat restart?
> >
> > Thanks.
> >
After reading this message and some thinking I can say that the problem is
harder than I thought. There's no way to trick it, at least there's no interface
you can create/implement to fix it... And of course it wasn't the Serializable
one...
Sorry, for misleading... But... what about this:
Object _statesBean =
getServletContext().getAttribute(StatesBean.STATES_BEAN_NAME);
Class sBeanClazz = _statesBean.getClass();
Method m = sBeanClazz.getMethod("foo", new Class[] {/*args*/});
m.invoke(_statesBean, new Object{ /*params*/ });
he-he, ugly :) Not sure if it'll work...
Regards,
VG.
> > Wednesday, March 14, 2001, 3:16:45 PM, you wrote:
> >
> > VG> I think you're experiencing a standard Java class loader problem.
> > VG> Java treats classes loaded into different classloaders as different
> > VG> classes, even though they share the same full. qual. name.
> > VG> Your recompiled servlets are reloaded by a brand new class loader
> > VG> to make sure the old classes are garbage collected. What you get
> > VG> from the context is actuially an instance of a class loaded into
> > VG> a different classloader, and (StatesBean) part in your statement
> > VG> causes StatesBean to be loaded again by this new classloader that
> > VG> reloaded your servlet, so
> > VG> VM complains that you cannot cast objects since it thinks they
> > VG> are instances of 2 completely different classes. No matter where
> > VG> you place your files you'll have the same problem.
> >
> > VG> You can avoid this problem by writing some extra code and have your
> > VG> bean to implement some interface.... Extra work, just restart
> > VG> Tomcat every time...
> >
> > VG> Regards,
> > VG> VG.
> >
> > VG> Andrey Myatlyuk wrote:
> > >>
> > >> Hello Tomcat users,
> > >>
> > >> I'm in a trouble. I share some object(StatesBean) between servlets. And when I
> > >> recompile _servlet_, I got ClassCastException about shared object.
> > >>
> > >> _statesBean=
> > >> (StatesBean)getServletContext().getAttribute(StatesBean.STATES_BEAN_NAME);
> > >>
> > >>
> > >> Classfile for this object is placed in the same directory, where
> > >> servlets do - web-inf/classes. Where I need to place classfile for
> > >> this object to prevent Tomcat exceptions?
> > >>
> > >> Of course, if I reload Tomcat everything is OK.
> > >>
> > >> Thank you in advance!
> > >>
> > >> --
> > >> Best regards,
> > >> Andrey mailto:[EMAIL PROTECTED]
> > [...]
>
> Hi :-) I am not sure, I guess:
> * perhaps the problem is:
> - let use suppose: classloaderA -> classA -> instanceA
> then you "setAttribute" instanceA into ServletContext of
> this wepapp, so now ServletContext holds a reference to
> instanceA.
> - after a while, your Sevlet class is reloaded, with
> jakarta-tomcat-4.0-b1, now classloaderA is not there,
> so classA is not there, But instanceA is there: because
> at least there is One reference of instanceA is being holded
> by ServletContext, so it will not be GCed, and getAttribute()
> will not return null.
> - but now instanceA doesn't has "its original class" and "its
> original classloader", I am not sure, but I guess perhaps it is
> the reason.
>
> * IMHO, I guess: if you can find a way to load classA from a
> special classloader which will not be destroyed when/even if
> your Servlet class is reloaded, then you can solve the problem.
> It means that our Servlet class and some Helper classes are
> loaded by several classloaders in "diferent layer". if we don't
> want to keep a Attribute "across Servlet reloading", perhaps
> we don't need to it; but if we want, and we are sure that the
> "webapp classloader" will be destroyed and re-made, than I
> guess perhaps we have to use classloaders which are in
> "diferent layer".
>
> * the following is a good email about the classloader:
>
> //************ <good email> ************************
> On Sat, 10 Mar 2001, David Wall wrote:
>
> > There appears to be a serious problem with the classpath/classloader with
> > Tomcat 3.2.1.
> >
> > It may be related to the Jasper engine, which outputs a dynamic classpath
> > name that includes all of the classes and jars in the WEB-INF directory, as
> > expected. But is the same classloader used when servlets are loaded at
> > startup according to the web.xml file?
> >
>
> The same class loader is used to load all classes within a particular web
> application, but there is more to the story than that. See below.
>
> > Anyway, I'm not sure where the problem resides, but I have found that by
> > setting the CLASSPATH to the same thing Jasper sets up (specifically those
> > files in WEB-INF/classes and WEB-INF/lib), my beans will no longer complain
> > about unknown classes.
> >
> > But unfortunately, this "fix" doesn't really work because apparently they
> > really are loaded by different classloaders, so they are not the same
> > classes within the JVM. This causes problems for classes that appear to
> > have been initialized, but then magically are not when loaded through the
> > other classloader.
> >
>
> The most common cause for this is actually a developer error. Before
> explaining how this can be true, let's look a little at how class loading
> actually works in Tomcat (the details do ***not*** necessarily apply to
> any other servlet container, because standard behavior is not specified).
>
> There is actually a hierarchy of class loaders created when Tomcat is
> running:
> - Bootstrap class loader (Java system classes)
> - Extensions class loader (JAR files from $JAVA_HOME/jre/lib/ext)
> - System class loader (contents of CLASSPATH at startup time)
> - Webapp class loader (contents of WEB-INF/classes and WEB-INF/lib
> for your particular web application)
>
> Now, when your servlet class is loaded, Tomcat asks the webapp class
> loader to load it. Following the standard Java delegation model, the web
> app class loader first asks it's parent class loader to try to find the
> class -- and so on up the hierarchy. If your servlet class is actually in
> WEB-INF/classes or WEB-INF/lib, all of these attempts to delegate upwards
> will fail. Therefore, the web app class loader will load the class
> itself.
>
> The same thing happens for every other class that your servlet references
> -- it gets loaded by whichever class loader finds that class. If the load
> happens from a class loader *above* the calling class's class loader, that
> is fine. However, trouble occurs if you try the opposite direction,
> because there are no links *downward* in the class loader hierarchy.
>
> Consider what happens if you put your servlet class into $TOMCAT_HOME/lib
> (so that it gets added to the system class loader at startup time). When
> you reference the servlet, it gets loaded by the system class loader --
> not the web app class loader. So, if it tries to refer to a JavaBean
> class you have stored in WEB-INF/classes or WEB-INF/lib. What
> happens? You've got it: ClassNotFoundException. Because the servlet was
> loaded from the system class loader, it can only look *up* the hierarchy
> rather than *down*.
>
> > Anyway, is there anybody looking into this? I know I've seen several
> > postings complaining about classpath problems that are likely related to
> > this. Has it been fixed in 3.2.2?
> >
>
> The moral of the story is that you should follow the following steps to
> completely avoid class loading problems in your web apps, and guarantee
> that your apps will be portable to other servlet containers:
>
> * Do not rely on system extensions in $JAVA_HOME/jre/lib/ext. If you
> do, those classes are *not* allowed to reference any classes on the
> system class path, or inside your web application.
>
> * Do not rely on adding classes onto your CLASSPATH (or putting them in
> $TOMCAT_HOME/lib) before starting Tomcat. Such classes will have
> problems with downward references, as described above. Also, support
> for shared library classes is ***not*** required by the servlet spec,
> so you cannot count on this facility in a portable app.
>
> * Put all classes your application needs into WEB-INF/classes, or
> in JAR files unde WEB-INF/lib. In this way, they will all be loaded
> by the same class loader and not have any referencing problems.
>
> There are other specific issues with specific libraries, and there are
> some changes in how class loading works in Tomcat 4.0, but the above
> outline identifies what to do about the majority of class loading issues
> in servlet containers.
>
> > Thanks,
> > David
> >
>
> Craig McClanahan
>
> //************ </good email> ************************
>
> Bo ^_^
> Mar.14, 2001