Skip to content
This repository has been archived by the owner on Jul 30, 2024. It is now read-only.

PropertyModel considerations

kennethgeerts edited this page May 20, 2011 · 3 revisions

Property models are a common programming paradigm in Wicket, but as Wicket goes, they are poorly documented.

We will explain a little about them based on the following property model:

IModel<Zip> model =  
    new PropertyModel<Zip>(person, "fetchAddressBook().addresses.0.zip"));

The simplest form to express the same without reflection would be:

IModel<Zip> model =
    new IModel<Zip>(){
        public Zip getObject(){
            Address firstAddress = getFirstAddress();
            if (firstAddress == null) return null;
            return firstAddress.getZip()
        }
        public void setObject(Zip zip){
            getFirstAddress.setZip(zip);
        }
        private getFirstAddress(){
            AdressBook addressBook = person.fetchAddresBook();
            if (addressBook != null) return null;
            List<Addresses> list = addressBook.addresses;
            if (list == null) return null;
            return list.get(0);
        }
        public void detach(){}
    } 

So you see the main benefits:

  • no null checking needed
  • a lot more concise (and you'll need that because you basically need to construct a new model for each subcomponent)

Main drawback is the code is not refactoring-safe anymore: e.g. if somebody renames fetchAdressBook to getAddressBook without changing the expression in the PropertyModel too, the code will be broken without any compiler warning.

In the past we tried several strategies to get around the problem:

  • Don't use PropertyModels:
    Use AbstractReadOnlyModel when appropriate to reduce code size.
    Use nested models to avoid to duplicate a lot of stuff over and over again.
    IModel<Zip> model = 
        new ZipModel(new ListItemModel<Address>
            (new AddressesModel(new AddressBookModel(person), 0));
However, this approach lead to even more code.
  • Use PropertyModels, but test them:
    @Autowired
    SomePageData somePageData;

    @Test
    public void testComponentModel(){
        Zip expectedZip = new Zip(435435);
        Mockito.when(somePageData.getPerson())
            .thenReturn(new Person(new AddressBook(new Address(expectedZip));
        WicketTester wicketTester = new WicketTester();
        wicketTester.startPage(SomePage.class);
        wicketTester.assertModelValue("zipField", expectedValue);
    }
(Note that the _setObject()_ functionality is not validated yet!)
  • You have to write a test for every PropertyModel, and most of the time, code coverage tools don't help you to see which ones are not covered. If you have one of these property models failing, most of the time the complete page fails, making all your tests fail, which is not a good help either. Also, the error messages of wicket are not always straightforward as it comes to root cause analysis, since the faults are detected at render time, so it is very difficult to pinpoint what code caused the problem...

But we should have something better... so I created the VerifiablePropertyModel!

Some other pointers:

Clone this wiki locally