Live Javalobby Chat!
Join other Javalobby members in a real-time chat. Login with your Javalobby username and password to join.
Rooms (4):User Count:
Swing 0
EclipseZone 0
Java EE 0
More Rooms Available...
Start the webstart client!Join the chat now!
Spotlight Features

EZ Interviews: Tim Wagner, Web Tools project leader

Web Tools Platform project leader Tim Wagner balances the competing interests of open source and commercial development in what may be the most closely watched of all the Eclipse projects. In this exclusive interview, find out how he does it, and why.

Erik's Pulse 2005: A Year In Links

The truth is out there, and JL's Erik Thauvin never misses it! Last year, the Javalobby Newsletter published 46 editions of Erik's Pulse. Erik assembled a great summary of them in this mega-list.

Wicket: What's that buzz?

Javalobby's tip-meister, R.J. Lorimer, introduces you to Wicket and shows you why it is uniquely powerful and not just another Java MVC framework. Enjoy!

Why You Should Be Using Eclipse RCP (In 10 Minutes)

RCP enthusiast, J Aaron Farr, says you should be using Eclipse RCP. Don't believe him? Check out his 10 minute screencast showing the functionality that proves why Java on the desktop isn't dead!

JavaPolis 2005 - Conference Report

JavaPolis 2005 wrapped up last week and Julien Delfosse gives an incredible overview of the sessions he attended and his overall feel of the show. Synopsis: good show, good drinks, too many guys!
Threads: [ Previous | Next ]
  Click to reply to this thread Reply

Wicket: A Little Bit About Wicket

At 11:48 PM on Jan 2, 2006, R.J. Lorimer wrote:

Lets face it, Java MVC web application frameworks are a dime a dozen. That's admittedly why when Wicket was first released, I didn't pay very much attention. Wicket persisted without my attention, however, and has certainly continued to generate buzz. Recently, I was in a position to spend some time learning what all the talk was about, and my first impression was certainly a positive one.

Note that Wicket 1.2 is planned for release very soon, and based on the discussions on the user and development mailing lists, early 2006 (January/February) is when it is coming. In this article, I am focusing on Wicket 1.1 usage, since that is the current stable release.

Before going through all of this Wicket example, let's learn just a little bit about Wicket.

Wicket's Approach to Java Web Applications

(Lack of) Configuration Files

One of Wicket's key strengths is that it uses bascially no configuration files. There has certainly been a push back in recent years on the proliferation of configuration files that have to be managed just to keep everything running. You have to configure Wicket in the web.xml file of your application (a requirement of the servlet specification), and that's just about it. This makes the configuration consistent with the rest of the application logic, and also ensures that it is succeptible to standard refactoring tools such as those embedded in Intellij, Netbeans, and Eclipse.

(Lack of) Specialized Markup and Embedded Logic

Wicket has an interesting philosophy regarding the HTML markup used to template out the view. There are certainly a lot of rendering technologies available: JSP/JSTL , Velocity , Freemarker , and XSL to name a few. Other MVC frameworks, such as Tapestry use a customized markup, and in Tapestry's case in particular, something largely based in the world of static HTML. Wicket takes a similar approach as Tapestry's, and ensures that the HTML is easily consumable by standard 'HTML' applications, such as browsers and HTML editors like Macromedia Dreamweaver. Interestingly enough, Wicket even uses the namespace standards to extend HTML so that there is really no custom syntax at all - no "special sauce" as the Wicket website calls it. Instead, Wicket empowers the developer through its rich component model.

Rich Component Model

Wicket has what could be called a rich component model. What I mean by that is instead of having chunks of logic embedded in the view markup (such as JSP/Velocity/Freemarker scriptlets), you actually have a Wicket component (a 100% Java object) that contains the behavior that defines the dynamic UI result for that part of the result. This makes the configurability, extendability, and resuability of the UI components infinitely stronger. All of the wonderful patterns and techniques you have learned to maintain Java code to make it reusable work perfectly in Wicket. Where as entire frameworks, such as Tiles , were created to help modularize and componentize JSPs, Wicket naturally centers around that form of reusability, and in a 100% Java way.

