In this post, I still follow the Wicket in Action book, yet continue with the process of breaking out the concept into one simple project. This post takes the model (Customer object) and ties it to the page using the CompoundPropertyModel<Customer> object. I use paramaterized generics (<Customer>) part for the methods, so no casting of the return value needed for our callback (onSubmit). The code for this can be downloaded as hippo03.zip from my site and imported in eclipse. To run the code, you need Maven and Java. To run it, just use mvn jetty:run and point your web browser to http://localhost:8080/
The process is as follows. We create object used for model. Set the default model using the setDefaultModel for the Index.java page which extends WebPage.
We set labels so that they will use the getters from the default model. Maybe someday Java will have properties like Pascal! First, here is the Java code in Index.java creating the Customer object (our Model of MVC). I use setDefaultModel to set the model for our page (Index.html). I don’t know exactly why it is not setModel() like it is in our form, but I am still getting the details on Wicket, so I hope to figure out why later.
customer = new Customer(); customer.setFirstName("Jimmy"); customer.setLastName("Dean"); customer.getAddress().setStreet("123 Easy Street"); myModel = new CompoundPropertyModel<Customer>(customer); setDefaultModel(myModel); firstNameLabel = new Label("firstName"); add(firstNameLabel); lastNameLabel = new Label("lastName"); add(lastNameLabel); addressLabel = new Label("address.street"); add(addressLabel);
This following the html for the Labels. The labels match the attributes for the object.
<tr> <td><code>firstName in Label</code></td> <td wicket:id="firstName"></td> </tr> <tr> <td><code>lastName in Label</code></td> <td wicket:id="lastName"></td> </tr> <tr> <td><code>street.address in Label</code></td> <td wicket:id="address.street">1234 Any Street</td> </tr>
Now, we shall add the form(myForm), passing the model as an argument to the form. At first, I thought that myForm would get the model from the Index page, but it does not, so I passed it the model as an argument for the constructor. In myForm, we first add the model, and then the fields. The attributes for the fields match the names of the attributes in the Customer object model, and therefore, the model binds them directly matches the fields directly to the object. Below, first is the java code and then the html.
The Java code (Form.java)
setModel(myModel); fnameField = new TextField<String>("firstName"); add(fnameField); lnameField = new TextField<String>("lastName"); add(lnameField); streetField = new TextField<String>("address.street"); add(streetField);
Java code in Index.java
myForm = new Form1("myform",myModel); add(myForm);
The html (Index.html)
<tr><td>First Name</td><td><input type="text" wicket:id="firstName" /></td></tr> <tr><td>Last Name</td><td><input type="text" wicket:id="lastName" /></td></tr> <tr><td>Street</td><td><input type="text" wicket:id="address.street" /></td></tr>
And, when the user hits the submit button for the form, we create a callback for onSubmit behavior.
protected void onSubmit() { Customer customer = getModelObject(); String street = customer.getAddress().getStreet(); // Probably should use logging here! System.out.println("Customer street is " + street); // do something with/to the customer }
As the book notes, this ties the data close to the form construction. Make an UML class diagram of your model, hand it to your html designer, and it seems that you are almost all good to go. I am sure there are still little devils running through the details, but this provides good abstraction and takes the developer away from dealing with low level http dirty work. Yet, the book notes that the referenced attributes in quotes can’t be easily refactored if need be. I find that it makes MVC really clean and look forward to more.