Wicket
  1. Wicket
  2. WICKET-2388

Use dynamic proxies to hide PageParameters key/value pairs

    Details

    • Type: Improvement Improvement
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 1.4.0
    • Fix Version/s: None
    • Component/s: wicket
    • Labels:
      None
    • Environment:
      Any

      Description

      Enable users to work with Java objects rather than key/value pairs in PageParameters.

      I'm attaching a patch (with tests) that adds a method
      public T <T> PageParameters.asObject (Class<T> type)

      The basic idea is that you pass in an interface type with getters and setters following the beans pattern. asObject() generates an implementation of that interface (using dynamic proxies). The bean property names of methods are mapped to keys in the PageParameters, and type conversion is transparent. So you can, say, pass
      public interface MyData

      { public String getCheese(); public void setCheese(String cheese); public int getFoo(); public void setFoo(int val); }

      Populating a PageParameters is as simple as
      PageParameters p = new PageParameters();
      MyData data = p.asObject(MyData.class);
      data.setCheese ("Gouda");
      data.setFoo (42);
      ...then make a BookmarkablePageLink or whatever with it.

      On the page that receives the object, you simply do the same thing but call getters to retrieve the data. Much nicer than working with key/value pairs, and completely eliminates the problem of typos in key names breaking things.

      See http://weblogs.java.net/blog/timboudreau/archive/2008/08/objects_not_str.html for the general concept - I'm putting together a small general framework for this, but it's not available yet, and I figured a patch for PageParameters would be nicer than adding a dependency to Wicket anyway.

      What would be truly slick is if this could be made completely transparent - i.e.,
      public class MyPage extends WebPage {
      public MyPage (MyData data) {
      }
      }
      ...so if parameters are present, Wicket would search
      1. For a constructor taking PageParameters, as usual
      2. For a constructor taking an object whose class is an Interface type; if so, it calls PageParameters.asObject() with the type, and passes that
      3. A default no-arg constructor as now.

      This magical part could potentially be dangerous, so it might be best to mark pages that want their constructor arguments transparently dereferenced to have a marker annotation to indicate they really expect that behavior.

      1. pageParametersProxy.diff
        28 kB
        Tim Boudreau
      2. pageParametersProxy.diff
        28 kB
        Tim Boudreau

        Activity

        Hide
        Igor Vaynberg added a comment -

        this can be done via an adapter that can live in wicketstuff. i dont think this belongs in core.

        Show
        Igor Vaynberg added a comment - this can be done via an adapter that can live in wicketstuff. i dont think this belongs in core.
        Hide
        Juergen Donnerstag added a comment -

        was experimental so far. Probably shouldn't go into core as long as core provides all the hooks necessary.

        Show
        Juergen Donnerstag added a comment - was experimental so far. Probably shouldn't go into core as long as core provides all the hooks necessary.
        Hide
        Igor Vaynberg added a comment -

        i really dont think we need this

        Show
        Igor Vaynberg added a comment - i really dont think we need this
        Hide
        Martin Grigorov added a comment -

        It seems Juergen's code for this ticket got lost with the re-work of PageParameters for Wicket 1.5.

        Show
        Martin Grigorov added a comment - It seems Juergen's code for this ticket got lost with the re-work of PageParameters for Wicket 1.5.
        Hide
        Juergen Donnerstag added a comment -

        initial contribution committed

        Show
        Juergen Donnerstag added a comment - initial contribution committed
        Hide
        Tim Boudreau added a comment -

        Updating the patch - Eelco noticed that if you were doing a removal, the code should never reach the switch statement below.

        Show
        Tim Boudreau added a comment - Updating the patch - Eelco noticed that if you were doing a removal, the code should never reach the switch statement below.
        Hide
        Tim Boudreau added a comment -

        One open question is how best to deal with failures - in particular, there are a couple of cases that can throw a NumberFormatException (which may translate into a relatively inscrutable "at Proxy0 (Unknown Source)" stack trace) - which can happen if someone manually messes around with a URL.

        Another failure mode is deserialization errors (although this really should not be used heavily for passing serialized objects, both because they risk overrunning the browser URL-length limit, and for the obvious security reasons) - i.e. someone saves a bookmark; a new version of the app is deployed and the class signature is changed, so the object can't be deserialized (unless they were very conscientious and masochistic and wrote the horrible code you have to write to deserialize old versions of a type).

        Show
        Tim Boudreau added a comment - One open question is how best to deal with failures - in particular, there are a couple of cases that can throw a NumberFormatException (which may translate into a relatively inscrutable "at Proxy0 (Unknown Source)" stack trace) - which can happen if someone manually messes around with a URL. Another failure mode is deserialization errors (although this really should not be used heavily for passing serialized objects, both because they risk overrunning the browser URL-length limit, and for the obvious security reasons) - i.e. someone saves a bookmark; a new version of the app is deployed and the class signature is changed, so the object can't be deserialized (unless they were very conscientious and masochistic and wrote the horrible code you have to write to deserialize old versions of a type).
        Hide
        Tim Boudreau added a comment -

        Patch to PageParameters and class which implements proxying.

        Show
        Tim Boudreau added a comment - Patch to PageParameters and class which implements proxying.

          People

          • Assignee:
            Igor Vaynberg
            Reporter:
            Tim Boudreau
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 24h
              24h
              Remaining:
              Remaining Estimate - 24h
              24h
              Logged:
              Time Spent - Not Specified
              Not Specified

                Development