Community
Participate
Working Groups
Build Identifier: 8.1.0.v20120127 2012-02-01 15:18:51.873:WARN:oejnm.MongoSessionManager: java.lang.ClassNotFoundException: com.i3analytics.maps.SomeMap at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:603) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1574) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350) at org.eclipse.jetty.nosql.mongodb.MongoSessionManager.decodeValue(MongoSessionManager.java:447) at org.eclipse.jetty.nosql.mongodb.MongoSessionManager.loadSession(MongoSessionManager.java:318) at org.eclipse.jetty.nosql.NoSqlSessionManager.getSession(NoSqlSessionManager.java:68) at org.eclipse.jetty.server.session.AbstractSessionManager.getHttpSession(AbstractSessionManager.java:270) at org.eclipse.jetty.server.session.SessionHandler.checkRequestedSessionId(SessionHandler.java:277) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:158) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:907) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110) at org.eclipse.jetty.server.Server.handle(Server.java:346) at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:442) at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:924) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:582) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:218) at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:51) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:586) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:44) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533) at java.lang.Thread.run(Thread.java:662) The ObjectInputStream is using the classloader of the MongoSessionHandler which won't have access to classes in my war (com.i3analytics.*). Reproducible: Always Steps to Reproduce: 1. Configure jetty to use mongoDb session clustering 2. Place an instance of a class, that exists only in the war, into the session 3. Bounce the container 4. Upon call of the loadSession of the MongoSessionHandler on the client accessing the server again, ClassNotFound exception is thrown. Also, noted in this stackoverflow: http://stackoverflow.com/questions/9066844/jetty-nosql-mongosessionmanager-usage-on-heroku Potential Fix: Following the code in the JDBCSessionManager (copy-paste) I created a ClassLoadingObjectInputStream. I changed line 446 to: ClassLoadingObjectInputStream in = new ClassLoadingObjectInputStream(new ByteArrayInputStream((byte[])value)); And the situation was resolved, objects were de-serialized. I am seeing another issue now though, that the objects de-serialized don't line up the byte arrays I am getting from the DBObject attr's map of values. I'm tracing through that now.
The other problem I am seeing I just pinned down to the ByteArrayOutputStream and ObjectOutputStream being passed around as parameters to the encodeName method. Even when the reset is called the objects saved into mongodb do not deserialize back into the class that the byte array is supposed to represent. My change is: Line 408: From: protected Object encodeName(ObjectOutputStream out, ByteArrayOutputStream bout, Object value) throws IOException To: protected Object encodeName(Object value) throws IOException Line 424: From: o.append(encodeName(entry.getKey().toString()),encodeName(out,bout,entry.getValue())); To: o.append(encodeName(entry.getKey().toString()),encodeName(entry.getValue())); And then on Line 431, I instantiated a fresh set of outputstreams: ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bout); Now the classes going into mongodb are the same when they come out.
Created attachment 210443 [details] Patch generated against the 8.1.0.v20120127 tag AFTER change in bug 370368 Here is a patch that contains both fix for issue describe in title of this ticket and the change to use of newly instantiated output streams per call to encode.
Applied, thanks much. Since your on a roll I figured I would link you this: http://wiki.eclipse.org/Jetty/Contributor/Contributing_Patches It makes the easiest to apply patches and gives you credit within our git system. Gerrit is fast approaching as well. :) anyway, much appreciate the contributions!