Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 8.0.0-M6
    • Fix Version/s: 6.27.0, 7.8.0, 8.0.0-M7
    • Component/s: wicket, wicket-extensions
    • Labels:
      None
    • Environment:
      Jetty 9.4.5.v20170502

      Description

      When using ModalWindow in combination with PageReference does not work since version 8.0.0-M6.

      I tried 8.0.0-M5 as well without getting this issue.

      Using the example code of wicket-examples, the call (ModalWindowPage)modalWindowPage.getPage() will always return null instead of the page.

      The PageReference object contains a valid pageId, but the PageManager cannot find the object referenced by this ID.

      I attached an example project to show this issue
      (use mvn clean compile jetty:run to start local webserver on 8080).

      I'm also pretty sure that this problem will also occur with the wicket-example code.
      My example is just a stripped version of the wicket-examples modal window sample which will throw an IllegalArgumentException when getPage() is null.

        Issue Links

          Activity

          Hide
          mgrigorov Martin Grigorov added a comment - - edited

          Your application and Wicket-Examples work fine here with both 8.0.0-M6 and 8.0.0-SNAPSHOT.
          http://examples8x.wicket.apache.org/ajax/modal-window

          Show
          mgrigorov Martin Grigorov added a comment - - edited Your application and Wicket-Examples work fine here with both 8.0.0-M6 and 8.0.0-SNAPSHOT. http://examples8x.wicket.apache.org/ajax/modal-window
          Hide
          hypfvieh David M. added a comment -

          hmmm... That's really strange.

          I get the null-reference every time on my main working machine as well as on my laptop.
          I also tried to use different java versions (openjdk 1.8.0_131, oracle jdk 1.8.0_121 as well as old oracle jdk 1.8.0_74), but that does not change anything.

          Any idea on how I could help to track down this issue?

          Show
          hypfvieh David M. added a comment - hmmm... That's really strange. I get the null-reference every time on my main working machine as well as on my laptop. I also tried to use different java versions (openjdk 1.8.0_131, oracle jdk 1.8.0_121 as well as old oracle jdk 1.8.0_74), but that does not change anything. Any idea on how I could help to track down this issue?
          Hide
          hypfvieh David M. added a comment -

          After some further debugging, I can see the following:

          'PageReference.getPage()' calls 'Session.get().getPageManager().getPage()' which then will use 'getRequestAdapter().getPage()'.
          This will use 'PersistentRequestAdapter.getPage()' to retrieve the page.

          In my sample, PersistentRequestAdapter tries to find the page with 'findPage()' method which will iterate the
          'touchedPages' member. The member only contains one entry in my sample, and that is the modal window, not the parent page (referenced page) of the modal window.
          So this 'findPage()' call will return null.

          As second pass, if returned page was null, getSessionEntry(false) is called and returns a SessionEntry (org.apache.wicket.page.PageStoreManager$SessionEntry) object.
          Then 'getPage(id)' on this SessionEntry object is called.

          After some checks, the 'sessionCache' member is checked and if that is not null (which is the case), 'findPage(id)' is used to find the page in sessionCache member.
          The 'sessionCache' member also only contains the ModalWindow, not the requested page, so again null is returned.

          As last option getPageStore() is called and returning an AsynchronousPageStore object.
          'getPage()' call is issued on the AsynchronousPageStore object.

          The first thing inside this 'getPage()' call is a 'getEntry' call which returns null, so the 'delegate' member (instance of DefaultPageStore) will be used.
          'getPage()' is called on 'delegate' member.

          In that method, DefaultPageStore member 'pagesCache' (instance of AbstractPageStore) is queryied and will again return null which will result in calling 'getPageData(sessionId, pageId)'.
          Now the method 'getData(sessionId, pageId) on 'dataStore' (instance of AsynchronousDataStore) member of AbstractPageStore will be called.

          'getEntry(sessionId, id)' will again return null, so 'dataStore.getData(sessionId, id)' is used.

          In the DiskDataStore class, 'getData' will use 'getSessionEntry' (returns an object, not null) and then try to load the page with 'sessionEntry.loadPage(id)'.
          In 'loadPage' 'getManager().getPageWindow(id)' will return null.

          The manger behind 'getManager()' is org.apache.wicket.pageStore.PageWindowManager.
          In PageWindowManager object the member 'idToWindowIndex' only contains one entry, and that is the pageId of the ModalWindow, not the parent.
          That means, 'getWindowIndex(pageId)' will return -1 because the lookup in idToWindowIndex-Map will return null.

          After all of that stuff above, this 'null' value is returned through all the stacks until it reaches my sample code.

          The question for me is, why is the initial "parent" page not inside any of those "stores"?

          Show
          hypfvieh David M. added a comment - After some further debugging, I can see the following: 'PageReference.getPage()' calls 'Session.get().getPageManager().getPage()' which then will use 'getRequestAdapter().getPage()'. This will use 'PersistentRequestAdapter.getPage()' to retrieve the page. In my sample, PersistentRequestAdapter tries to find the page with 'findPage()' method which will iterate the 'touchedPages' member. The member only contains one entry in my sample, and that is the modal window, not the parent page (referenced page) of the modal window. So this 'findPage()' call will return null. As second pass, if returned page was null, getSessionEntry(false) is called and returns a SessionEntry (org.apache.wicket.page.PageStoreManager$SessionEntry) object. Then 'getPage(id)' on this SessionEntry object is called. After some checks, the 'sessionCache' member is checked and if that is not null (which is the case), 'findPage(id)' is used to find the page in sessionCache member. The 'sessionCache' member also only contains the ModalWindow, not the requested page, so again null is returned. As last option getPageStore() is called and returning an AsynchronousPageStore object. 'getPage()' call is issued on the AsynchronousPageStore object. The first thing inside this 'getPage()' call is a 'getEntry' call which returns null, so the 'delegate' member (instance of DefaultPageStore) will be used. 'getPage()' is called on 'delegate' member. In that method, DefaultPageStore member 'pagesCache' (instance of AbstractPageStore) is queryied and will again return null which will result in calling 'getPageData(sessionId, pageId)'. Now the method 'getData(sessionId, pageId) on 'dataStore' (instance of AsynchronousDataStore) member of AbstractPageStore will be called. 'getEntry(sessionId, id)' will again return null, so 'dataStore.getData(sessionId, id)' is used. In the DiskDataStore class, 'getData' will use 'getSessionEntry' (returns an object, not null) and then try to load the page with 'sessionEntry.loadPage(id)'. In 'loadPage' 'getManager().getPageWindow(id)' will return null. The manger behind 'getManager()' is org.apache.wicket.pageStore.PageWindowManager. In PageWindowManager object the member 'idToWindowIndex' only contains one entry, and that is the pageId of the ModalWindow, not the parent. That means, 'getWindowIndex(pageId)' will return -1 because the lookup in idToWindowIndex-Map will return null. After all of that stuff above, this 'null' value is returned through all the stacks until it reaches my sample code. The question for me is, why is the initial "parent" page not inside any of those "stores"?
          Hide
          mgrigorov Martin Grigorov added a comment -

          Can anyone else reproduce the problem with David M.'s quickstart or with wicket-examples ?

          Show
          mgrigorov Martin Grigorov added a comment - Can anyone else reproduce the problem with David M. 's quickstart or with wicket-examples ?
          Hide
          svenmeier Sven Meier added a comment -

          I'm getting a NullPointerException in wicket-examples and the IllegalArgumentException in the quickstart.

          Show
          svenmeier Sven Meier added a comment - I'm getting a NullPointerException in wicket-examples and the IllegalArgumentException in the quickstart.
          Hide
          svenmeier Sven Meier added a comment -

          It works with M5 :/

          Show
          svenmeier Sven Meier added a comment - It works with M5 :/
          Hide
          svenmeier Sven Meier added a comment -

          This doesn't have anything to do with ModalWindow - every retrieval of previous pages from the page store fails:

          Just open wicket-example's FormInput several times, then switch back to a previous page id and Wicket will recreate an expired page.

          Show
          svenmeier Sven Meier added a comment - This doesn't have anything to do with ModalWindow - every retrieval of previous pages from the page store fails: Just open wicket-example's FormInput several times, then switch back to a previous page id and Wicket will recreate an expired page.
          Hide
          svenmeier Sven Meier added a comment -

          Breaking commit is 290398a3e4f950f6c6cd93ad0c557c12c867ce0e

          Show
          svenmeier Sven Meier added a comment - Breaking commit is 290398a3e4f950f6c6cd93ad0c557c12c867ce0e
          Hide
          mgrigorov Martin Grigorov added a comment -

          I'll take a look now!

          Show
          mgrigorov Martin Grigorov added a comment - I'll take a look now!
          Hide
          mgrigorov Martin Grigorov added a comment -

          This is the problem:

          at org.apache.wicket.pageStore.DiskDataStore.removeData(DiskDataStore.java:169)
          	  - locked <0x176a> (a org.apache.wicket.pageStore.DiskDataStore$SessionEntry)
          	  at org.apache.wicket.pageStore.AsynchronousDataStore.removeData(AsynchronousDataStore.java:204)
          	  at org.apache.wicket.pageStore.AbstractPageStore.removePageData(AbstractPageStore.java:105)
          	  at org.apache.wicket.pageStore.AbstractCachingPageStore.unbind(AbstractCachingPageStore.java:95)
          	  at org.apache.wicket.page.PageStoreManager$SessionEntry.valueUnbound(PageStoreManager.java:319)
          	  at org.eclipse.jetty.server.session.AbstractSession.unbindValue(AbstractSession.java:527)
          	  at org.eclipse.jetty.server.session.AbstractSession.setAttribute(AbstractSession.java:453)
          	  at org.apache.wicket.session.HttpSessionStore.setAttribute(HttpSessionStore.java:366)
          	  at org.apache.wicket.Session.setAttribute(Session.java:855)
          	  at org.apache.wicket.page.DefaultPageManagerContext.setSessionAttribute(DefaultPageManagerContext.java:99)
          	  at org.apache.wicket.page.RequestAdapter.setSessionAttribute(RequestAdapter.java:90)
          	  at org.apache.wicket.page.PageStoreManager$PersistentRequestAdapter.storeTouchedPages(PageStoreManager.java:413)
          ...
          

          Updating the session attribute leads to unbinding the old one and thus removing the data stored in the disk.

          Show
          mgrigorov Martin Grigorov added a comment - This is the problem: at org.apache.wicket.pageStore.DiskDataStore.removeData(DiskDataStore.java:169) - locked <0x176a> (a org.apache.wicket.pageStore.DiskDataStore$SessionEntry) at org.apache.wicket.pageStore.AsynchronousDataStore.removeData(AsynchronousDataStore.java:204) at org.apache.wicket.pageStore.AbstractPageStore.removePageData(AbstractPageStore.java:105) at org.apache.wicket.pageStore.AbstractCachingPageStore.unbind(AbstractCachingPageStore.java:95) at org.apache.wicket.page.PageStoreManager$SessionEntry.valueUnbound(PageStoreManager.java:319) at org.eclipse.jetty.server.session.AbstractSession.unbindValue(AbstractSession.java:527) at org.eclipse.jetty.server.session.AbstractSession.setAttribute(AbstractSession.java:453) at org.apache.wicket.session.HttpSessionStore.setAttribute(HttpSessionStore.java:366) at org.apache.wicket.Session.setAttribute(Session.java:855) at org.apache.wicket.page.DefaultPageManagerContext.setSessionAttribute(DefaultPageManagerContext.java:99) at org.apache.wicket.page.RequestAdapter.setSessionAttribute(RequestAdapter.java:90) at org.apache.wicket.page.PageStoreManager$PersistentRequestAdapter.storeTouchedPages(PageStoreManager.java:413) ... Updating the session attribute leads to unbinding the old one and thus removing the data stored in the disk.
          Hide
          jira-bot ASF subversion and git services added a comment -

          Commit 95fcc140dc64b8226f54664b70249ec3067e0768 in wicket's branch refs/heads/wicket-7.x from Martin Grigorov
          [ https://git-wip-us.apache.org/repos/asf?p=wicket.git;h=95fcc14 ]

          WICKET-6387 ModalWindow PageReference broken

          Do not remove the session data when the SessionEntry is updated in the Session

          Show
          jira-bot ASF subversion and git services added a comment - Commit 95fcc140dc64b8226f54664b70249ec3067e0768 in wicket's branch refs/heads/wicket-7.x from Martin Grigorov [ https://git-wip-us.apache.org/repos/asf?p=wicket.git;h=95fcc14 ] WICKET-6387 ModalWindow PageReference broken Do not remove the session data when the SessionEntry is updated in the Session
          Hide
          jira-bot ASF subversion and git services added a comment -

          Commit 0f8e0199944b0eb920c278814b629504ca62dbf0 in wicket's branch refs/heads/wicket-6.x from Martin Grigorov
          [ https://git-wip-us.apache.org/repos/asf?p=wicket.git;h=0f8e019 ]

          WICKET-6387 ModalWindow PageReference broken

          Do not remove the session data when the SessionEntry is updated in the Session

          (cherry picked from commit 95fcc140dc64b8226f54664b70249ec3067e0768)

          Show
          jira-bot ASF subversion and git services added a comment - Commit 0f8e0199944b0eb920c278814b629504ca62dbf0 in wicket's branch refs/heads/wicket-6.x from Martin Grigorov [ https://git-wip-us.apache.org/repos/asf?p=wicket.git;h=0f8e019 ] WICKET-6387 ModalWindow PageReference broken Do not remove the session data when the SessionEntry is updated in the Session (cherry picked from commit 95fcc140dc64b8226f54664b70249ec3067e0768)
          Hide
          jira-bot ASF subversion and git services added a comment -

          Commit 9e50533f2d9546d46686a88146936b25e1f355dd in wicket's branch refs/heads/master from Martin Grigorov
          [ https://git-wip-us.apache.org/repos/asf?p=wicket.git;h=9e50533 ]

          WICKET-6387 ModalWindow PageReference broken

          Do not remove the session data when the SessionEntry is updated in the Session

          (cherry picked from commit 95fcc140dc64b8226f54664b70249ec3067e0768)

          Show
          jira-bot ASF subversion and git services added a comment - Commit 9e50533f2d9546d46686a88146936b25e1f355dd in wicket's branch refs/heads/master from Martin Grigorov [ https://git-wip-us.apache.org/repos/asf?p=wicket.git;h=9e50533 ] WICKET-6387 ModalWindow PageReference broken Do not remove the session data when the SessionEntry is updated in the Session (cherry picked from commit 95fcc140dc64b8226f54664b70249ec3067e0768)
          Hide
          svenmeier Sven Meier added a comment -

          +1 that was tricky

          Show
          svenmeier Sven Meier added a comment - +1 that was tricky
          Hide
          papegaaij Emond Papegaaij added a comment -

          This change breaks page store management on Wildfly. It seems Undertow does not unbind the attribute. It does re-bind. In Undertow the code that calls the listeners is:

                  final HttpSessionImpl httpSession = SecurityActions.forSession(session, servletContext, false);
                  if (old != value) {
                      if (old instanceof HttpSessionBindingListener) {
                          ((HttpSessionBindingListener) old).valueUnbound(new HttpSessionBindingEvent(httpSession, name, old));
                      }
                      applicationListeners.httpSessionAttributeReplaced(httpSession, name, old);
                  }
                  if (value instanceof HttpSessionBindingListener) {
                      ((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(httpSession, name, value));
                  }
          

          Perhaps the updating should be reset to false at valueBound?

          Show
          papegaaij Emond Papegaaij added a comment - This change breaks page store management on Wildfly. It seems Undertow does not unbind the attribute. It does re-bind. In Undertow the code that calls the listeners is: final HttpSessionImpl httpSession = SecurityActions.forSession(session, servletContext, false ); if (old != value) { if (old instanceof HttpSessionBindingListener) { ((HttpSessionBindingListener) old).valueUnbound( new HttpSessionBindingEvent(httpSession, name, old)); } applicationListeners.httpSessionAttributeReplaced(httpSession, name, old); } if (value instanceof HttpSessionBindingListener) { ((HttpSessionBindingListener) value).valueBound( new HttpSessionBindingEvent(httpSession, name, value)); } Perhaps the updating should be reset to false at valueBound?

            People

            • Assignee:
              mgrigorov Martin Grigorov
              Reporter:
              hypfvieh David M.
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development