Hi all, as I've a requirement to maintain long lived sessions (~120s) I'm using tomcat's PersistentManager to avoid keeping lots of sessions in memory, each one with its own lastPage. I'm observing, specially in a heavy loaded production environment, permanent errors with a trace like
Nov 19, 2008 1:56:20 AM org.apache.catalina.session.StoreBase processExpires SEVERE: Session: 115F3CD5A33E7D941AF8971FA62DE270; java.lang.IllegalArgumentException: Unknown object type null at org.apache.wicket.protocol.http.pagestore.DiskPageStore.restoreAfterSerialization(DiskPageStore.java:1214) at org.apache.wicket.protocol.http.SecondLevelCacheSessionStore$SecondLevelCachePageMap.readObject(SecondLevelCacheSessionStore.java:409) at sun.reflect.GeneratedMethodAccessor85.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351) at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1441) at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:942) at org.apache.catalina.session.FileStore.load(FileStore.java:296) at org.apache.catalina.session.StoreBase.processExpires(StoreBase.java:195) at org.apache.catalina.session.PersistentManagerBase.processExpires(PersistentManagerBase.java:553) at org.apache.catalina.session.ManagerBase.backgroundProcess(ManagerBase.java:667) I've managed myself to reproduced this error in a more controlled environment and I discovered that tomcat's manager background thread is swapping out the session at a moment where lastPage == null. SecondLevelCacheSessionStore$SecondLevelCachePageMap [line: 380] if (sessionId != null && store instanceof IClusteredPageStore == false) { Object page = lastPage; if (store instanceof ISerializationAwarePageStore) <--- conditional breakpoint if page == null { Daemon Thread [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (Suspended (breakpoint at line 380 in SecondLevelCacheSessionStore$SecondLevelCachePageMap)) SecondLevelCacheSessionStore$SecondLevelCachePageMap.writeObject(ObjectOutputStream) line: 380 GeneratedMethodAccessor139.invoke(Object, Object[]) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25 Method.invoke(Object, Object...) line: 597 ObjectStreamClass.invokeWriteObject(Object, ObjectOutputStream) line: 945 ObjectOutputStream.writeSerialData(Object, ObjectStreamClass) line: 1461 ObjectOutputStream.writeOrdinaryObject(Object, ObjectStreamClass, boolean) line: 1392 ObjectOutputStream.writeObject0(Object, boolean) line: 1150 ObjectOutputStream.writeObject(Object) line: 326 StandardSession.writeObject(ObjectOutputStream) line: 1517 StandardSession.writeObjectData(ObjectOutputStream) line: 959 FileStore.save(Session) line: 372 PersistentManager(PersistentManagerBase).writeSession(Session) line: 868 PersistentManager(PersistentManagerBase).swapOut(Session) line: 839 PersistentManager(PersistentManagerBase).processMaxIdleSwaps() line: 1058 PersistentManager(PersistentManagerBase).processPersistenceChecks() line: 570 PersistentManager(PersistentManagerBase).processExpires() line: 551 PersistentManager(ManagerBase).backgroundProcess() line: 667 StandardContext(ContainerBase).backgroundProcess() line: 1316 ContainerBase$ContainerBackgroundProcessor.processChildren(Container, ClassLoader) line: 1601 ContainerBase$ContainerBackgroundProcessor.processChildren(Container, ClassLoader) line: 1610 ContainerBase$ContainerBackgroundProcessor.processChildren(Container, ClassLoader) line: 1610 ContainerBase$ContainerBackgroundProcessor.run() line: 1590 Thread.run() line: 619 I've configured a minIdleTime of 120 seconds so I don't think tomcat swaps the session out while it's still being accessed, in an invalid intermediate state. The code for processMaxIdleSwaps looks fine: protected void processMaxIdleSwaps() { if (!isStarted() || maxIdleSwap < 0) return; Session sessions[] = findSessions(); long timeNow = System.currentTimeMillis(); // Swap out all sessions idle longer than maxIdleSwap if (maxIdleSwap >= 0) { for (int i = 0; i < sessions.length; i++) { StandardSession session = (StandardSession) sessions[i]; synchronized (session) { if (!session.isValid()) continue; int timeIdle = // Truncate, do not round up (int) ((timeNow - session.getLastAccessedTime()) / 1000L); if (timeIdle > maxIdleSwap && timeIdle > minIdleSwap) { if (log.isDebugEnabled()) log.debug(sm.getString ("persistentManager.swapMaxIdle", session.getIdInternal(), new Integer(timeIdle))); try { swapOut(session); } catch (IOException e) { ; // This is logged in writeSession() } } } } } } Do you have any idea why lastPage could be null so many times (as an important percentage -about 10%- of the sessions throws the above error) ? Take into account that a big number of bots and crawlers is accessing the site. Any help will be very appreciated, I've spent many hours and days tracing this issue... Best regards -Carlos --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]