dcsimg
December 8, 2016
Hot Topics:

Wicket: The First Steps

  • April 23, 2007
  • By Karthik Gurumurthy
  • Send Email »
  • More Articles »

There is a one-to-one mapping between the HTML page wicket:id attributes and the properties of the UserProfile Java bean. The Wicket components corresponding to the HTML elements identified by wicket:id need not map to the same model class. It's been designed that way in this example in order to demonstrate the workings of one of the Wicket's model classes. You also aren't required to create a new POJO for every Wicket page. You can reuse one if it already exists. For example, information like a user profile is stored in the back-end repository store and is typically modeled in Java through Data Transfer Objects (DTOs). If you already have a DTO that maps to the information captured in the UserProfilePage template, you could use that as the backing model class for the page, for instance. (Please refer to http://www.corej2eepatterns.com/Patterns2ndEd/TransferObject.htm if you need more information on DTOs.) Wicket, being a component-oriented framework, encourages very high levels of reuse.

You just specified the UserProfile model class, but you need the corresponding Page class, too (see Listing 12).

Listing 12. UserProfilePage.java
import java.util.Arrays;

import wicket.markup.html.WebPage;
import wicket.markup.html.form.DropDownChoice;
import wicket.markup.html.form.Form;
import wicket.markup.html.form.TextField;
import wicket.model.CompoundPropertyModel;
import com.wicketdev.app.model.UserProfile;

public class UserProfilePage extends AppBasePage{

  public UserProfilePage() {

    UserProfile userProfile = new UserProfile();
    CompoundPropertyModel userProfileModel = new CompoundPropertyModel(userProfile);
    Form form = new UserProfileForm("userProfile",userProfileModel);

    add(form);

    TextField userNameComp = new TextField("name");
    TextField addressComp = new TextField("address");
    TextField cityComp = new TextField("city");

    /*
    * Corresponding to HTML Select, we have a DropDownChoice component in Wicket.
    * The constructor passes in the component ID "country" (that maps to wicket:id
    * in the HTML template) as usual and along with it a list for the
    * DropDownChoice component to render
    */

    DropDownChoice countriesComp = new DropDownChoice("country",
       Arrays.asList(new String[] {"India", "US", "UK" }));

    TextField pinComp = new TextField("pin");

    form.add(userNameComp);
    form.add(addressComp);
    form.add(cityComp);
    form.add(countriesComp);
    form.add(pinComp);
  
  }

  class UserProfileForm extends Form {

    // PropertyModel is an IModel implementation
    public UserProfileForm (String id,IModel model) {
       super(id,model);
    }

    @Override
    public void onSubmit() {
      /* Print the contents of its own model object */
      System.out.println(getModelObject());
    }
  }
}

Note that none of the Wicket components are associated with a model! The question "Where would it source its data from while rendering or update the data back on submit?" still remains unaddressed. The answer lies in the UserProfilePage constructor:

public class UserProfilePage....{

   /** Content omitted for clarity **/
  public UserProfilePage(){

    /* Create an instance of the UserProfile class */
    UserProfile userProfile = new UserProfile();

    /*
    * Configure that as the model in a CompoundPropertyModel object.
    * You will see next that it allows you
    * to share the same model object between parent and its child components.
    */

    CompoundPropertyModel userProfileModel = new CompoundPropertyModel(userProfile);

    /*
    * Register the CompoundPropertyModel instance with the parent component,
    * Form in this case, for the children to inherit from. So all the
    * remaining components will then use the UserProfile instance
    * as its model, using OGNL like 'setters' and 'getters'
    */

    Form form = new UserProfileForm("userProfile",userProfileModel);
      //...

      /*
      * The following code ensures that rest of the components are Form's
      * children, enabling them to share Form's model.
      */

      form.add(userNameComp);
      form.add(addressComp);
      form.add(cityComp);
      form.add(countriesComp);
      form.add(pinComp);
      //...
}

Wicket's CompoundPropertyModel allows you to use each component's ID as a property-path expression to the parent component's model. Notice that the form's text field components do not have a model associated with them. When a component does not have a model, it will try to search up its hierarchy to find any parent's model that implements the IcompoundModel interface, and it will use the first one it finds, along with its own component ID to identify its model. Actually, the CompoundPropertyModel can be set up in such a way that it uses the component ID as a property expression to identify its model.

You do not have to worry about this now. So in essence every child component added to the form will use part of the form's CompoundPropertyModel as its own because the containing Form object is the first component in the upwards hierarchy whose model implements ICompoundModel.

Fill in the form values and click Save. You should see something similar to the following on the Eclipse console:

Struts users can probably relate to this way of using models as they are somewhat similar to Struts ActionForms. For JSF users, it should suffice to say that it's not too different from a JSF-managed bean. Using distinct POJOs as model objects probably makes it easier to move things around while refactoring. The good thing is that Wicket doesn't dictate anything and will work like a charm irrespective of which "modeling" option you choose.

Development vs. Deployment Mode

Modify the label User Name to User Name1 in Login.html and refresh the page; you will notice the template now displays User Name1. Essentially, any change to the template is reflected in the subsequent page access. Wicket checks for any changes to a template file and loads the new one if it indeed has been modified. This is of great help during the development phase. But you probably wouldn't be looking for this default "feature" when deploying in production, as it may lead to the application performing slowly. Wicket easily allows you to change this behavior through the wicket.Application.configure("deployment") method (see Listing 13). Note that the default value is development.

Listing 13. HelloWorldApplication.java
import wicket.protocol.http.WebApplication;
import wicket..Application;

public class HelloWorldApplication extends WebApplication {
    public HelloWorldApplication() {
        configure(Application.DEVELOPMENT);
    }

    public Class getHomePage() {
       return Login.class;
    }
}

This looks more like a configuration parameter, and hence you should specify it as one in web.xml. The WebApplication class that you configured in web.xml allows access to wicket.protocol.http.WicketServlet (see Listing 14).

Listing 14. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc
.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
 <display-name>Wicket Shop</display-name>
  <servlet>
   <servlet-name>HelloWorldApplication</servlet-name>
   <servlet-class>wicket.protocol.http.WicketServlet</servlet-class>
   <init-param>
     <param-name>applicationClassName</param-name>
     <param-value>com.wicketdev.app.HelloWorldApplication</param-value>
   </init-param>
   <init-param>
    <param-name>configuration</param-name>
    <param-value>development</param-value>
   </init-param>
   <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>HelloWorldApplication</servlet-name>
    <url-pattern>/helloworld/*</url-pattern>
  </servlet-mapping>

</web-app>




Page 4 of 6



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date
Rocket Fuel