PageMap.remove(Page) throws ClassCastException
----------------------------------------------

                 Key: WICKET-942
                 URL: https://issues.apache.org/jira/browse/WICKET-942
             Project: Wicket
          Issue Type: Bug
          Components: wicket
    Affects Versions: 1.3.0-beta3
            Reporter: John Ray


When I try to expire a page by calling PageMap.remove(Page) I get the following 
exception

java.lang.ClassCastException: java.lang.Integer cannot be cast to 
org.apache.wicket.protocol.http.pagestore.PageWindowManager$PageWindowInternal
     at 
org.apache.wicket.protocol.http.pagestore.PageWindowManager.removePage(PageWindowManager.java:544)
     at 
org.apache.wicket.protocol.http.pagestore.DiskPageStore$SessionEntry.removePage(DiskPageStore.java:255)
     at 
org.apache.wicket.protocol.http.pagestore.DiskPageStore.removePage(DiskPageStore.java:623)
     at 
org.apache.wicket.protocol.http.pagestore.DiskPageStore.removePage(DiskPageStore.java:652)
     at 
org.apache.wicket.protocol.http.SecondLevelCacheSessionStore$SecondLevelCachePageMap.removeEntry(SecondLevelCacheSessionStore.java:368)
     at org.apache.wicket.PageMap.remove(PageMap.java:289)

The problem in removePage() of the PageWindowManager class was that it wasn't 
getting the PageWindowInternal from the windows list. There is also a problem 
though in that it attempts to iterate through the window indexes and at the 
same time calls removePage() which removes them so you get a 
ConcurrentModificationException. I've tested the following and it works

        public void removePage(int pageId)
        {
                if (idToWindowIndices == null)
                {
                        rebuildIndices();
                }

                List indicesList = (List) idToWindowIndices.get(pageId);
                if (indicesList == null)
                {
                        return; // Return if page was already removed
                }

                Object[] indices = indicesList.toArray();
                for (int i=0; i < indices.length; i++)
                {
                        PageWindowInternal window = 
(PageWindowInternal)windows.get((Integer)indices[i]);
                        removePage(window.pageId, window.versionNumber, 
window.ajaxVersionNumber);
                }
        }

However I ran into another problem. When my page removes itself it then gets 
immediately added back in at the end of the request cycle in 
Session.requestDetached(). So its impossible for a page to expire itself. To 
fix this I would recommend changing the PageMap.remove(Page) method to

        public final void remove(final Page page)
        {
                // Remove the pagemap entry from session
                removeEntry(page.getPageMapEntry());
                // Make sure it doesn't get added again at the end of the 
request cycle
                Session.get().untouch(page);
        }

and then add the untouch() method to Session

        /**
        * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL IT.
        * <p>
        * This method will remove a page that was previously added via touch()
        * @param page
        */
        public final void untouch(Page page)
        {
                List lst = (List)touchedPages.get();
                if (lst != null)
                {
                        lst.remove(page);
                }
        }

With the above changes my code works as it did under version 1.2.6

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to