ClassNotFoundException destroying a session in Tomcat
When a session was being expired (either through a timeout, or via using the Tomcat Manager to manually destroy them) that contained an EJB I was getting a ClassNotFoundException. The stack trace when killing from the manager was:
java.lang.RuntimeException: Specified calling class, net.devgrok.MyEjbRemote could not be found for WebappClassLoader delegate: false repositories: ----------> Parent Classloader: org.apache.catalina.loader.StandardClassLoader@70cb6009 at org.jboss.ejb3.common.lang.SerializableMethod.getClassFromName(SerializableMethod.java:311) at org.jboss.ejb3.common.lang.SerializableMethod.getClassType(SerializableMethod.java:282) at org.jboss.ejb3.common.lang.SerializableMethod.toMethod(SerializableMethod.java:233) at org.jboss.ejb3.common.lang.SerializableMethod.toMethod(SerializableMethod.java:220) at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java:182) at org.jboss.ejb3.proxy.impl.handler.session.SessionProxyInvocationHandlerBase.invoke(SessionProxyInvocationHandlerBase.java:164) at net.devgrok.JndiRemoteProxyInvocationHandler.invoke(JndiRemoteProxyInvocationHandler.java:55) at $Proxy15.logout(Unknown Source) at org.apache.catalina.session.StandardSession.expire(StandardSession.java:702) at org.apache.catalina.session.StandardSession.expire(StandardSession.java:660) at org.apache.catalina.session.StandardSession.invalidate(StandardSession.java:1113) at org.apache.catalina.session.StandardSessionFacade.invalidate(StandardSessionFacade.java:150) at org.apache.catalina.manager.HTMLManagerServlet.invalidateSessions(HTMLManagerServlet.java:822) at org.apache.catalina.manager.HTMLManagerServlet.doSessions(HTMLManagerServlet.java:690) at org.apache.catalina.manager.HTMLManagerServlet.doGet(HTMLManagerServlet.java:128) at org.apache.catalina.manager.HTMLManagerServlet.doPost(HTMLManagerServlet.java:164) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) ... at java.lang.Thread.run(Thread.java:619) Caused by: java.lang.ClassNotFoundException: net.devgrok.MyEjbRemote at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:247) at org.jboss.ejb3.common.classloader.PrimitiveAwareClassLoader.findClass(PrimitiveAwareClassLoader.java:105) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) at org.jboss.ejb3.common.lang.SerializableMethod.getClassFromName(SerializableMethod.java:307) ... 32 moreAfter some investigating I discovered the current thread's ClassLoader was incorrect. So I created a HttpSessionListener to swap the ClassLoader, unload the session and put the ClassLoader back.
public class SessionLifecycleEventListener implements HttpSessionListener { private static final Logger log = LoggerFactory.getLogger(SessionLifecycleEventListener.class); public void sessionDestroyed(HttpSessionEvent evt) { HttpSession session = evt.getSession(); //remember class loader ClassLoader currentLoad = Thread.currentThread().getContextClassLoader(); try { //set classloader to be the webapp's ClassLoader webApp = this.getClass().getClassLoader(); Thread.currentThread().setContextClassLoader(webApp); //clear all the session objects now Enumeration<String> names = session.getAttributeNames(); while (names.hasMoreElements()) { String name = names.nextElement(); session.removeAttribute(name); } } catch (RuntimeException e) { log.error("closeEjbSession caught exception", e); } finally { //restore classloader Thread.currentThread().setContextClassLoader(currentLoad); } public void sessionCreated(HttpSessionEvent evt) { } }
Comments
Post a Comment