Sep 29, 2009

Wicket Framework

Objective

Wicket Web Framework document provides basic idea on Wicket framework and also helps to build simple application.

What is Wicket?

Wicket is a Java web application framework that takes simplicity, separation of concerns and ease of development to a whole new level. Wicket pages can be mocked up previewed and later revised using standard WYSIWYG HTML design tools. Dynamic content processing and form handling is all handled in Java code using a first-class component model backed by POJO data beans that can easily be persisted using your favorite technology.

Why Wicket is invented?

1) Most existing web frameworks provide weak to non-existent support in managing server-side state

In Wicket, all server side state is automatically managed. You will never directly use an Http Session object or similar wrapper to store state. Instead, state is associated with components. Each server-side page component holds a nested hierarchy of stateful components, where each component's model is, in the end, a POJO (Plain Old Java Object). Wicket maintains a map of these pages in each user's session. One purpose of this page map (and the component hierarchy on each page) is to allow the framework to hide all details of how your components and models are accessed. You deal with simple, familiar Java objects and Wicket deals with things like URLs, session ids and GET/POST requests.

In simple statement we can say “Wicket is to JSP as Java is to C

2) Most existing frameworks require special HTML code

JSP is by far the worst offender, allowing the embedding of Java code directly in web pages, but to some degree almost all of the frameworks introduce some kind of special syntax to your HTML code.

Wicket does not introduce any special syntax to HTML. Instead, it extends HTML in a standards-compliant way via a Wicket namespace that is fully compliant with the XHTML standard. This means that you can use Macromedia Dream weaver, Microsoft Front Page, Word, Adobe Go Live, or any other existing HTML editor to work on your web pages and Wicket components. To accomplish this, Wicket consistently uses a single id attribute in the Wicket namespace ("wicket:id") to mark HTML tags that should receive special treatment by the toolkit. If you prefer not to render Wicket name spaced tags and attributes to your end-users, Wicket has a simple setting to strip them all out, resulting in ordinary, standards-compliant HTML

So that web designers can work on the HTML with very little knowledge of the application code (they cannot remove the component name tags and they cannot arbitrarily change the nesting of components, but anything else goes). Likewise, coders can work on the Java components that attach to the HTML without concerning themselves with what a given page looks like. By not stepping on each other's toes, everyone can get more work done.

3) Existing frameworks are not easy

Most of the existing toolkits have poorly defined or non-existent object models. In some cases, the model is defined using special XML syntaxes. The syntaxes may be so cumbersome that special tools are required to manipulate all the configuration information.

Wicket is all about simplicity. There are no configuration files to learn in Wicket. Wicket is a simple class library with a consistent approach to component structure. In Wicket, your web applications will more closely resemble a Swing application than a JSP application. If you know Java (and especially if you know Swing), you already know a lot about Wicket

4) Existing frameworks inhibit reusability

Most of the frameworks don’t have component models that allow reusing.

Wicket has been explicitly designed to make it very, very easy to create reusable components. Components in Wicket can be packaged up in JAR files and reused by simply dropping them in your lib folder - no configuration necessary!

Developing a Web Application with Wicket

Functional flow of this application is to have homepage consisting of a dropdown box to select the type of pizza, check boxes to select the toppings and a text box to add a comment as below
image13

After filling all the details and if you click submit as shown in below screenshot


image22

You will be navigated to another page where the whole data given in home page will be displayed


image33
Technical Overview






Since Wicket works with standard HTML, the presentation layer was designed with HTML .Wicket has the concept of model objects, these objects are simple POJOs (Plain Old Java Objects) that hold the values of the components on a page. These model objects are a similar concept to Backing Beans in JSF or Form Beans in Struts. The HTML pages containing Wicket components have some special HTML attributes that are used for mapping them to the Model objects, the attribute names must match fields of the Model objects, when a user enters some data in the HTML form and submit the page, the appropriate properties on the Model object are populated with the data entered by the user.