Components don't just participate in the rendering process, they define it. Each component is allowed to have associated markup, and combines that markup with an internal model (provided by the developer). The behavior and logic of the component is all 100% Java code, and is all pluggable and controllable.

Finally, since all of the GUI behavior and code references are embedded in pure Java code, refactoring and code analysis are a piece of cake, as standard Java tools work perfectly with Wicket components.

Smart Session Management

Wicket takes session management to a new level. Because of Wicket's rich component model, the session management is extremely valuable for handling complex behavior such as processing form results - the component you associate with the UI to do the rendering of the form, will be the same one that consumes the result from the user. Likewise, session management makes it trivial for Wicket to handle the 'back button problem' for you. For those of you not familiar, the 'back button' problem is the scenario in which a user clicks the back button to get to a page of your application (such as a certain part of a form), and can re-submit or travel in a different direction at that point - even though that re-submit could invalidate server-side data, and potentially cause all kinds of problems.

A Quick Run-Through

Applications

The first step is to create an application object (an implementation of wicket.protocol.http.WebApplication ) - this object will help Wicket understand the organization and configuration of our program.

package com.javalobby.tnt.wicket.aloha;
 
import wicket.ApplicationSettings;
import wicket.protocol.http.WebApplication;
import wicket.util.time.Duration;
 
public class AlohaApplication extends WebApplication {
 
	@Override protected void init() {
		// Set the 'Home Page' of the application (the 'index')
		getPages().setHomePage(AlohaPage.class);
		
		// Note that many of the settings below are 'defaults', but are being 
		// set explicitly in this example to clarify.
		
		// Can be enabled/disabled to leave 'wicket' XHTML extensions in 
		// rendered result to browser (a development assistance setting)
		getSettings().setStripWicketTags(false);
		
		// Tells Wicket to explicitly report if a component is specified 
		// in the component model of a Particular page, but isn't used.
		// Useful in development to ensure all components are being rendered.
		// (But potentially slower)
		getSettings().setComponentUseCheck(true);
		
		// Tells wicket to check the timestamp of certain resources (such as HTML markup)
		// and update its local cached representation if they have changed
		// Useful in development, but more efficient to leave unset (null) in a production 
		// environment where you don't need/want polling.
		getSettings().setResourcePollFrequency(Duration.ONE_SECOND);
		
		// Tells wicket to use a helpful 'debug' exception page with a snapshot of the 
		// component model, and the exception stack trace.
		// Other settings are available to show pages that say there has been an internal error 
		// (a production-friendly page)
		// In addition, more advanced usage allows you to override this behavior completely.		
		getSettings().setUnexpectedExceptionDisplay(ApplicationSettings.SHOW_EXCEPTION_PAGE);
		
		// Alternative configuration - common 'configuration types' 
		// that set some of the settings above based on what you would 
		// want for production vs. development
		//getSettings().configure("development");
		// -- or --
		//getSettings().configure("deployment");
		
		// Potentially get custom settings from web.xml
		System.out.println(getWicketServlet().getInitParameter("aloha-app-setting"));
	}
}

Note that strictly speaking, you can just as easily use the constructor of your WebApplication class to set all of your settings and adjust things - the init() method used above exists in case you want to get some custom init-parameters from the WicketServlet as can be seen in the tail end of our configuration above.

Pages

The next step is to create a page. Pages are a combination of components and markup. We'll go through the page class creation first:

package com.javalobby.tnt.wicket.aloha;
 
import java.util.*;
 
import wicket.markup.html.WebPage;
import wicket.markup.html.basic.Label;
import wicket.markup.html.list.*;
 
public class AlohaPage extends WebPage {
	
