Hi again Christopher,

thanks for your note and interest, some more details
inline...

On 01/23/2013 07:39 PM, Christopher Schultz wrote:
-----BEGIN PGP SIGNED MESSAGE-----

ObjectInputStream should be using the "context class loader" of the
thread which should be the WebappClassLoader.

Can you show us your code (the part that actually loads the bytes
into the ClassLoader to define the class)?
The byte[] arrives at the service as a Base64 string. Base64 to byte[]
is trivial and has been ruled out as a problem. The class type is loaded
using a custom ClassLoader (code as follows)

public class FileClassLoader extends java.lang.ClassLoader {
        public FileClassLoader(ClassLoader contextClassLoader) {
                super(contextClassLoader);
        }
        public synchronized Class<?> arrayToClass(String name, byte[] ct,
                        boolean resolve) {
                Class<?> c = defineClass(name, ct, 0, ct.length);
                try {
                        this.loadClass(c.getName(), resolve);
                } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                }
                return c;
        }
}

This is called by...
ClassLoader contextClassLoader =
Thread.currentThread().getContextClassLoader();
Class<?> spClass = cl.arrayToClass(null, byArray, True);

Also, where does the de-serialization occur? I suspect in the
webapp, but you haven't described everything in detail (and the
details count).
The problem is (was) deserializing an instance of such an object. Code
uses is as follows...

public Object Base64StringToObject(String str) {
   Object outObj = null;
   if (str != null) {
      try {
        ByteArrayInputStream bais = null;
        bais = new ByteArrayInputStream(Base64.decode(str));
        ObjectInputStream ois = new ObjectInputStream(bais);
        outObj = ois.readObject();
        } catch (IOException e) {
                e.printStackTrace();
                return null;
        } catch (ClassNotFoundException e) {
                e.printStackTrace();
                return null;
        }
        }
                return outObj;
        }

called by...
Object spB64Inst = su.Base64StringToObject(base64codeStrInstance);

In my service, I've loaded a full class definition and created an
instance of it. At this point it (afaik) must be in the cache of
the WebappClassLoader. However, when an ObjectInputStream is
called to... ois.readObject() on a byte[] of an instance of that
same class, it fail for ClassNotFoundException.

Hmm. Can you post the full stack trace of that CNFE?
Although the class (spClass) is now loaded in my custom class loader,
this fails, the CFNE is pasted at the very bottom of this note (for ease
of reading).

What works...
Using the code form this page...

http://www.jarvana.com/jarvana/view/org/apache/tomcat/tomcat-catalina/7.0.4/tomcat-catalina-7.0.4-sources.jar!/org/apache/catalina/util/CustomObjectInputStream.java?format=ok

And described here...
http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/util/CustomObjectInputStream.html

I implemented this in my application (i.e. not imported from a jar) and
use it like this (unchanged except for the package declaration)...

public Object Base64StringToObjectCustomOis(String str, ClassLoader cl) {
        Object outObj = null;
                if (str != null) {
                        try {
                        ByteArrayInputStream bais = null;
                        bais = new ByteArrayInputStream(Base64.decode(str));
                        CustomObjectInputStream cois = new 
CustomObjectInputStream(bais, cl);

  ///// next line is the main difference...

                outObj = cois.readObject();

                } catch (IOException e) {
                e.printStackTrace();
                return null;
        } catch (ClassNotFoundException e) {
                e.printStackTrace();
                return null;
                }
        }
        return outObj;
        }

And called like this... (cl same object as before)
Object spB64Inst =
su.Base64StringToObjectCustomOis(base64codeStrInstance,cl);

I've read (can't recall where) that the standard ObjectInputStream uses
a class loader of the JVM which may not have visiblilty on the WebappClassLoader due to the delegation model used by Tomcat. All the CustomObjectInputStream appears to do is to override one of the methods of OIS and pass a class loader, but in this case passes 'my' WebappClassLoader.

When I used this code, the problem went away.

FYI, (for reading the stacktrace), The class spClass is the type
definition for HelloWorldSP.java. The class in the application which is
running when this error happens is called FetchProfAbilities.java.

The object su in the above code refers to an instance of
SerializationUtilities (where the de/serialization takes place).

Please shout with any more questions. I appear to have overcome the
problem, but for my thesis, I would like to 'nail down' the root cause
of the problem (for academic reasons).

thanks again and best regards,
Peter






A Tomcat solution is identified here...
http://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/util/CustomObjectInputStream.html


I'm

surprised that class needs to exist... I would have expected OIS to
use the context class loader. I'll have to check on that.

Which is in $CATILANA_HOME/lib/catalina.jar.

Has anyone use this? do I need to add this jar implement this, and
include it in my war file?

You should be able to use that class directly from within
CATALINA_HOME/lib

- -chris -----BEGIN PGP SIGNATURE----- Version: GnuPG/MacGPG2 v2.0.17
(Darwin) Comment: GPGTools - http://gpgtools.org Comment: Using GnuPG
with Thunderbird - http://www.enigmail.net/

iEYEAREIAAYFAlEAPHcACgkQ9CaO5/Lv0PBzPgCbBrCdn8wrD/6YYPoYNpoht6s8
8vsAnifcwJCpAtLsZqc3SfncDY9QdF2k =wIKl -----END PGP SIGNATURE-----

---------------------------------------------------------------------


To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org


--
with best regards,
Peter Lavin,
PhD Candidate,
CAG - Computer Architecture & Grid Research Group,
Lloyd Institute, 005,
Trinity College Dublin, Ireland.
+353 1 8961536

CNFE...
java.lang.ClassNotFoundException: common.core.providers.HelloWorldSP
        at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1676)
        at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:264)
        at
java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:621)
        at
java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1592)
        at
java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1513)
        at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1749)
        at
java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368)
        at
common.utilities.SerializationUtilities.Base64StringToObject(SerializationUtilities.java:165)
        at
common.core.providers.FetchProfAbilitiesSP.ProcB64AddSimpleAct(FetchProfAbilitiesSP.java:786)
        at
common.core.providers.FetchProfAbilitiesSP.processUrl(FetchProfAbilitiesSP.java:272)
        at
common.core.providers.FetchProfAbilitiesSP.process(FetchProfAbilitiesSP.java:122)
        at common.core.ResourceManager.process(ResourceManager.java:172)
        at common.agents.SocialGridAgent.process(SocialGridAgent.java:110)
        at
org.sga.basicagent.AgentServiceImpl.process(AgentServiceImpl.java:45)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at
org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:173)
        at
org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:89)
        at
org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:61)
        at
org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:75)
        at
org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
        at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
        at java.util.concurrent.FutureTask.run(FutureTask.java:166)
        at
org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
        at
org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:106)
        at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
        at
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:118)
        at
org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:208)
        at
org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:223)
        at
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:205)
        at
org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:113)
        at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:184)
        at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:107)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
        at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:163)
        at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
        at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
        at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
        at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
        at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
        at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
        at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
        at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
        at
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
        at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
        at
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:182)
        at
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
        at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:679)


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to