When writing applications with wicket, each HTML page must have a corresponding Java object extending the WebPage class. The HTML file and the Java class must have the same name, for example, an HTML file called MyWicketPage.html must have a corresponding MyWicketPage.java. The HTML files must be deployed to the same directory where the corresponding java classes reside. Wicket has several components meant to be mapped to HTML form fields. Components can be added to each other in a matter similar to the DOM of the HTML page. If the page has a form with a drop down, some checkboxes and a text field, instances of the Dropdown Choice, Checkbox and Text Field classes must be added to an instance of the Form class. The Form then needs to be added to the java class corresponding to the HTML page.

For the example WebApplication home page code(WicketTestPage.html) looks like this:

<form wicket:id="pizzaForm">
<div style="font-weight: bold;" font-weight="" bold=""><big>Online Pizza Builder</big></div>
<table style="text-align: left; width: 427px; height: 112px;" border="1"
cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td style="font-weight: bold; text-align: right;">Crust:</td>
<td><select wicket:id="crust">
<option>option 1</option>
<option>option 2</option>
<option>option 3</option>
</select></td>
</tr>
<tr>
<td style="font-weight: bold; text-align: right;">Toppings:</td>
<td>Pepperoni<input wicket:id="pepperoni" type="checkbox" /> Sausage<input
wicket:id="sausage" type="checkbox" />&nbsp;Onions<input
wicket:id="onions" type="checkbox" />&nbsp;Green Peppers<input
wicket:id="greenPeppers" type="checkbox" /></td>
</tr>
<tr>
<td style="font-weight: bold; text-align: right;">Comments:</td>
<td><input maxlength="50" size="50" wicket:id="comments" type="text" /></td>
</tr>
<tr>
<td style="text-align: center;" colspan="2"><input value="Submit"
name="Submit" type="submit" /></td>
</tr>
</tbody>
</table>
</form>


The corresponding java code for the WicketTestPage class extending wicket.markup.html. WebPage which should have the same name as homepage (WicketTestPage.html)


public class WicketTestPage extends WebPage
{
PizzaForm pizzaForm = new PizzaForm("pizzaForm");
public WicketTestPage()
{
super();
add(pizzaForm);
}
}

You should have a PizzaModel class to hold the user-entered values on the form as shown below


public class PizzaModel implements Serializable
{
private String crust;
private boolean pepperoni;
private boolean sausage;
private boolean onions;
private boolean greenPeppers;
private String comments;

public String getComments()
{
return comments;
}
public void setComments(String comments)
{
this.comments = comments;
}
public String getCrust()
{
return crust;
}
public void setCrust(String crust)
{
this.crust = crust;
}
public boolean getGreenPeppers()
{
return greenPeppers;
}
public void setGreenPeppers(boolean greenPeppers)
{
this.greenPeppers = greenPeppers;
}
public boolean getOnions()
{
return onions;
}

public void setOnions(boolean onions)
{
this.onions = onions;
}
public boolean getPepperoni()
{
return pepperoni;
}
public void setPepperoni(boolean pepperoni)
{
this.pepperoni = pepperoni;
}
public boolean getSausage()
{
return sausage;
}
public void setSausage(boolean sausage)
{
this.sausage = sausage;
}
}
Notice how the field names on the PizzaModel class match the <wicket:id> attributes in the HTML file. To bind the properties in the PizzaModel class to the fields in the HTML form you have to add following line of code in the PizzaForm class:
setModel(new CompoundPropertyModel(pizzaModel)); 

The wicket.model.CompoundPropertyModel class takes care of populating the fields in the Model object (PizzaModel in this example) with the appropriate user-entered values.

Now write a new Model class (CrustType) to model the options in the drop down, for the Pizza Application:


public class CrustType implements Serializable
{
String id;
String text;

public CrustType()
{
super();
}

public CrustType(String crustName)
{
setId(crustName);
setText(crustName);

}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getText()
{
return text;
}
public void setText(String value)
{
this.text = value;
}
@Override
public String toString()
{
return getText();
}
}

