Skip to content

LazyModel

Sven Meier edited this page Feb 11, 2014 · 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 (loaded once per request only):

    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() ));

Any method returning null immediately stops the evaluation. The same holds for any access to an out-of-bound list index.

DataTables columns can be lazily evaluated too:

    column = new LazyColumn<A, Void, 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

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:

Limitations:

  • no lazy evaluations on final classes (F is final)
    model(from(a).getF().getString());
  • no lazy evaluations of final methods (#getFinalB() is final)
    model(from(a).getFinalB().getCharacter());

Note that these unsupported cases will fail with a NullPointerException!

Clone this wiki locally