	public AlohaPage() {
		// A Title for our page
		add(new Label("pageTitle", "Aloha - The Time is: " + new Date()));
		
		// A Wicket-style Loop/List of Items
		add(new ListView("people", getPeople()) {
			// This method is called for each 'entry' in the list.
			@Override protected void populateItem(ListItem item) {
				Person person = (Person)item.getModelObject();
				item.add(new Label("firstName", person.firstName));
				item.add(new Label("lastName", person.lastName));
				item.add(new Label("email", person.email));
			}		
		});
	}
 
	// Some arbitrary factory method.
	private List<Person> getPeople() {
		List<Person> people = new ArrayList<Person>();
		people.add(new Person("R.J.", "Lorimer", "rj@javalobby.org"));
		people.add(new Person("Rick", "Ross", "rick@javalobby.org"));
		people.add(new Person("Matt", "Schmidt", "matt@javalobby.org"));
		return people;
	}
	
	// some arbitrary class for data.
	class Person {
		String firstName;
		String lastName;
		String email;
		
		Person(String fName, String lName, String emailAddr) {
			this.firstName = fName;
			this.lastName = lName;
			this.email = emailAddr;
		}
	}
}

Note that in many cases you may not want to put the Strings and Person objects in to the components directly (as I have done). That is because of Wicket's session-usage model, where components are kept on the session for an entire web conversation. For larger and more complex applications where session replication and maximum memory consumption control are important, you may want to install custom wicket.model.IModel implementations. Optimum model usage is a tip for another day, but for those of you who are curious, there are two reasons to implement a custom model: 1.) to avoid expensive String/model data being stored in the session if it should be freshly retrieved and collected for each request and 2.) to avoid holding data that isn't serializable (such as our Person class) on the session since this data will break session clustering and failover.

This page effectively has a component tree - this tree logically looks like this:

AlohaPage
|
*--- Label id='pageTitle' model='The Time is ####'
|
*--- ListView id='people' model=ArrayList of Person objects
     |
     *--- ListItem model=Person[0]
     |    |
     |    *--- Label id='firstName' model='R.J.'
     |    |
     |    *--- Label id='lastName' model='Lorimer'
     |    |
     |    *--- Label id='email' model='rj at javalobby dot org'
     |
     *--- ListItem model=Person[1]
|    |
     |    *--- Label id='firstName' model='Rick'
     |    |
     |    *--- Label id='lastName' model='Ross'
     |    |
     |    *--- Label id='email' model='rick at javalobby dot org'
     |
     *--- ListItem model=Person[2]
          |
          *--- Label id='firstName' model='Matt'
          |
          *--- Label id='lastName' model='Schmidt'
          |
          *--- Label id='email' model='matt at javalobby dot org'          

Now, on to the HTML markup for this new page we have created. This HTML is designed to line up to the component tree that we have just created.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
<html 
	xmlns="http://www.w3.org/1999/xhtml" 
	xmlns:wicket="http://wicket.sourceforge.net/" 
	xml:lang="en" 
	lang="en">  