Then you had to instantiate the wicket.markup.html.form.DropDownChoice , which is the Wicket component used to map to an html <select> field (more commonly called a drop down), using the following constructor:


public DropDownChoice(java.lang.String id,
IModel model,
IModel choices,
IChoiceRenderer renderer)

The parameters you had to pass to make it all work together are as follows:


crustDropDown = new DropDownChoice(
"crust",new PropertyModel(pizzaModel, "crust"), Arrays
.asList(new CrustType[]
{ new CrustType("Thin & Crispy"),
new CrustType("Hand Tossed"),
new CrustType("Pan Pizza") }),
new ChoiceRenderer("text", "id"));
PizzaModel is the instance of the Model object that maps to the HTML form. "crust" is the name of the property in the model that will hold the value the user selected in the drop down. wicket.markup.html.form.ChoiceRenderer implements the wicket.markup.html.form.IChoiceRenderer interface, the two parameters to its constructor represent the displayed text and the value of the drop down options, respectively

And to map the form in OnlinePizzaBuilder.html, PizzaForm class is provided as below which uses the models explained above. It extends wicket.markup.html.form.Form class, which provides an onSubmit() method that is executed when the form is submitted.

public class PizzaForm extends Form
{
private DropDownChoice crustDropDown;
private CheckBox pepperoniCheckBox = new CheckBox("pepperoni");
private CheckBox sausageCheckBox = new CheckBox("sausage");
private CheckBox onionsCheckBox = new CheckBox("onions");
private CheckBox greenPeppersCheckBox = new CheckBox("greenPeppers");
private TextField commentsTextField = new TextField("comments");

public PizzaForm(String id)
{
super(id);
PizzaModel pizzaModel = new PizzaModel();
setModel(new CompoundPropertyModel(pizzaModel));
crustDropDown = new DropDownChoice(
"crust",new PropertyModel(pizzaModel, "crust"), Arrays
.asList(new CrustType[]
{ new CrustType("Thin & Crispy"),
new CrustType("Hand Tossed"),
new CrustType("Pan Pizza") }),
new ChoiceRenderer("text", "id"));

add(crustDropDown);
add(pepperoniCheckBox);
add(sausageCheckBox);
add(onionsCheckBox);
add(greenPeppersCheckBox);
add(commentsTextField);
}
}
To be able to manipulate the user-entered values, the onSubmit() method of the wicket.markup.html.form.Form method must be overwritten. The onSubmit() method of the PizzaForm class follows:
protected void onSubmit()
{
PizzaModel pizzaModel = (PizzaModel) getModelObject();
setResponsePage(new WicketTestConfPage(pizzaModel));
}
The getModelObject() method call obtains an instance of the Model object populated with the user-entered values. The requestCycle.setResponsePage() directs the browser to a new page. The WebPage instance that the browser will be redirected to must have a constructor taking an instance of the Model object as a parameter.

Now the last step is to display a confirmation page displaying all the user entered values and here is the source for the confirmation page:
public class WicketTestConfPage extends WebPage
{
public WicketTestConfPage(PizzaModel pizzaModel)
{
super();
add(new Label("crust", pizzaModel.getCrust()));
add(new Label("pepperoni", new Boolean(pizzaModel.getPepperoni())
.toString()));
add(new Label("sausage", new Boolean(pizzaModel.getSausage()).toString()));
add(new Label("onions", new Boolean(pizzaModel.getOnions()).toString()));
add(new Label("greenPeppers", new Boolean(pizzaModel.getGreenPeppers())
.toString()));
add(new Label("comments", pizzaModel.getComments()));
}
}

All it does is create some labels to displaying the values of the Model object it takes as its sole constructor parameter. Here are the relevant sections of the corresponding HTML file (WicketTestConfPage.html):


