GuestBook

The GuestBook application allows users to enter comments that appear on a page like a weblog. Drawing the list of comments is very easy with the Wicket ListView component. This example also gives an impression of what form handling is like.

Tables

The Comment POJO model is very straightforward:

Comment.java

public class Comment implements Serializable
{
	private String text;
	private Date date = new Date();

	public Comment()
	{
	}

	public Comment(final Comment comment)
	{
		this.text = comment.text;
		this.date = comment.date;
	}

	public String getText()
	{
		return text;
	}

	public void setText(String text)
	{
		this.text = text;
	}

	public Date getDate()
	{
		return date;
	}

	public void setDate(Date date)
	{
		this.date = date;
	}
}

The GuestBook constructor adds a CommentForm and a ListView of the comments. Notice how the model is passed in as the second argument to the ListView constructor. Then as the view renders, the populateItem method is called passing in a ListItem container for the current row in the list. The implementation below obtains the Comment POJO from the list item and adds label components for the date and text of the Comment. This is all accomplished in just a few lines of code.

GuestBook.java

package wicket.examples.guestbook;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import wicket.examples.WicketExamplePage;
import wicket.markup.html.basic.Label;
import wicket.markup.html.basic.MultiLineLabel;
import wicket.markup.html.form.Form;
import wicket.markup.html.form.TextArea;
import wicket.markup.html.list.ListItem;
import wicket.markup.html.list.ListView;

public final class GuestBook extends WicketExamplePage
{
	private static final List commentList = new ArrayList();
	private final ListView commentListView;

	public GuestBook()
	{
		add(new CommentForm("commentForm"));
		add(commentListView = new ListView("comments", commentList)
		{
			public void populateItem(final ListItem listItem)
			{
				final Comment comment = (Comment)listItem.getModelObject();
				listItem.add(new Label("date", comment.getDate()));
				listItem.add(new MultiLineLabel("text", comment.getText()));
			}
		});
	}

	public final class CommentForm extends Form
	{
		private final Comment comment = new Comment();

		public CommentForm(final String componentName)
		{
			super(componentName);
			add(new TextArea("text", comment, "text"));
		}

		public final void onSubmit()
		{
			final Comment newComment = new Comment(comment);
			newComment.setDate(new Date());
			synchronized (commentListView.getModelLock())
			{
				commentList.add(0, newComment);
			}
			commentListView.invalidateModel();
			comment.setText("");
		}
	}
}

When the CommentForm is submitted, the onSubmit() method is called. Notice that nothing gets the value of the TextArea that was added in the CommentForm constructor. This is because the comment is the model and the third parameter to the TextArea constructor specified the property of the model to update. So all onSubmit() has to do is create a new comment from the model that was updated and add it to the comment list. When the page redraws, the new list will be rendered.

The synchronized block is present to ensure that the shared static model used by commentListView (commentList) is only updated by one thread at a time. Remember, this is a multi-user application with a shared model!

Finally, you may notice the call to commentListView.invalidateModel(). This informs the list view that its model has been modified. In more advanced usage scenarios, this would allow Wicket to expire stale pages accessed with the browser's back button.

In the HTML below, notice the way that the TextArea component is being nested inside the CommentForm. Wicket is able to keep everything straight because the Java Component.add() calls have to result in the same nesting structure as the HTML. Finally, notice the <wicket:remove> block. This is simply markup that is there for previewing purposes only. When the page renders, it is stripped out.

GuestBook.html

<html>
<body>
  <form wicket:id = "commentForm">
    Add your comment here:
    <p>
    <textarea wicket:id = "text">This is a comment</textarea>
    <p>
    <input type = "submit" value = "Submit"/>
  </form>
  <p>
  <span wicket:id = "comments">
    <p>
	    <span wicket:id = "date">1/1/2004</span><br>
	    <span wicket:id = "text">Comment text goes here.</span>
	</p>
  </span>
  <wicket:remove>
    <p>
	    1/2/2004<br/>
	    More comment text here.
    </p>
  </wicket:remove>
</body>
</html>