<head>
	<!-- The 'pageTitle' label.
		 We have designated a wicket 'Label' object with the ID 'pageTitle'.
		 Wicket labels will replace the contents of the markup they represent 
		 (in this case the <title> tag) with their dynamic model data as a 
		 String (in this case the result of '"Aloha - The Time is: " + new Date()'.	
	-->
    <title wicket:id="pageTitle">[Page Title]</title>
</head>
<body>
	<!-- A Common Data Table -->
	<table>
		<thead>
			<tr>
				<th>First Name</th>
				<th>Last Name</th>
				<th>Email Address</th>
			</tr>
		</thead>
		<tbody>
			<!-- The 'example' list item. 
				 List items (which are components roughly representing a 'for loop') are 
				 given example markup. In this case, for each list item we want to have a
				 <tr> with three <td> tags in it - each one a sub component of the list item.			
			-->
			<tr wicket:id="people">
				<!-- For a given list item, render the firstName label. -->
				<td wicket:id="firstName">[First Name]</td>
				<!-- For a given list item, render the lastName label. -->
				<td wicket:id="lastName">[Last Name]</td>
				<!-- For a given list item, render the email label. -->
				<td wicket:id="email">[Email]</td>
			</tr>
		</tbody>
	</table>
</body>
</html>

What you should keep in mind is that different components respond to their corresponding HTML differently - as an example, the label simply replaces the contents of its HTML markup with its string representation. The list item, on the other hand, uses its markup as a 'prototype'. It then loops over its model objects, calling populateItem with each to create the sub-component trees for the various ListItem objects. The thing to remember is that none of these Wicket objects (the Label, the ListItem) are magical - if you needed some specialized markup to be handled in a way that Wicket isn't familiar, it is a reasonable process to create custom components. Also keep in mind that Wicket has many, many other components similar to the ListItem to provide for the common cases that show up (including Links, BookmarkablePageLinks, Buttons, Forms, Panels - reusable page chunks, Borders -theme-ing for a site/component, and on and on).

Remember also that these HTML markup pages are designed to be browser-friendly - here is what mine looks like by just looking at the HTML page with my browser:

Configuration

Next, the mandatory configuration. All we need now is just to register the WicketServlet in the web.xml file so that the servlet container can start Wicket, and Wicket can start your application:

<?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>Aloha Application</display-name>
    <servlet>
        <servlet-name>wicket</servlet-name>
        <servlet-class>wicket.protocol.http.WicketServlet</servlet-class>
        <init-param>
          <param-name>applicationClassName</param-name>
          <param-value>com.javalobby.tnt.wicket.aloha.AlohaApplication</param-value>
        </init-param>
        <init-param>
          <param-name>aloha-app-setting</param-name>
          <param-value>This is an example app-specific setting.</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>wicket</servlet-name>
        <url-pattern>/app</url-pattern>
    </servlet-mapping>
</web-app>

Finally, we can ship the contents of this project to a Java application server. Here is the final WAR-file layout:

WEB-INF/
|
*---classes/
|   |
|   *---com/javalobby/tnt/wicket/aloha/
|   |   |
|   |   *--- AlohaApplication.class - Application definition
|   |   | 
|   |   *--- AlohaPage.class - AlohaPage component definition
|   |   |
|   |   *--- AlohaPage.html - Associatied HTML markup for aloha page.
|   |
|   *--- log4j.properties - log4j properties of your making (or java.util.logging properties)
|
*--- web.xml - The web.xml file.

Once the application server starts, we see this print in our log:

 
This is an example app-specific setting.

That is coming from the combination of the init-param in our web.xml and this line of code in our application class:

// Potentially get custom settings from web.xml
System.out.println(getWicketServlet().getInitParameter("aloha-app-setting"));

I configured Wicket on the '/jlwicket' context of my application server on port 8080, so the URL I am hitting to get to this application is http://localhost:8080/jlwicket/app . Here is a screenshot of the final result. Contrast and compare it to the 'prototype' UI from the XHTML we browsed above:

This is a very quick and dirty sketch of playing with Wicket - but I highly suggest you pull down the latest and give it a shot. It's still a young framework, but the methodology and approach is very unique and very powerful.

Until next time,

R.J. Lorimer
Contributing Editor - rj -at- javalobby.org
Author              - http://www.coffee-bytes.com
Software Consultant - http://www.numbersix.com

Wicket: A Little Bit About Wicket by R.J. Lorimer - Jan 2, 2006 11:48 PM
Re: Wicket: A Little Bit About Wicket by David Heffelfinger - Jan 3, 2006 10:50 AM
Re: Wicket: A Little Bit About Wicket by Riyad Kalla - Jan 3, 2006 1:07 PM
Re: Wicket: A Little Bit About Wicket by Ali Anwar - Jan 3, 2006 4:05 PM