<table style="text-align: left; width: 427px; height: 112px;" border="1"
cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td style="font-weight: bold; text-align: right;">Crust:</td>
<td><span wicket:id="crust">Hello</span></td>
</tr>
<tr>
<td style="font-weight: bold; text-align: right;">Toppings:</td>
<td>Pepperoni:&nbsp; <span wicket:id="pepperoni"></span>
Sausage:&nbsp;<span wicket:id="sausage"></span>&nbsp;Onions: &nbsp;<span
wicket:id="onions"></span>&nbsp;Green Peppers:&nbsp;<span
wicket:id="greenPeppers"></span></td>
</tr>
<tr>
<td style="font-weight: bold; text-align: right;">Comments:</td>
<td><span wicket:id="comments"></span></td>
</tr>
</tbody>
</table>


Of interest here are the <span> fields; these correspond to the labels in the WicketTestConfPage java class. You may notice some of the <span> tags have text inside them, this text will only be displayed in the browser when mocking up the pages, when displayed from the Wicket application, they will display whatever value the corresponding Label instances have.

How to deploy the application in tomcat


When deploying wicket applications, the application is declared in a standard web.xml file, using wicket.protocol.http.WicketServlet as the servlet, and passing instance of a class extending wicket.protocol.http.WebApplication as its only initialization parameter. As an example, here are the relevant sections of the web.xml used for the sample application:
<servlet>
<servlet-name>WicketTestApplication</servlet-name>
<servlet-class>
wicket.protocol.http.WicketServlet
</servlet-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>
net.ensode.wickettest.WicketTestApplication
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WicketTestApplication</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>

The class extending wicket.protocol.http.WebApplication for the sample application is trivial, all it does is call getPages().setHomePage(WicketTestPage.class) from its constructor. This method call will set the initial page of the application to the HTML page corresponding to WicketTestPage.java

To download the source code for above sample application click SourceCode

Do the required setup with the help of readme.txt file from downloaded Zip file.

The application would be accessed using the URL: http://localhost:8080/wickettestapp/app. This URL assumes you are deploying to your local workstation and that the servlet container is listening to port 8080, substitute the host name and port as appropriate.

Summary from Sample Application







  • Provides clear separation of concerns where web designers don't have to add any special markup to the HTML files to make them work with wicket, allowing them to use any WYSIWYG editor to create the pages.
  • Makes it easy to create Java code that is able to execute outside of a servlet container or application server, making this code easy to unit test. For these reasons, Wicket is a good choice when creating web applications and dynamic web sites.
  • Does not require special XML configuration files


Advantages of Wickets


EASY (SIMPLE / CONSISTENT / OBVIOUS)


  • POJO-centric
  • All code written in Java ala Swing
  • Minimize "conceptual surface area"
  • Avoid overuse of XML configuration files
  • Fully solve back button problem
  • Easy to create bookmarkable pages
  • Maximum type safety and compile-time problem diagnosis
  • Maximum diagnosis of run-time problems
  • Minimum reliance on special tools
  • Components, containers and conventions should be consistent

REUSABLE


  • Components written in Wicket should be fully reusable
  • Reusable components should be easily distributed in ordinary JAR files
NON-INTRUSIVE
  • HTML or other markup not polluted with programming semantics
  • Only one simple tagging construct in markup
  • Compatible with any ordinary HTML editor
  • Easy for graphics designers to recognize and avoid framework tagging
  • Easy to add tagging back to HTML if designers accidentally remove it

SAFE


  • Code is secure by default
  • Only explicitly bookmarkable links can expose state in the page or URL
  • All logic in Java with maximum type safety
  • Easy to integrate with Java security

EFFICIENT / SCALABLE


  • Efficient and lightweight, but not at the expense of other goals
  • Clustering through sticky sessions preferred
  • Clustering via session replication is easy to accomplish and easy to tune by working with detachable models

Some disadvantages of Wicket


  • Not as well documented as other web application frameworks like Struts or Java Server Faces.
  • Has limited AJAX support (in the latest beta), although more AJAX support is planned.
References

0 comments:

Text Widget

Copyright © Vinay's Blog | Powered by Blogger

Design by | Blogger Theme by