Uploaded image for project: 'Wicket'
  1. Wicket
  2. WICKET-4014

Wicket 1.5 Form Post Action and Link Get discard Page Class Information

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 1.5-RC7
    • Fix Version/s: 1.5.1
    • Component/s: wicket
    • Labels:
      None
    • Environment:
      Wicket version: 1.5-RC7
      java version "1.6.0_25"
      Java(TM) SE Runtime Environment (build 1.6.0_25-b06)
      Java HotSpot(TM) Client VM (build 20.0-b11, mixed mode, sharing)
      Server: GlassFish 3.1.1

      Description

      Page expiry is a very annoying and perplexing event especially if users stay logged in via remember-me cookie.

      It is therefore not a fancy enhancement but an essential business requirement to not drop the user out of context after session expiry.
      Only stateless pages can fully achieve this, but it is not always desirable to go fully stateless, especially while a recovery solution already exists.
      In 1.4, this appears to be automatic with BookmarkablePageRequestTargetUrlCodingStrategy - without any additional coding.

      The solution is well known - keep as much state in the client as required to recover the page class, and possibly even its page parameters, and to not destroy this information.

      The two attached testcases show two possible methods of page fallback recovery (one with AJAX, one without) that already work behind the scenes.
      Of course it is easy with AJAX, to just force a page reload, but this is not discussed here. AJAX just serves to demonstrate how easy the principle actually is.
      In most cases the user could successfully reload the page but Wicket 1.5 can't create a response because it has forgotten the class of the expired page.

      In 1.4, it is possible to recover the class of an expired page via its mount path.
      This feature is lost in 1.5.

      To get this functionality back in a more streamlined fashion, I am additionaly proposing in a separate jira issue 4013 to store page class and page parameters in PageExpiredException.

      Meanwhile, the focus of this issue is to request whatever means to not overwrite the path of a page in a form post action or get request, and to get the page class back as in 1.4 by whatever means.

      The two attached testcases may be helpful for expermintation. The 1.4 tescase demonstrates how the scheme works, unfortunately I could not fill the blanks in the 1.5 testcase.

      In 1.4,

      a form tag is rendered as:
      <form wicket:id="form" action="?wicket:interface=:0:form::IFormSubmitListener::"
      This is requested as:
      /testForm.0?wicket:interface=:0:form::IFormSubmitListener::
      and the page class can be recovered from the mount path "testForm" as in
      mount(new HybridUrlCodingStrategy("testForm", TestPageForm.class));

      an anchor tag is rendered as:
      <a href="?wicket:interface=:0:linkSwitch::ILinkListener::"
      This is requested as:
      /testLink.0?wicket:interface=:0:linkSwitch::ILinkListener::
      and the page class can be recovered from the mount path "test" as in
      mount(new HybridUrlCodingStrategy("testLink", TestPageLink.class));

      In 1.5,

      a form tag is rendered as:
      <form wicket:id="form" action="wicket/page?0-2.IFormSubmitListener-form"
      This is requested requested as:
      /wicket/page?0-1.IFormSubmitListener-form

      This overwrites the mount path "testForm" as in
      mountPage("testForm", TestPageForm.class);
      Consequently the server cannot discover the page class

      an anchor tag is rendered as:
      <a href="wicket/page?0-1.ILinkListener-linkSwitch"
      This is requested requested as:
      /wicket/page?0-1.ILinkListener-linkSwitch

      This overwrites the mount path "testLink" as in
      mountPage("testLink", TestPageLink.class);
      Consequently the server cannot discover the page class

        Issue Links

          Activity

          Hide
          bht@actrix.gen.nz bernard added a comment -

          Testcases

          Show
          bht@actrix.gen.nz bernard added a comment - Testcases
          Hide
          bht@actrix.gen.nz bernard added a comment -

          Thanks very much for fixing this. How I can test? Are there any snapshot builds that I can download?

          Show
          bht@actrix.gen.nz bernard added a comment - Thanks very much for fixing this. How I can test? Are there any snapshot builds that I can download?
          Hide
          mgrigorov Martin Grigorov added a comment -

          Either SVN checkout and build Wicket locally or use 1.5-SNAPSHOT from http://wicket.apache.org/start/quickstart.html.
          The latter relies on Apache Jenkins servers which is not the most stable CI service.

          Show
          mgrigorov Martin Grigorov added a comment - Either SVN checkout and build Wicket locally or use 1.5-SNAPSHOT from http://wicket.apache.org/start/quickstart.html . The latter relies on Apache Jenkins servers which is not the most stable CI service.
          Hide
          bht@actrix.gen.nz bernard added a comment -

          Thanks. I am impressed. It looks like this is a major improvement compared with 1.4 - we don't have to catch PageExpiredException anymore

          Show
          bht@actrix.gen.nz bernard added a comment - Thanks. I am impressed. It looks like this is a major improvement compared with 1.4 - we don't have to catch PageExpiredException anymore
          Hide
          mgrigorov Martin Grigorov added a comment -

          PageExpiredException still can be thrown if the page is not mounted. In this case the link contains only the page id and there is no information which page class to use to create a new instance.

          But I think it was the same in 1.4 with the hybrid url coding strategies.

          Show
          mgrigorov Martin Grigorov added a comment - PageExpiredException still can be thrown if the page is not mounted. In this case the link contains only the page id and there is no information which page class to use to create a new instance. But I think it was the same in 1.4 with the hybrid url coding strategies.
          Hide
          bht@actrix.gen.nz bernard added a comment -

          I think we will see a substantial improvement in 1.5 compared with 1.4 because the hybrid strategies DO expire in 1.4. Now we can confidently say that mounting pages will avoid PageExpiredException. But wait, what happens to the PageParameters of the mounted page? Will they be used to reconstruct the page even if the request has POST parameters for the new target? Theoretically, it should be possible because 1.5 distinguishes between GET and POST parameters. Unfortunately I did not supply a testcase for PageParameters.

          Show
          bht@actrix.gen.nz bernard added a comment - I think we will see a substantial improvement in 1.5 compared with 1.4 because the hybrid strategies DO expire in 1.4. Now we can confidently say that mounting pages will avoid PageExpiredException. But wait, what happens to the PageParameters of the mounted page? Will they be used to reconstruct the page even if the request has POST parameters for the new target? Theoretically, it should be possible because 1.5 distinguishes between GET and POST parameters. Unfortunately I did not supply a testcase for PageParameters.
          Hide
          mgrigorov Martin Grigorov added a comment -

          The newly created page will use the parameters which have been send to the expired page.
          Please test it harder and let us know if there are any issues. Thanks!

          Show
          mgrigorov Martin Grigorov added a comment - The newly created page will use the parameters which have been send to the expired page. Please test it harder and let us know if there are any issues. Thanks!
          Hide
          bht@actrix.gen.nz bernard added a comment -

          I could verify that recovery works with parameters. This is more than what I could achieve with 1.4. You asked me to test harder. I can break it with the attached testcase where the GET parameter has the same name as the form field. I don't know whether this is out of scope.

          Show
          bht@actrix.gen.nz bernard added a comment - I could verify that recovery works with parameters. This is more than what I could achieve with 1.4. You asked me to test harder. I can break it with the attached testcase where the GET parameter has the same name as the form field. I don't know whether this is out of scope.
          Hide
          mgrigorov Martin Grigorov added a comment -

          Please create a separate ticket (may be a sub-task of this) and explain the problem there.
          Thanks !

          Show
          mgrigorov Martin Grigorov added a comment - Please create a separate ticket (may be a sub-task of this) and explain the problem there. Thanks !
          Hide
          thomas.goetz Tom Götz added a comment - - edited

          The only disadvantage to the solution is IMHO:
          when you have a mounted page with a state (e.g. some ajax components on the page) and the page expires then you now have no chance of informing the user about the session expiry. Instead a fresh page (with a reset/fresh state) is created which can result in a suboptimal user experience (as already discussed today in IRC with martin-g and carl-eric). I'd suggest to make that behavior configurable, should I open a new ticket for that?

          Show
          thomas.goetz Tom Götz added a comment - - edited The only disadvantage to the solution is IMHO: when you have a mounted page with a state (e.g. some ajax components on the page) and the page expires then you now have no chance of informing the user about the session expiry. Instead a fresh page (with a reset/fresh state) is created which can result in a suboptimal user experience (as already discussed today in IRC with martin-g and carl-eric). I'd suggest to make that behavior configurable, should I open a new ticket for that?
          Hide
          bht@actrix.gen.nz bernard added a comment -

          This issue is not fixed yet. In the the 1.4 test case, WebRequestCycleProcessor succeeds in re-instantiating a page from a form post request. In Wicket 6.5, the form post URL does not include any page information for a mounted page. It does not work although IPageSettings#getRecreateMountedPagesAfterExpiry() == true

          Show
          bht@actrix.gen.nz bernard added a comment - This issue is not fixed yet. In the the 1.4 test case, WebRequestCycleProcessor succeeds in re-instantiating a page from a form post request. In Wicket 6.5, the form post URL does not include any page information for a mounted page. It does not work although IPageSettings#getRecreateMountedPagesAfterExpiry() == true

            People

            • Assignee:
              mgrigorov Martin Grigorov
              Reporter:
              bht@actrix.gen.nz bernard
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development