Re: Bes practice for deployment to avoid ClassNotFoundException
Hi, You are experiencing Tomcat Session Persistence - http://tomcat.apache.org/tomcat-7.0-doc/config/manager.html#Persistence_Across_Restarts Just disable it for development to avoid such kind of problems. I'd also recommend to use Jetty for development if possible. It is much faster to restart. See src/test/java/.../Start.java in Wicket Quickstart. Martin Grigorov Wicket Training and Consulting https://twitter.com/mtgrigorov On Fri, Nov 21, 2014 at 6:22 PM, Thorsten Schöning tschoen...@am-soft.de wrote: Hi all, I'm new to wicket and just recently started to use it for a new web app for one of our projects. Today I came across a similar issue like described in [1], a ClassNotFoundException during deserialization of a page. The interesting part about this in my mind is, that the mentioned missing class was missing for a good reason: I simply refactored a bit and renamed the class, redeployed and restarted my Tomcat. This looks like a normal use case to me, but is something I didn't thought of when I've read through the docs because. My deployment is very simple: I check out a SVN working copy with a pre-configured tag containing the whole application once and afterwards just need to merge/update and stop/start the web server/app. How is deployment supposed to work in Wicket after I have refactored or otherwise changed my classes regarding cached and serialized pages? Is there anything I need to tell wicket to clear its caches on each deployment or ignore those or whatever? Am I forced to not delete once deployed classes for a fair period of time? That would be a litte nightmare... Or is there any other issue I ran into I should have avoided? Obviously others do deploy their Wicket apps as well, so I hope you have some input on how to avoid the problem I've ran into. Thanks! The important parts of the stacktrace: java.lang.ClassNotFoundException: de.am_soft.util.frontend.wicket.markup.link.LogoutLink at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at org.apache.wicket.application.AbstractClassResolver.resolveClass(AbstractClassResolver.java:108) at org.apache.wicket.serialize.java.JavaSerializer$ClassResolverObjectInputStream.resolveClass(JavaSerializer.java:218) at java.io.ObjectInputStream.[...] [...] at org.apache.wicket.serialize.java.JavaSerializer.deserialize(JavaSerializer.java:122) at org.apache.wicket.pageStore.DefaultPageStore.deserializePage(DefaultPageStore.java:396) at org.apache.wicket.pageStore.DefaultPageStore.getPage(DefaultPageStore.java:135) at org.apache.wicket.page.PageStoreManager$SessionEntry.getPage(PageStoreManager.java:203) at org.apache.wicket.page.PageStoreManager$PersistentRequestAdapter.getPage(PageStoreManager.java:360) at org.apache.wicket.page.AbstractPageManager.getPage(AbstractPageManager.java:107) [1]: https://issues.apache.org/jira/browse/WICKET-4785 Mit freundlichen Grüßen, Thorsten Schöning -- Thorsten Schöning E-Mail: thorsten.schoen...@am-soft.de AM-SoFT IT-Systeme http://www.AM-SoFT.de/ Telefon...05151- 9468- 55 Fax...05151- 9468- 88 Mobil..0178-8 9468- 04 AM-SoFT GmbH IT-Systeme, Brandenburger Str. 7c, 31789 Hameln AG Hannover HRB 207 694 - Geschäftsführer: Andreas Muchow - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: Bes practice for deployment to avoid ClassNotFoundException
Guten Tag Martin Grigorov, am Sonntag, 23. November 2014 um 11:22 schrieben Sie: You are experiencing Tomcat Session Persistence - http://tomcat.apache.org/tomcat-7.0-doc/config/manager.html#Persistence_Across_Restarts Just disable it for development to avoid such kind of problems. But the exception clearly comes from wicket's page store, I already found the code where the exception is captured and rethrown as RuntimeException. I really doubt this is a problem of the Tomcat. 122: return ois.readObject(); at org.apache.wicket.serialize.java.JavaSerializer.deserialize(JavaSerializer.java:122) java.lang.RuntimeException: Could not deserialize object from byte[] throw new RuntimeException(Could not deserialize object from byte[], cnfx); Additionally, deactivating this feature for development only in Tomcat wouldn't change anything, if I update the production system after refactoring I would get the same error there of course. From looking at the code I think what I would need to do instead is create my own delegating serializer, which encapsulates the default Wicket one, catches the problematic exception and returns null instead of throwing the exception. It looks like that all code mentioned in the stacktrace is using null if things are not found or such and would ultimately lead to PageProvider.isNewPageInstance believing that a new instance is needed: public boolean isNewPageInstance() { boolean isNew = pageInstance == null; if (isNew pageId != null) { IRequestablePage storedPageInstance = getStoredPage(pageId); if (storedPageInstance != null) { pageInstance = storedPageInstance; isNew = false; } } return isNew; } storedPageInstance would simply be null when using my own serializer. From my opinion this should be a at least configurable default behavior in Wicket anyways, I don't see how else it can handle things like refactoring with using it's own page store of serialized Java classes. It must ignore ClassNotFoundException in such cases somehow because it's a perfectly valid situation. Mit freundlichen Grüßen, Thorsten Schöning -- Thorsten Schöning E-Mail: thorsten.schoen...@am-soft.de AM-SoFT IT-Systeme http://www.AM-SoFT.de/ Telefon...05151- 9468- 55 Fax...05151- 9468- 88 Mobil..0178-8 9468- 04 AM-SoFT GmbH IT-Systeme, Brandenburger Str. 7c, 31789 Hameln AG Hannover HRB 207 694 - Geschäftsführer: Andreas Muchow - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: Bes practice for deployment to avoid ClassNotFoundException
Hallo Thorsten, On Sun, Nov 23, 2014 at 1:02 PM, Thorsten Schöning tschoen...@am-soft.de wrote: Guten Tag Martin Grigorov, am Sonntag, 23. November 2014 um 11:22 schrieben Sie: You are experiencing Tomcat Session Persistence - http://tomcat.apache.org/tomcat-7.0-doc/config/manager.html#Persistence_Across_Restarts Just disable it for development to avoid such kind of problems. But the exception clearly comes from wicket's page store, I already found the code where the exception is captured and rethrown as RuntimeException. I really doubt this is a problem of the Tomcat. Here is what happens: 1) Wicket stores a Page into the HTTP session 2) Tomcat shuts down and persists all HTTP sessions into the disk 3) you deploy and new version of the app (with incompatible changes in the classes, like renaming a class) 4) you start Tomcat and it tries to load the persisted sessions 4.1) Since Wicket stores its data as org.apache.wicket.pageStore.DefaultPageStore.SerializedPage (a triple of pageId (int) / sessionId (String) / pageData (byte[])) it is Wicket's job to deserialize the pageData byte[] to SomePage instance. That's why you think Wicket is to blame here. But even if there was a Page stored as an attribute in the http session then Tomcat would fail the same way since there is no such class in the webapp class loader anymore. In both cases I think Tomcat will just log an error that an old session cannot be loaded and continue with the start of the application. Am I correct or Tomcat fails to start ? Please paste the complete exception if I am not correct. 122: return ois.readObject(); at org.apache.wicket.serialize.java.JavaSerializer.deserialize(JavaSerializer.java:122) java.lang.RuntimeException: Could not deserialize object from byte[] throw new RuntimeException(Could not deserialize object from byte[], cnfx); Additionally, deactivating this feature for development only in Tomcat wouldn't change anything, if I update the production system after refactoring I would get the same error there of course. No. Wicket cleans up its data storages at session invalidation time (per sessionId) or at application stop (for all sessions). So there is nothing to load at start time and no knowledge about old stuff. From looking at the code I think what I would need to do instead is create my own delegating serializer, which encapsulates the default Wicket one, catches the problematic exception and returns null instead of throwing the exception. It looks like that all code mentioned in the stacktrace is using null if things are not found or such and would ultimately lead to PageProvider.isNewPageInstance believing that a new instance is needed: public boolean isNewPageInstance() { boolean isNew = pageInstance == null; if (isNew pageId != null) { IRequestablePage storedPageInstance = getStoredPage(pageId); if (storedPageInstance != null) { pageInstance = storedPageInstance; isNew = false; } } return isNew; } storedPageInstance would simply be null when using my own serializer. From my opinion this should be a at least configurable default behavior in Wicket anyways, I don't see how else it can handle things like refactoring with using it's own page store of serialized Java classes. It must ignore ClassNotFoundException in such cases somehow because it's a perfectly valid situation. Mit freundlichen Grüßen, Thorsten Schöning -- Thorsten Schöning E-Mail: thorsten.schoen...@am-soft.de AM-SoFT IT-Systeme http://www.AM-SoFT.de/ Telefon...05151- 9468- 55 Fax...05151- 9468- 88 Mobil..0178-8 9468- 04 AM-SoFT GmbH IT-Systeme, Brandenburger Str. 7c, 31789 Hameln AG Hannover HRB 207 694 - Geschäftsführer: Andreas Muchow - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Re: Bes practice for deployment to avoid ClassNotFoundException
Guten Tag Martin Grigorov, am Sonntag, 23. November 2014 um 12:20 schrieben Sie: 4) you start Tomcat and it tries to load the persisted sessions 4.1) Since Wicket stores its data as org.apache.wicket.pageStore.DefaultPageStore.SerializedPage (a triple of pageId (int) / sessionId (String) / pageData (byte[])) it is Wicket's job to deserialize the pageData byte[] to SomePage instance. I'm pretty sure this is not what is happening and the provided stacktrace makes clear that Wicket is doing everything. The only thing where Tomcat comes into play is the actual class loading itself, but that's correct of course because Tomcat provides at least a parent classloader to use. Wicket does serialize and deserialize the pages on it's own just because of an incoming request. In both cases I think Tomcat will just log an error that an old session cannot be loaded and continue with the start of the application. Am I correct or Tomcat fails to start ? Tomcat doesn't log anything and just succeeds to start, at least I didn't find any log messages from Tomcat in Eclipse and requesting other pages from Wicket after ClassNotFoundException succeeded as well. Simply because there were newly created. Please paste the complete exception if I am not correct. I attached the saved HTML file with everything Wicket told me, but there's nothing more interesting than what I've already posted in my fist mail. No. Wicket cleans up its data storages at session invalidation time (per sessionId) or at application stop (for all sessions). So there is nothing to load at start time and no knowledge about old stuff. If that was true, Tomcat wouldn't be able to run into any problems with a serialized session as well because there wouldn't be anything left from Wicket to serialize. Or does Wicket only clear persistent storage in files, but retains it's session data? That wouldn't make much sense to me, because the problem would remain. Besides that, I just tested with a request for some page: Wicket did create a folder to save the serialized page during runtime of Tomcat. So I stopped Tomcat to see if the folder gets deleted or such and it didn't, instead Wicket created the additional file DiskDataStoreIndex as serialized Java object, which clearly contains the path to the serialized page. Afterwards I restarted Tomcat, issued another request, DiskDataStoreIndex got read (monitored using ProcMon) and afterwards deleted. The only thing I didn't see was reading the former persisted page... But the former behavior corresponds to the code: DiskDataStore.destroy doesn't just empty anything, data gets persisted in a file and there's even a load method to load the data. So the only interesting thing is if pages are used as well after the restart or not: Application.internalDestroy does call a lot of destroy methods, but DiskDataStore.destroy e.g. is implemented to persist data, while other caches seem to really be just cleared, like that for markup. Which is the codepath where I can see that persisted pages get forgotten on shutdown of Wicket? Following Application.internalDestroy and it's call of internalGetPageManager().destroy(); lead me to DiskDataStore which clearly doesn't destroy the data... A simple explanation for my problem could as well be that I didn't restart the Tomcat and that during it's restart it works like you say, but in that case I want to make sure that really session and persistent page store are abandoned and currently it doesn't look so... Mit freundlichen Grüßen, Thorsten Schöning -- Thorsten Schöning E-Mail: thorsten.schoen...@am-soft.de AM-SoFT IT-Systeme http://www.AM-SoFT.de/ Telefon...05151- 9468- 55 Fax...05151- 9468- 88 Mobil..0178-8 9468- 04 AM-SoFT GmbH IT-Systeme, Brandenburger Str. 7c, 31789 Hameln AG Hannover HRB 207 694 - Geschäftsführer: Andreas Muchow - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org
Bes practice for deployment to avoid ClassNotFoundException
Hi all, I'm new to wicket and just recently started to use it for a new web app for one of our projects. Today I came across a similar issue like described in [1], a ClassNotFoundException during deserialization of a page. The interesting part about this in my mind is, that the mentioned missing class was missing for a good reason: I simply refactored a bit and renamed the class, redeployed and restarted my Tomcat. This looks like a normal use case to me, but is something I didn't thought of when I've read through the docs because. My deployment is very simple: I check out a SVN working copy with a pre-configured tag containing the whole application once and afterwards just need to merge/update and stop/start the web server/app. How is deployment supposed to work in Wicket after I have refactored or otherwise changed my classes regarding cached and serialized pages? Is there anything I need to tell wicket to clear its caches on each deployment or ignore those or whatever? Am I forced to not delete once deployed classes for a fair period of time? That would be a litte nightmare... Or is there any other issue I ran into I should have avoided? Obviously others do deploy their Wicket apps as well, so I hope you have some input on how to avoid the problem I've ran into. Thanks! The important parts of the stacktrace: java.lang.ClassNotFoundException: de.am_soft.util.frontend.wicket.markup.link.LogoutLink at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at org.apache.wicket.application.AbstractClassResolver.resolveClass(AbstractClassResolver.java:108) at org.apache.wicket.serialize.java.JavaSerializer$ClassResolverObjectInputStream.resolveClass(JavaSerializer.java:218) at java.io.ObjectInputStream.[...] [...] at org.apache.wicket.serialize.java.JavaSerializer.deserialize(JavaSerializer.java:122) at org.apache.wicket.pageStore.DefaultPageStore.deserializePage(DefaultPageStore.java:396) at org.apache.wicket.pageStore.DefaultPageStore.getPage(DefaultPageStore.java:135) at org.apache.wicket.page.PageStoreManager$SessionEntry.getPage(PageStoreManager.java:203) at org.apache.wicket.page.PageStoreManager$PersistentRequestAdapter.getPage(PageStoreManager.java:360) at org.apache.wicket.page.AbstractPageManager.getPage(AbstractPageManager.java:107) [1]: https://issues.apache.org/jira/browse/WICKET-4785 Mit freundlichen Grüßen, Thorsten Schöning -- Thorsten Schöning E-Mail: thorsten.schoen...@am-soft.de AM-SoFT IT-Systeme http://www.AM-SoFT.de/ Telefon...05151- 9468- 55 Fax...05151- 9468- 88 Mobil..0178-8 9468- 04 AM-SoFT GmbH IT-Systeme, Brandenburger Str. 7c, 31789 Hameln AG Hannover HRB 207 694 - Geschäftsführer: Andreas Muchow - To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org