Skip to content
Sven Meier edited this page Jul 11, 2013 · 10 revisions

A type-safe model implementation for Apache Wicket, supporting:

  • lazy evaluation of method invocations
  • arbitrary parameters
  • generics
  • collections
  • interfaces
    A a = ...;
    
    IModel<B> model = model(from(a).getB());

... or starting from a model (must be an IObjectClassAwareModel, e.g. PropertyModel or subclass of AbstractReadonlyModel):

    IModel<A> a = ...;
    
    IModel<Map<String, String>> model = model(from(a).getB().getStrings());

... or as a LoadableDetachableModel:

    IModel<A> a = ...;
    
    IModel<String> model = model(from(a).getB().getStrings().get("key")).loadableDetachable();

Evaluations can be nested too:

    IModel<A> a = ...;
    IModel<D> d = ...;
    
    IModel<C> model = model(from(a1).getB().getCs().get( from(d).getIndex() ));

DataTables columns can be lazily evaluated too:

    column = new LazyColumn<A, B>(header, from(A.class).getB());

To be able to 'record' evaluations, LazyModel uses proxies for each method invocation's result: cglib is used to generate a subclass of the method's return type. For primitive or final return types this is not possible. To support this common usecase, LazyModel utilizes ThreadLocals:

    model(from(a).getI()); // works although #getI() has a primitive type as return type
    model(from(a).getF()); // works although #getF() has final class F as return type

But accessing a property on a final class does not work:

    model(from(a).getF().getString()); // fails since #getString() is a method on final class F

All this proxying comes at a performance cost: depending on your usage LazyModel is 2 to 5 times slower than PropertyModel! If you're concerned about this you might want to cache lazy evaluations:

    private static final LazyModel<B> B = model(from(A.class).getB());

    IModel<A> a = ...;

    add(new TextField<B>("b", B.bind(a));

Caching model instances will increase performance for LazyModel to be slightly faster than PropertyModel.

Inspired by:

Using:

Clone this wiki locally