Today we will add simple listing view for locations added to the database in previous posts.  I said ‘simple’ as there are some more sophisticated ways to show many items using Wicket but probably we will not have many locations to show in our application so simple view without pagination should be ok. More complicated way (DataTable component) will be covered in the future when we will add ‘listing items’ feature’.

But first small bug I found in our DAO layer. In class AbstractDAO we created method findByProperty and there is one line there:

At first everything  seems to be ok, but what will happen when query returns no result? An ugly exception is thrown. So we have to fix it with following code:

After this one, we could return to main topic of this post.

Preparing logic

As we need list of all locations we must add one method to ListingService interface and class:

LocationDao uses generic method findAll from AbstractDAO to load all objects from db.

Adding listing component

When we are ready with our logic, we could look at LocationsPage.java and HTML files:

First we add placeholders for Wicket objects in HTML:
locations for component to list all locations from database. We add it around tr element so each item will be rendered as separate table row. Of course you can use li, span, div instead.
id: a label inside locations to render ID of each entity object
name: a label inside locations to show name of each location

Then we modify wicket page class:

So what is happening in the code above? Let me explain it in more detail. In (1) we add new method to initGui(), in (2) we create ListView component which renders list of object in a selected way. In (2) you can also notice a createModelForLocations() method invocation, but this method will be covered a little later. ListView class has one method we have to implement: populateItem (3) which is called for each object from collections or collection model passed to ListView.

In this method we must add two labels declared inside locations element in HTML file, and we do it in (4).  And here, as authors of Wicket and developers using this framework suggest, we use model instead of sending pure String value to the component. Why? Because if we use property of entity loaded from database, we are connecting view with this data and when page state is serialized also entity object is serialized too. And if our application uses Open Session in View we could end with the whole object graph serialized which will dramatically increase memory needed for each user session. So this is not what we really want 🙂

In (4) we are using PropertyModel which wraps Location model to get one property from it, id or name. Model wrapping is one of the best ways to use Wicket models effectively. Thanks to it we have only one Location model and we can wrap it many times in many ways to use it in a different situations.

Now, it’s time to talk about mysterious method creating model for our ListView component (5):

In this method we are using LoadableDetachableModel, another feature which you should use often if you want your applications to be memory efficient. This model (more detailed info can be found here) has one nice feature, it nullifies model object at the end of each request and loads it when needed. So no risk to have your 100000 entity objects serialized when page is saved on the server.

Results

Working as expected. But if we view this page with empty database it will look rather strange:

ListView component isn’t rendered (no locations so nothing to show) but as it is placed inside table and under row with headers this part of HTML is visible.  We must fix it and additionally, we will add with information label when there are no locations.

The simplest way of hiding component is to call setVisible(false) method but as we want to hide pure HTML which isn’t directly assigned to any Wicket component, this way won’t work. In such cases framework provides wicket:enclosure tag (read more about Wicket tags here) which renders html inside only when connected Wicket component is visible. Let me show this in practice:

We simply surround table with wicket:enclosure and define its child component as locations. So when locations.getVisible() returns false, no code inside enclosure is rendered.

Now we need to make location ListView component invisible when list is empty:

Moreover we want to show information when there are no locations, so we add label:

and in Java page class we create Label which is visible when ListView is not:

After these improvements our page is ready:

Page is ready, you are ready to use ListView component in your projects  so we reached the end of this post. As usual latest source code is available here and changeset from this post (except DAO bug fix which was pushed earlier) can be viewed here.