Wednesday, December 05, 2007

Wicket HTML Table implementation

This is how you implement an html table using Wicket framework. For those of you who are new to wicket, Wicket is a component-oriented Java web application framework. It’s very different from action-/request-based frameworks like Struts, WebWork, or Spring MVC where form submission ultimately translates to a single action. In Wicket, a user action typically triggers an event on one of the form components, which in turn responds to the event through strongly typed event listeners. (See wicket.apache.org).

This example shows how you render an html table that display person's data. (e.g. first name, last name and age ).

1) First you need to define your HTML.


<form wicket:id="personListForm">
<table width="100%" border="0" >
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email Address</th>
</tr>
<tr wicket:id="personList">
<td wicket:id="firstName">[first]</td>
<td wicket:id="lastName">[last]</td>
<td wicket:id="email">[email]</td>
</tr>
</table>
</form>



2) In your java code where you have to define the form. You will need the following:

a) Define a dataProvider - You can implement the IDataProvider interface, and define its functions. Normally, the IDataProvider is an object
that has access to your backend service.

b) Define a model - You can implement IModel, or you can use the subclasses available. ContactDetachableModel, DetachableContactModel, StringResourceModel.
Why can't we just use the POJO directly from the backend service? Well, wicket will sometimes serialized the object to save memory when you move from one page to the other, and go back. All
object that you will need to display, have to be wrapped/implemented IModel.




//This is the POJO that you retrieve from your service.
class Person implements Serializable {
private static final long serialVersionUID = 5934872279937101444L;
private String firstName;
private String lastName;
private String email;

//access methods here.
//getters and setters not define.

}


A detachable modelin Wicket is a model that can get rid of a large portion of its state to reduce the amount of memory it takes up and to make it cheaper to serialize when replicating it in a clustered environment. When an object is in the detached state, it contains only somevery minimal nontransient state such as an object ID that can be used to reconstitute the object from a persistent data store. When a detached object is attached, some logic in the object uses this minimal state to reconstruct the full state of the object. This typically involves restoring fields from persistent storageusing a database persistence technology


//This is the Wicket Model
public class DetachablePersonModel extends LodableDechableModel {
//make it transient, so that it will not get serialized.
private transient Person person;

@Override
public Object getObject() {
return this.person;
}
...

}



public class PersonDataProvider implements IDataProvider {

public Iterator<Person> iterator(int first, int count) {
Iterator<Person> iterator = null;
iterator = getPersonService().retrieveEntirePerson(first,count);
return iterator;
}

//Your model is used here.
public IModel model(Object object) { return new DetachablePersonModel((Person)object); }

public int size() {
int size = 0;
try {
size = getPersonService().retrieveEntirePerson().size();
} catch (ServiceException e) { //implement exception here.}
return size;
}

}


c) Define a DataView - Data views aim to make it very simple to populate your repeating view from a database by utilizing IDataProvider to act as an interface between the database and the dataview.


Normally, you will implement DataView as an anonymous class, or an inner class, because the chances of reusing the class is minimal.


//define as inner class

private class PersonDataView extends DataView {

...
@Override
protected void populateItem(Item item) {
Person person = (Person) item.getModelObject();
item.setModel(new CompoundPropertyModel(person));
item.add(new Label("firstName"));
item.add(new Label("lastName"));
item.add(new Label("emal"));

}
}


3) This is how you would define it in your page.


final Form persontListForm = new Form("personListForm");
final PersonDataProvider personDataProvider = new PersonDataProvider();
final DataView personDataView = new PersonDataView("personList", personDataProvider);
personDataView.setItemsPerPage(5);
persontListForm.add(contactListDataView);



For information regarding the objects used in this example visit:

http://people.apache.org/~tobrien/wicket/apidocs/index.html


Main wicket site:

wicket.apache.org