wicket tutorial

63
Wicket Application Development i Wicket Application Development

Upload: sandeep-mandori

Post on 26-Oct-2014

253 views

Category:

Documents


1 download

DESCRIPTION

wicket tutorial for beginners and experience ones.

TRANSCRIPT

Page 1: Wicket Tutorial

Wicket Application Developmenti

Wicket Application Development

VIKAS
Typewriter
started 6-June-2011
Page 2: Wicket Tutorial

Copyright © 2010 H. Turgut Uyar <[email protected]>

This tutorial is released under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported Li-cense.

You are free:

• to Share — to copy, distribute and transmit the work

• to Remix — to adapt the work

Under the following conditions:

• Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any waythat suggests that they endorse you or your use of the work).

• Noncommercial — You may not use this work for commercial purposes.

• Share Alike — If you alter, transform, or build upon this work, you may distribute the resulting work only underthe same or similar license to this one.

You can find more information on the page: http://creativecommons.org/licenses/by-nc-sa/3.0/.

Page 3: Wicket Tutorial

Wicket Application Developmentiii

Contents

1 Basics 1

1.1 Creating the Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Dynamic Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.3 Adding Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.4 Shorter Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2 Application Structure 13

2.1 Adding Stylesheets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2 Shared Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3 Data Model 19

3.1 Movies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.2 Displaying Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.3 Movie Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4 Forms 27

4.1 Text Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

4.2 Check Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5 Data Persistence 37

5.1 A Collection Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

5.2 JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

A Development Environment 45

A.1 Installing NetBeans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

A.2 Installing the Wicket Plugin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

B Solutions to Exercises 49

Page 4: Wicket Tutorial
Page 5: Wicket Tutorial

Wicket Application Developmentv

List of Figures

1.1 Screenshot: Home page containing a title and a link to the movie list page . . . . . . . . . . . . . . . 1

1.2 Screenshot: NetBeans new project category form . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3 Screenshot: NetBeans new project name form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.4 Screenshot: NetBeans new project server form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.5 Screenshot: NetBeans new project framework form . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.6 Screenshot: NetBeans new Wicket project default files . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.7 Listing: Initial home page template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.8 Listing: Initial home page class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.9 Listing: Home page template showing the current date and time . . . . . . . . . . . . . . . . . . . . 6

1.10 Listing: Home page class providing the current date and time . . . . . . . . . . . . . . . . . . . . . . 6

1.11 Listing: Initial movie list page template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.12 Listing: Initial movie list page class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.13 Listing: Home page template with link to movie list page . . . . . . . . . . . . . . . . . . . . . . . . 9

1.14 Listing: Movie list page link class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

1.15 Listing: Home page class constructor with link component to movie list page . . . . . . . . . . . . . 10

1.16 Listing: Home page class constructor using shorter code . . . . . . . . . . . . . . . . . . . . . . . . 11

2.1 Screenshot: Home page containing style sheet and navigation panel . . . . . . . . . . . . . . . . . . 13

2.2 Listing: Application style sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.3 Listing: Home page template with style sheet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.4 Listing: Home page class constructor with style sheet component . . . . . . . . . . . . . . . . . . . . 15

2.5 Listing: Base page class with style sheet component . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.6 Listing: Home page class extending the base page class . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.7 Listing: Navigation panel template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.8 Listing: Navigation panel class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.9 Listing: Home page template with navigation panel . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

2.10 Listing: Base page class constructor with navigation panel . . . . . . . . . . . . . . . . . . . . . . . 18

2.11 Listing: Home page class with navigation panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

Page 6: Wicket Tutorial

3.1 Screenshot: Movie list page populated with test data . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.2 Listing: Movie class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.3 Listing: Movie list template using a list view . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

3.4 Listing: Movie list page class with sample movie data . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3.5 Listing: Property list view component for movie list . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

3.6 Listing: Movie collection class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

3.7 Listing: Application class containing the collection object . . . . . . . . . . . . . . . . . . . . . . . . 24

3.8 Listing: Movie list page class constructor getting movie list from application . . . . . . . . . . . . . . 25

3.9 Screenshot: Movie display page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3.10 Screenshot: Movie list page with links to movie display pages . . . . . . . . . . . . . . . . . . . . . 26

4.1 Screenshot: Movie edit page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

4.2 Screenshot: Movie list page with delete option . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

4.3 Listing: Page template for editing a movie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

4.4 Listing: Movie edit form class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4.5 Listing: Movie edit page class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4.6 Listing: Header panel template with link to movie adding page . . . . . . . . . . . . . . . . . . . . . 31

4.7 Listing: Header panel class constructor with link component to movie adding page . . . . . . . . . . 31

4.8 Listing: Movie list template with check boxes for entries . . . . . . . . . . . . . . . . . . . . . . . . 32

4.9 Listing: Movie list form class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

4.10 Listing: Movie list page class containing movie list form component . . . . . . . . . . . . . . . . . . 35

5.1 Screenshot: Creating a folder for external libraries in Netbeans . . . . . . . . . . . . . . . . . . . . . 38

5.2 Listing: Movie collection interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

5.3 Listing: Movie collection interface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

5.4 Screenshot: NetBeans project properties form for external libraries . . . . . . . . . . . . . . . . . . . 40

5.5 Listing: Movie class with id attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

5.6 Listing: Movie collection class using a database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

5.7 Listing: Getting movies from a collection using JDBC . . . . . . . . . . . . . . . . . . . . . . . . . 43

5.8 Listing: Adding a movie to a collection using JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

5.9 Listing: Deleting a movie from a collection using JDBC . . . . . . . . . . . . . . . . . . . . . . . . 44

5.10 Listing: Updating a movie in a collection using JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . 44

A.1 Screenshot: NetBeans install welcome page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

A.2 Screenshot: NetBeans install option customization form . . . . . . . . . . . . . . . . . . . . . . . . . 46

A.3 Screenshot: NetBeans Wicket plugin installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

Page 7: Wicket Tutorial

Wicket Application Developmentvii

Preface

This tutorial aims to demonstrate how to build an application using the Apache Wicket web framework. You can findmore information about the Wicket project on its web site:

http://wicket.apache.org/

Although the application code does not depend on any particular development environment, the narration makes useof NetBeans features and it can be easier to use NetBeans when repeating the steps explained in the tutorial. You canfind some installation notes about NetBeans in Appendix A.

WarningPlease keep in mind that this is not a "best practices" tutorial; it just tries to make it easier to understand theWicket framework for a beginner. Although I have prepared this tutorial to the best of my understanding onthe subject, it may still contain errors, omissions, and improper uses of Java or Wicket features. If you haveany corrections or suggestions, please e-mail them to me. Thanks.

VIKAS
Underline
Page 8: Wicket Tutorial
Page 9: Wicket Tutorial

Wicket Application Development1 / 55

Chapter 1

Basics

We will first start by creating a simple home page containing only a page title. Then we will add the current dateand time to this page to show how dynamic elements are handled in Wicket. Next, we will create a second page alsocontaining only a page title. This second page will be populated with the list of movies in later chapters. Finally, wewill provide a link from the home page to the movie list page. In the end, the home page will look like in Figure 1.1.

Figure 1.1: Screenshot: Home page containing a title and a link to the movie list page

1.1 Creating the Project

Creating a Wicket project requires several configuration steps. Fortunately, the Wicket plugin for NetBeans cangenerate and manage these configuration files so that we won’t have to deal with them. To start the project, choose"File→ New Project" from the main menu and fill in the requested information as follows:

• First, select "Java Web→Web Application" as the project category (Figure 1.2).

• Next, specify the name of the project as MovieDB. You can accept the default project location suggested by Net-Beans (Figure 1.3).

• In the third step, select "Apache Tomcat" as the server (Figure 1.4).

• Finally, select "Wicket" as your framework and type itucs.blg361.moviedb as the main package (Figure 1.5).

VIKAS
Underline
VIKAS
Underline
VIKAS
Underline
VIKAS
Underline
Page 10: Wicket Tutorial

Figure 1.2: Screenshot: NetBeans new project category form

Figure 1.3: Screenshot: NetBeans new project name form

Figure 1.4: Screenshot: NetBeans new project server form

Page 11: Wicket Tutorial

Wicket Application Development3 / 55

Figure 1.5: Screenshot: NetBeans new project framework form

The project will be created with some default files for a typical Wicket application (Figure 1.6). The "Projects" paneseparates the project files into groups such as source packages and configuration files. We will only work with the"Source Packages" group which, as seen in the screenshot, contains a package with the name we have specified atproject creation. All of the files we will edit will go into this package.

In order to simplify the discussion, remove the following files from the project: BasePage.java, HeaderPanel.html, HeaderPanel.java, and style.css. Of the remaining files, leave Application.java as it is.Modify the contents of the files HomePage.html and HomePage.java as given in Figure 1.7 and Figure 1.8,respectively. When you run the project after applying these changes, you should see the text "MovieDB Homepa-ge" in your browser.

VIKAS
Underline
VIKAS
Underline
Page 12: Wicket Tutorial

Figure 1.6: Screenshot: NetBeans new Wicket project default files

vgup30
Typewriter
07-June-2011
vgup30
Typewriter
Page 13: Wicket Tutorial

Wicket Application Development5 / 55

1 <?xml version="1.0" encoding="UTF-8"?>2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">4 <html xmlns:wicket="http://wicket.apache.org">5 <head>6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>7 <title>MovieDB</title>8 </head>9 <body>

10 <h1>MovieDB Homepage</h1>11 </body>12 </html>

Figure 1.7: Listing: Initial home page template

1 package itucs.blg361.moviedb;2

3 import org.apache.wicket.markup.html.WebPage;4

5 public class HomePage extends WebPage {6

7 public HomePage() {8 }9 }

Figure 1.8: Listing: Initial home page class

This initial version of the application consists of only one web page and there is no dynamic content in that page. InWicket, we have to write two files for every page in the application: one is an HTML file that contains the templateof the page, and the other is a Java source file containing the components that control the dynamic elements in thetemplate. The name of the class (and therefore the base name of the Java source file) has to be the same as the basename of the HTML template file, as in HomePage.java and HomePage.html. Since, in our first example, thereis no dynamic element in the template, there is no need for the class to supply any information to the template.

1.2 Dynamic Content

Let us add the current date and time to the home page. We change the template as in Figure 1.9. The lines 12-14contain the markup that will display the date and time. The wicket:id attribute indicates that the contents of thisdiv element are dynamic. Therefore, the date and time on line 13 is just a placeholder to be replaced by the dataprovided by a Wicket component at runtime.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 14: Wicket Tutorial

1 <?xml version="1.0" encoding="UTF-8"?>2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">4 <html xmlns:wicket="http://wicket.apache.org">5 <head>6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>7 <title>MovieDB</title>8 </head>9 <body>

10 <h1>MovieDB Homepage</h1>11

12 <div style="text-align: right; font-size: 70%" wicket:id="datetime">13 Tue May 25 14:47:56 EEST 201014 </div>15 </body>16 </html>

Figure 1.9: Listing: Home page template showing the current date and time

For every dynamic element in the template, there has to be a corresponding component in the Java controller class.The template element and the component are matched using their Wicket id attributes. In our example, that meansthat the HomePage class must contain a Wicket component with the Wicket id datetime. We have to choose asuitable Wicket component that can supply the requested data. In this case, since the data is a simple string, we canuse the Wicket Label component (Figure 1.10). The line 11 shows how to instantite a label component: the firstparameter is the Wicket id, and the second parameter is the string content of the label. When this component is addedto the page (line 12), the connection between the template element and the label component will be established.

1 package itucs.blg361.moviedb;2

3 import java.util.Date;4 import org.apache.wicket.markup.html.WebPage;5 import org.apache.wicket.markup.html.basic.Label;6

7 public class HomePage extends WebPage {8

9 public HomePage() {10 Date now = new Date();11 Label labelDateTime = new Label("datetime", now.toString());12 this.add(labelDateTime);13 }14 }

Figure 1.10: Listing: Home page class providing the current date and time

TipNote that you have to import the necessary Wicket component class (line 5). You can use the NetBeans autocom-plete feature to simplify this. When writing the label construction statement (line 11), type the first few characters ofthe component (for example, Lab) and hit Ctrl-Space. NetBeans will suggest possible imports starting with theseletters. If you select the Apache Wicket Label component, NetBeans will autocomplete the text as "Label" and addthe import statement to the beginning of the file.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 15: Wicket Tutorial

Wicket Application Development7 / 55

The application, as implemented so far, will run as follows:

• An Application object will be instantiated. This object will set the HomePage class as the entry page of theapplication.

• A HomePage object will be instantiated. This, in turn, will instantiate a Label object with the Wicket id date-time and set the current date and time as its contents. This label will be added to the page.

• The HomePage.html template will be used to display the page. All elements which do not have a Wicket id willbe displayed as they are. The contents of the div element with the Wicket id datetime will be replaced by thecontent of the label component with the same id in the HomePage object.

Adding a component to another component creates a hierarchy between the two. For example, when we added thelabel component to the page component, it made the label a sub-component of the page. The HTML template alsohas a hierarchy due to the nesting of the HTML tags. Wicket matches the hierarchy of the HTML template to thehierarchy of the Java components. For example, consider the template below where the span element is nested insidethe div element:

<body><div wicket:id="x">

some text<span wicket:id="y">some other text</span>

</div></body>

The corresponding Java page component could contain code like given below. Note that, the componentX (Wicketid x) is added to this (the page component), whereas componentY (Wicket id y) is added to componentX.

SomeComponent componentX = new SomeComponent("x");this.add(componentX);SomeOtherComponent componentY = new SomeOtherComponent("y");componentX.add(componentY);

The parent component of any component can be retrieved using its getParent method. Continuing with the exam-ple above, the following code will assign componentX to parent:

SomeComponent parent = (SomeComponent) componentY.getParent();

1.3 Adding Links

Now we want to create a second page which will be responsible for listing the movies in the collection. But at first,the page will only contain some static text, it will be populated in later chapters. To create this page, right click on theitucs.blg361.moviedb package in the "Projects" pane, select "New → Wicket Page" from the context menuand enter MovieListPage as the name. This will create two files as explained before: MovieListPage.htmland MovieListPage.java. Modify the template as in Figure 1.11. Again, since there is no dynamic element inthis template, the corresponding class is mostly empty (Figure 1.12).

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 16: Wicket Tutorial

1 <?xml version="1.0" encoding="UTF-8"?>2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">4 <html xmlns:wicket="http://wicket.apache.org">5 <head>6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>7 <title>MovieDB</title>8 </head>9 <body>

10 <h2>Movie List</h2>11 </body>12 </html>

Figure 1.11: Listing: Initial movie list page template

1 package itucs.blg361.moviedb;2

3 import org.apache.wicket.markup.html.WebPage;4

5 public final class MovieListPage extends WebPage {6

7 public MovieListPage() {8 }9 }

Figure 1.12: Listing: Initial movie list page class

Our next step will be to provide a link from the home page to the movie list page. In order to achieve this, wemodify the template as in Figure 1.13. The code for adding the link is on line 13. This line states that the necessaryinformation for the a element will be supplied by a Wicket component with the id list_movies in the HomePageclass. As before, the href attribute of the a element is just a placeholder and will be replaced by the value suppliedby a Wicket link component.

vgup30
Underline
Page 17: Wicket Tutorial

Wicket Application Development9 / 55

1 <?xml version="1.0" encoding="UTF-8"?>2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">4 <html xmlns:wicket="http://wicket.apache.org">5 <head>6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>7 <title>MovieDB</title>8 </head>9 <body>

10 <h1>MovieDB Homepage</h1>11

12 <ul>13 <li><a href="#" wicket:id="list_movies">List movies</a></li>14 </ul>15

16 <div style="text-align: right; font-size: 70%" wicket:id="datetime">17 Tue May 25 14:47:56 EEST 201018 </div>19 </body>20 </html>

Figure 1.13: Listing: Home page template with link to movie list page

The Wicket framework provides an abstract Link class which can be extended to create a new link class. For the newclass, we have to implement a constructor and override the onClick method that specifies what will happen whenthe link is clicked. To create this class, right click on the package name, select "New→ Java Class" and give it thename MovieListPageLink. Note that since this is not a Wicket page, it does not need a template associated withit.

TipWhen you add the superclass declaration to the class to make the line read

public class MovieListPageLink extends Link {

you will see a light bulb in the line number column next to this line indicating that there are some problems:

• First, it will complain that it cannot find the symbol for the class Link. To fix this, click on the light bulb and choosethe suggestion to add the import for the Wicket Link class.

• Next, it will say that you have to override the onClick method. To fix this, again click on the light bulb and choosethe suggestion to implement all abstract methods.

• And finally, it will require you to write a constructor for this class.

The resulting file is given in Figure 1.14. Constructor methods of Wicket component classes take an id value as theirfirst parameter (their Wicket id). Since there is nothing special to do, the constructor will just invoke the constructorof its superclass with the same parameter (line 8). The onClick method creates a new instance of a movie list page(line 13) and calls the setResponsePage method to direct the user to this newly created page (line 14).

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 18: Wicket Tutorial

1 package itucs.blg361.moviedb;2

3 import org.apache.wicket.markup.html.link.Link;4

5 public class MovieListPageLink extends Link {6

7 public MovieListPageLink(String id) {8 super(id);9 }

10

11 @Override12 public void onClick() {13 MovieListPage target = new MovieListPage();14 this.setResponsePage(target);15 }16 }

Figure 1.14: Listing: Movie list page link class

The final step is to add an instance of this link to the constructor of the home page (Figure 1.15).

1 public HomePage() {2 MovieListPageLink movieListLink = new MovieListPageLink("list_movies");3 this.add(movieListLink);4

5 Date now = new Date();6 Label labelToday = new Label("datetime", now.toString());7 this.add(labelToday);8 }

Figure 1.15: Listing: Home page class constructor with link component to movie list page

1.4 Shorter Code

There are a few things we can do to make the code shorter. First of all, we do not have to assign the result of everyintermediate step to a variable. For example, when adding the date and time to the home page, we can skip theassignment of the label to a variable and send the label directly as parameter to the add method. That means, we canchange the lines 5-7 of Figure 1.15 as follows:

Date now = new Date();this.add(new Label("datetime", now.toString()));

When the project gets larger, it becomes impractical to create Java files for every custom Wicket component we need.For example, we have to extend the Link class to create a link component for every link with a different target.Instead, we can use Java anonymous classes to reduce the number of files in our project and make it easier to manage.Note that in Figure 1.16, we extend the Wicket Link class where we instantiate a link to the movie list page andtherefore we do not need a MovieListPageLink class anymore.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 19: Wicket Tutorial

Wicket Application Development11 / 55

1 public HomePage() {2 Link movieListLink = new Link("list_movies") {3

4 @Override5 public void onClick() {6 this.setResponsePage(new MovieListPage());7 }8 };9 this.add(movieListLink);

10

11 Date now = new Date();12 this.add(new Label("datetime", now.toString()));13 }

Figure 1.16: Listing: Home page class constructor using shorter code

Exercise. Add a link from the movie list page to the home page. (p. 49)

vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 20: Wicket Tutorial
Page 21: Wicket Tutorial

Wicket Application Development13 / 55

Chapter 2

Application Structure

The pages in a web application share some components such as style sheets and global navigation panels. In thischapter, we will see how to implement such components without repeating code. First, we will add a style sheet tothe application. Then we will create a base page that will contain the components that all pages in the application willacquire. See Figure 2.1 for the screenshot of the resulting home page.

Figure 2.1: Screenshot: Home page containing style sheet and navigation panel

2.1 Adding Stylesheets

We want all our pages to have the same style, so we will add a style sheet to our package. Right click on the packagename in the "Projects" pane and select "New → Other" from the context menu. From that list, select "Web →Cascading Style Sheet" and give it the name style. This will create a file named style.css. Modify this file asgiven in Figure 2.2.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 22: Wicket Tutorial

1 body {2 background-color: white;3 color: #6F6F6F;4 font-family: ’Verdana’, ’Helvetica’, ’Sans-serif’, ’sans’;5 font-size: 10pt;6 padding: 10px 10px 10px 10px;7 margin: 10px 10px 10px 10px;8 }9

10 h1, h2, h3, h4 {11 color: #E9601A;12 }13

14 h2 {15 font-size: 1.25em;16 }17

18 a {19 color: #6F6F6F;20 text-decoration: underline;21 }22

23 th {24 background: #C3C3C3;25 color: white;26 font-weight: bold;27 text-align: left;28 }

Figure 2.2: Listing: Application style sheet

To add this style sheet to the home page, change the head part of its template as in Figure 2.3. The HomePage classnow has to contain a component for this style sheet, so we add a Wicket StyleSheetReference component inthe constructor (Figure 2.4).

1 <head>2 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>3 <title>MovieDB</title>4 <link wicket:id="stylesheet" rel="stylesheet" type="text/css" href="#"/>5 </head>

Figure 2.3: Listing: Home page template with style sheet

vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 23: Wicket Tutorial

Wicket Application Development15 / 55

1 public HomePage() {2 this.add(new StyleSheetReference("stylesheet", HomePage.class,3 "style.css"));4

5 Link movieListLink = new Link("list_movies") {6

7 @Override8 public void onClick() {9 this.setResponsePage(new MovieListPage());

10 }11 };12 this.add(movieListLink);13

14 Date now = new Date();15 this.add(new Label("datetime", now.toString()));16 }

Figure 2.4: Listing: Home page class constructor with style sheet component

2.2 Shared Components

Adding shared components to multiple pages in an application is a tedious and error-prone approach. Therefore, wewould like to be able to specify these at one point and let pages get them from that single source. For instance, in theprevious section, we had to add the style sheet component to every page class. Instead, using inheritance., we can addit to a base page and extend all application pages from this base page. Add a new Java class named BasePage toyour package (careful: a Java class, not a Wicket page; there will be no template for this class). The code of the classis given in Figure 2.5.

1 package itucs.blg361.moviedb;2

3 import org.apache.wicket.markup.html.WebPage;4 import org.apache.wicket.model.IModel;5 import org.apache.wicket.markup.html.resources.StyleSheetReference;6

7 public class BasePage extends WebPage {8

9 public BasePage() {10 this(null);11 }12

13 public BasePage(IModel model) {14 super(model);15 this.add(new StyleSheetReference("stylesheet", BasePage.class,16 "style.css"));17 }18 }

Figure 2.5: Listing: Base page class with style sheet component

Now the HomePage class will extend this BasePage instead of the generic WebPage (Figure 2.6).

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 24: Wicket Tutorial

1 public class HomePage extends BasePage {2

3 public HomePage() {4 Link movieListLink = new Link("list_movies") {5

6 @Override7 public void onClick() {8 this.setResponsePage(new MovieListPage());9 }

10 };11 this.add(movieListLink);12

13 Date now = new Date();14 this.add(new Label("datetime", now.toString()));15 }16 }

Figure 2.6: Listing: Home page class extending the base page class

Another improvement concerns the navigation. We might need links to the home page or movie list page from manypages in the application. So, having a global navigation mechanism where all such links will be available in all pagesmight be a good idea. Wicket provides panels which let us handle components as a group. Add a Wicket Panel namedHeaderPanel to your package and you will again get an HTML template and a Java source file. The template isgiven in Figure 2.7. We are only interested in the lines 9-14, the part where we describe the content of the panel. Thecorresponding Java class (Figure 2.8) places the link components into this panel component.

1 <?xml version="1.0" encoding="UTF-8"?>2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">4 <html xmlns:wicket="http://wicket.apache.org">5 <head>6 <title>MovieDB</title>7 </head>8 <body>9 <wicket:panel>

10 <ul>11 <li><a href="#" wicket:id="home">Home</a></li>12 <li><a href="#" wicket:id="list_movies">List movies</a></li>13 </ul>14 </wicket:panel>15 </body>16 </html>

Figure 2.7: Listing: Navigation panel template

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 25: Wicket Tutorial

Wicket Application Development17 / 55

1 package itucs.blg361.moviedb;2

3 import org.apache.wicket.markup.html.link.Link;4 import org.apache.wicket.markup.html.panel.Panel;5

6 public class HeaderPanel extends Panel {7

8 public HeaderPanel(String id) {9 super(id);

10

11 Link homeLink = new Link("home") {12

13 @Override14 public void onClick() {15 this.setResponsePage(new HomePage());16 }17 };18 this.add(homeLink);19

20 Link movieListLink = new Link("list_movies") {21

22 @Override23 public void onClick() {24 this.setResponsePage(new MovieListPage());25 }26 };27 this.add(movieListLink);28 }29 }

Figure 2.8: Listing: Navigation panel class

Now our actual pages (the home page and the movie list page) will only add this panel component instead of thelink components. The home page template has to be modified as in Figure 2.9. To make this panel available in allpages, we add it to the base page (Figure 2.10). The only component left in the home page is the date and time label(Figure 2.11).

1 <body>2 <div wicket:id="mainNavigation">links to common pages</div>3

4 <h1>MovieDB Homepage</h1>5

6 <div style="text-align: right; font-size: 70%" wicket:id="datetime">7 Tue May 25 14:47:56 EEST 20108 </div>9 </body>

Figure 2.9: Listing: Home page template with navigation panel

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 26: Wicket Tutorial

1 public BasePage(IModel model) {2 super(model);3 this.add(new StyleSheetReference("stylesheet", BasePage.class,4 "style.css"));5 this.add(new HeaderPanel("mainNavigation"));6 }

Figure 2.10: Listing: Base page class constructor with navigation panel

1 public class HomePage extends BasePage {2

3 public HomePage() {4 Date now = new Date();5 this.add(new Label("datetime", now.toString()));6 }7 }

Figure 2.11: Listing: Home page class with navigation panel

Exercise. Arrange the MovieListPage class so that it will use the style sheet and the navigation panel. (p. 50)

vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 27: Wicket Tutorial

Wicket Application Development19 / 55

Chapter 3

Data Model

In this chapter, we will create the Java classes in our data model, that is, the classes for movies and movie collections.First we will implement the movie class and fill the movie list page with some in-place generated test data. Then wewill implement the movie collection class which will hold some application-wide test data. The resulting movie listpage will look like in Figure 3.1.

Figure 3.1: Screenshot: Movie list page populated with test data

3.1 Movies

To represent movies in the application, we implement a plain Java class as in Figure 3.2. At first, it only contains titleand year attributes, along with their getters and setters. Apart from the default constructor which takes no parameters,there is one more constructor which takes the movie title as parameter.

vgup30
Underline
Page 28: Wicket Tutorial

1 package itucs.blg361.moviedb;2

3 public class Movie {4

5 private String title = null;6 private Integer year = null;7

8 public Movie() {9 }

10

11 public Movie(String aTitle) {12 this.setTitle(aTitle);13 }14

15 public void setTitle(String aTitle) {16 this.title = aTitle;17 }18

19 public String getTitle() {20 return this.title;21 }22

23 public void setYear(Integer aYear) {24 this.year = aYear;25 }26

27 public Integer getYear() {28 return this.year;29 }30 }

Figure 3.2: Listing: Movie class

3.2 Displaying Lists

To display a list of movies, we have to connect an HTML template element to a Wicket ListView component.These components are associated with Java lists and every element in the Java list is associated with a ListItemcomponent in the list view. If the Wicket id in the template matches a list view component, the underlying markupwill be generated for each element in the list. We change the code for the movie list template as in Figure 3.3. Thiscode will generate a tr element for each movie in the list. Again, note that, "The Matrix" and "1999" are justplaceholders, they will be replaced when the page is actually rendered.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 29: Wicket Tutorial

Wicket Application Development21 / 55

1 <body>2 <div wicket:id="mainNavigation">links to common pages</div>3

4 <h2>Movie List</h2>5

6 <table>7 <tr wicket:id="movie_list">8 <td>9 <span wicket:id="title">The Matrix</span>

10 (<span wicket:id="year">1999</span>)11 </td>12 </tr>13 </table>14 </body>

Figure 3.3: Listing: Movie list template using a list view

ListView is an abstract class that has to be extended in order to be used (Figure 3.4). By passing the movies list asthe second parameter to the constructor (line 20), we associate it with this list view component and every item (movie)in the list will be associated with the corresponding list item component in this list view. Since we don’t have a datasource to supply us with the movie information at the moment, we generate a sample list (lines 12-18).

When extending the ListView class, we have to implement the populateItem method which will be executedfor every element in the list. The current element will be passed as the item parameter, and we can get the Java objectassociated with this item using its getModelObject method. That means, the item.getModelObject() callon line 24 will give us the reference of the associated movie object. Then we use Wicket Label components todisplay the title and year of the movie on the web page (lines 25-26).

Note the hierarchies in the HTML template and the Java components:

• The Wicket id of the tr element matches the Wicket id of the ListView component object.

• The Wicket id of either of the span elements matches the Wicket id of one of the Label components.

Also note that the text for a label must be a string, so we convert the year of the movie to a string (line 26).

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 30: Wicket Tutorial

1 package itucs.blg361.moviedb;2

3 import java.util.LinkedList;4 import java.util.List;5 import org.apache.wicket.markup.html.basic.Label;6 import org.apache.wicket.markup.html.list.ListItem;7 import org.apache.wicket.markup.html.list.ListView;8

9 public final class MovieListPage extends BasePage {10

11 public MovieListPage() {12 List<Movie> movies = new LinkedList<Movie>();13 Movie movie1 = new Movie("The Shining");14 movie1.setYear(1980);15 movies.add(movie1);16 Movie movie2 = new Movie("Barton Fink");17 movie2.setYear(1991);18 movies.add(movie2);19

20 ListView movieListView = new ListView("movie_list", movies) {21

22 @Override23 protected void populateItem(ListItem item) {24 Movie movie = (Movie) item.getModelObject();25 item.add(new Label("title", movie.getTitle()));26 item.add(new Label("year", movie.getYear().toString()));27 }28 };29 this.add(movieListView);30 }31 }

Figure 3.4: Listing: Movie list page class with sample movie data

Wicket also supports a simpler way of creating custom list views. If your code conforms to a few basic Java conven-tions, Wicket can automatically map the model object (in our case, the movie) to the component (the list view item).The rule is that the model object has to define getters and setters for each of its attributes using a standard interface:

• The name of the getter method for an attribute has to start with "get", followed by the name of the attribute withits first letter capitalized. For instance, if the name of the attribute is "title", the name of the getter has to be"getTitle". This method should take no parameters and return the value of the attribute in a proper format.

• The name of the setter method for an attribute has to start with "set", followed by the name of the attribute with itsfirst letter capitalized. Again, if the name of the attribute is "title", the name of the setter has to be "setTitle".This method should take the value to be assigned to the attribute as its only parameter and return nothing.

• Getters for boolean attributes have to be named starting with "is" instead of "get". For instance, if the attribute isa boolean named "successful", the name of the getter has to be "isSuccessful".

Since our Movie class already conforms to these rules, we just have to extend the PropertyListView classinstead of the ListView class to use this feature (Figure 3.5). Note that, in this code, we do not supply the contentsfor the title and year labels (lines 6-7). For the Wicket id title, Wicket will look for a method named get-Title and for the id year, the method named getYear. Also, the conversion from integer to string for years ishandled automatically.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Rectangle
Page 31: Wicket Tutorial

Wicket Application Development23 / 55

1 PropertyListView movieListView =2 new PropertyListView("movie_list", movies) {3

4 @Override5 protected void populateItem(ListItem item) {6 item.add(new Label("title"));7 item.add(new Label("year"));8 }9 };

Figure 3.5: Listing: Property list view component for movie list

3.3 Movie Collections

Next, we will implement a class that will represent a movie collection. This class will contain a list of movie ob-jects and some methods to interact with that list such as adding or deleting movies and getting a list of all movies(Figure 3.6).

1 package itucs.blg361.moviedb;2

3 import java.util.LinkedList;4 import java.util.List;5

6 public class MovieCollection {7

8 private List<Movie> movies;9

10 public MovieCollection() {11 this.movies = new LinkedList<Movie>();12 }13

14 public List<Movie> getMovies() {15 return this.movies;16 }17

18 public void addMovie(Movie aMovie) {19 this.movies.add(aMovie);20 }21

22 public void deleteMovie(Movie aMovie) {23 this.movies.remove(aMovie);24 }25 }

Figure 3.6: Listing: Movie collection class

In our earlier example, the list of movies was generated by the page that lists the movies. This is obviously not theproper place to generate the collection because there should be one movie collection object which is accessible toall components in the application. Therefore, the better place to generate it would be in the Application class(Figure 3.7). So, we add a collection object member to this class (line 7), instantiate it in the constructor (line 10) and

vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 32: Wicket Tutorial

add a getCollection method which will return this collection (lines 24-26). Again, we provide some sample data(lines 12-17) in order to test our application.

1 package itucs.blg361.moviedb;2

3 import org.apache.wicket.protocol.http.WebApplication;4

5 public class Application extends WebApplication {6

7 private MovieCollection collection;8

9 public Application() {10 this.collection = new MovieCollection();11

12 Movie movie1 = new Movie("The Shining");13 movie1.setYear(1980);14 this.collection.addMovie(movie1);15 Movie movie2 = new Movie("Barton Fink");16 movie2.setYear(1991);17 this.collection.addMovie(movie2);18 }19

20 public Class getHomePage() {21 return HomePage.class;22 }23

24 public MovieCollection getCollection() {25 return this.collection;26 }27 }

Figure 3.7: Listing: Application class containing the collection object

Now that the MovieListPage class does not generate the list of movies, it has to retrieve them from the application.So the lines 12-18 in Figure 3.4 will be replaced by the lines 2-4 in Figure 3.8. We can use the getApplicationmethod of web page classes to get a handle of the application object that contains this web page (note that this is aWicket application object that we have to cast to our Application class as in line 2).

vgup30
Underline
vgup30
Rectangle
vgup30
Underline
Page 33: Wicket Tutorial

Wicket Application Development25 / 55

1 public MovieListPage() {2 Application app = (Application) this.getApplication();3 MovieCollection collection = app.getCollection();4 List<Movie> movies = collection.getMovies();5

6 PropertyListView movieListView =7 new PropertyListView("movie_list", movies) {8

9 @Override10 protected void populateItem(ListItem item) {11 item.add(new Label("title"));12 item.add(new Label("year"));13 }14 };15 this.add(movieListView);16 }

Figure 3.8: Listing: Movie list page class constructor getting movie list from application

The "model" is a very important concept in Wicket development but we have discussed it here very very briefly.You are encouraged to read the section titled "Working with Wicket Models" in the Wicket reference guide:

https://cwiki.apache.org/WICKET/working-with-wicket-models.html

Exercise. Add a page that will display a movie (Figure 3.9). Then, organize the movie list page so that the entries arelinks to pages that will display the selected movie (Figure 3.10). (p. 50)

Figure 3.9: Screenshot: Movie display page

vgup30
Underline
vgup30
Underline
Page 34: Wicket Tutorial

Figure 3.10: Screenshot: Movie list page with links to movie display pages

Page 35: Wicket Tutorial

Wicket Application Development27 / 55

Chapter 4

Forms

In this chapter, we will implement the parts that will enable us to modify the collection. This includes the operationsto add a new movie and to delete an existing movie. Both operations require the use of forms containing componentssuch as text boxes and check boxes. The resulting pages are given in Figure 4.1 and Figure 4.2.

Figure 4.1: Screenshot: Movie edit page

vgup30
Underline
vgup30
Underline
Page 36: Wicket Tutorial

Figure 4.2: Screenshot: Movie list page with delete option

4.1 Text Boxes

First, we will add a new page to our application for adding movies. In order to do this, we need a page to edit the dataof a movie. Add a Wicket page named MovieEditPage to the package and modify its contents as in Figure 4.3.From this template we can see that the corresponding Wicket page class has to contain a component with the Wicketid movie_edit which has to be able to handle forms (line 13). And this component has to contain two othercomponents with the Wicket ids title and year, both of which will be responsible for handling text boxes (lines17 and 21).

vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 37: Wicket Tutorial

Wicket Application Development29 / 55

1 <?xml version="1.0" encoding="UTF-8"?>2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">4 <html xmlns:wicket="http://wicket.apache.org">5 <head>6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>7 <title>MovieDB</title>8 <link wicket:id="stylesheet" rel="stylesheet" type="text/css" href="#"/>9 </head>

10 <body>11 <div wicket:id="mainNavigation">links to common pages</div>12

13 <form action="#" wicket:id="movie_edit">14 <table>15 <tr>16 <th>Title:</th>17 <td><input wicket:id="title" type="text"/></td>18 </tr>19 <tr>20 <th>Year:</th>21 <td><input wicket:id="year" type="text" size="4"/></td>22 </tr>23 </table>24 <input value="Save" name="save" type="submit"/>25 </form>26 </body>27 </html>

Figure 4.3: Listing: Page template for editing a movie

Let us start by creating the form element. Add a new Java class with the name MovieEditForm to the package andspecify the Wicket Form component as its superclass (Figure 4.4). This form component will take the movie objectit will edit as a parameter to its constructor (line 9). The movie object will serve as the model for the component,i.e. it will provide the data for any of the components contained in the page. To achieve this, we create a WicketCompoundPropertyModel object from the movie and set it as the model of this form (lines 12-13).

To control text boxes in the application, we use TextField components. We add two such components to the form(lines 15-16) using the Wicket ids specified in the template. Since we have set a movie object as the model of thisform, the associations between the movie and the components will be handled automatically. For example, wheneverthe contents of the text box for the title needs to be determined, the getTitle method will be called for the movieobject. And when the form is submitted, the setTitle method will be called using the contents of the text box asparameter.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 38: Wicket Tutorial

1 package itucs.blg361.moviedb;2

3 import org.apache.wicket.markup.html.form.Form;4 import org.apache.wicket.markup.html.form.TextField;5 import org.apache.wicket.model.CompoundPropertyModel;6

7 public class MovieEditForm extends Form {8

9 public MovieEditForm(String id, Movie aMovie) {10 super(id);11

12 CompoundPropertyModel model = new CompoundPropertyModel(aMovie);13 this.setModel(model);14

15 this.add(new TextField("title"));16 this.add(new TextField("year"));17 }18

19 @Override20 public void onSubmit() {21 Movie movie = (Movie) this.getModelObject();22 Application app = (Application) this.getApplication();23 MovieCollection collection = app.getCollection();24 collection.addMovie(movie);25 this.setResponsePage(new MovieDisplayPage(movie));26 }27 }

Figure 4.4: Listing: Movie edit form class

When implementing a form, another major task is to specify what will happen when the form is submitted. We do thisby overriding the onSubmit method of the Wicket Form class. For this particular form, we need to add the movieobject to the collection; therefore, we get the movie which is the model object of this form (line 21), we get a handleto the application object (line 22), we get the collection object from the application (line 23), add the movie to thecollection (line 24), and redirect the user to the page that will display this movie (line 25).

Now we have to add this form component to the MovieEditPage class to complete the connection between thetemplate and all the Wicket components (Figure 4.5). This page also takes the movie to be edited as a parameter to itsconstructor (line 5) and passes it to the form component (line 6).

1 package itucs.blg361.moviedb;2

3 public final class MovieEditPage extends BasePage {4

5 public MovieEditPage(Movie aMovie) {6 this.add(new MovieEditForm("movie_edit", aMovie));7 }8 }

Figure 4.5: Listing: Movie edit page class

To provide a link to this page from other pages we add a list item to the markup of the header panel template (Fig-

vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 39: Wicket Tutorial

Wicket Application Development31 / 55

ure 4.6) and a link component to the corresponding Java class (Figure 4.7). When this link is clicked, we instantiatea new movie object and send it to the edit page as parameter (lines 18-19). Note that, since all Movie class con-structors require a title, an empty string is provided as title. Also note that, now that we can add movies to thecollection, we don’t need the sample movie data anymore and we can delete the relevant lines from the constructor ofthe Application class (Figure 3.7 lines 12-17).

1 <body>2 <wicket:panel>3 <ul>4 <li><a href="#" wicket:id="home">Home</a></li>5 <li><a href="#" wicket:id="list_movies">List movies</a></li>6 <li><a href="#" wicket:id="add_movie">Add movie</a></li>7 </ul>8 </wicket:panel>9 </body>

Figure 4.6: Listing: Header panel template with link to movie adding page

1 public HeaderPanel(String id) {2 super(id);3

4 Link homeLink = new Link("home") {5 ...6 };7 this.add(homeLink);8

9 Link movieListLink = new Link("list_movies") {10 ...11 };12 this.add(movieListLink);13

14 Link movieAddLink = new Link("add_movie") {15

16 @Override17 public void onClick() {18 Movie movie = new Movie("");19 this.setResponsePage(new MovieEditPage(movie));20 }21 };22 this.add(movieAddLink);23 }

Figure 4.7: Listing: Header panel class constructor with link component to movie adding page

4.2 Check Boxes

Our next step is to delete movies from the collection. We will change the movie list page so that there will be a checkbox next to every movie and a delete button at the bottom of the page. When the delete button is pressed all thechecked movies will be deleted.

vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 40: Wicket Tutorial

First, we change the template for the movie list page as in Figure 4.8. The changes from the earlier version (Figure 3.3)are as follows:

• There is a check box in front of every movie link (line 10). These check boxes will be controlled by Wicket Checkcomponents in the Java code.

• We will group check boxes so that we can handle them easier using a CheckGroup component in Wicket. We usethe div element on line 7 to establish this connection.

• Since check boxes need to be part of a form, we put all the elements under a form element (line 6).

• There is now a button for submitting this form (line 20).

1 <body>2 <div wicket:id="mainNavigation">links to common pages</div>3

4 <h2>Movie List</h2>5

6 <form action="#" wicket:id="movie_list_form">7 <div wicket:id="selected_movies">8 <table>9 <tr wicket:id="movie_list">

10 <td><input type="checkbox" wicket:id="selected"/></td>11 <td>12 <a href="#" wicket:id="movie_link">13 <span wicket:id="title">The Matrix</span>14 (<span wicket:id="year">1999</span>)15 </a>16 </td>17 </tr>18 </table>19 </div>20 <input type="submit" value="Delete" name="delete"/>21 </form>22 </body>

Figure 4.8: Listing: Movie list template with check boxes for entries

The movie list view we have used so far is no longer sufficient for handling this template. We need a movie list formthat will include the movie list view. The implementation is given in Figure 4.9. This component will keep the listof selected movies in the selectedMovies attribute (line 14), which is initialized as an empty linked list in theconstructor (line 18). The constructor creates and adds a check box group component (line 20-22) which it associateswith this list. This way, all movies associated with the check boxes under this check group will be elements of the list.

Until now, the movie list view used to be directly under the movie list page but now it has to be placed under this checkgroup according to the hierarchy in the HTML template. Therefore we move the code generating the movie list viewfrom the MovieListPage class to this class (lines 24-41) and add the list view under the check group (line 42).This code contains a new statement for adding a check box to the list item (line 38). Sending the model of the item asa parameter to the constructor of the Check component (via the getModel method) creates the connection betweenthe check box and the check group it is in. The MovieListPage class now only needs the form component, so itsconstructor will be as in Figure 4.10.

vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 41: Wicket Tutorial

Wicket Application Development33 / 55

As before, we override the onSubmit method to determine the action to take when the submit button is clicked.Since the selectedMovies attribute keeps the list of movies selected for deletion, we iterate over its elements anddelete them from the collection (lines 49-51). Then we redirect the user to the movie list page (line 52).

vgup30
Underline
Page 42: Wicket Tutorial

1 package itucs.blg361.moviedb;2

3 import java.util.LinkedList;4 import java.util.List;5 import org.apache.wicket.markup.html.basic.Label;6 import org.apache.wicket.markup.html.form.Check;7 import org.apache.wicket.markup.html.form.CheckGroup;8 import org.apache.wicket.markup.html.form.Form;9 import org.apache.wicket.markup.html.list.ListItem;

10 import org.apache.wicket.markup.html.list.PropertyListView;11

12 public class MovieListForm extends Form {13

14 private List<Movie> selectedMovies;15

16 public MovieListForm(String id) {17 super(id);18 this.selectedMovies = new LinkedList<Movie>();19

20 CheckGroup movieCheckGroup =21 new CheckGroup("selected_movies", this.selectedMovies);22 this.add(movieCheckGroup);23

24 Application app = (Application) this.getApplication();25 MovieCollection collection = app.getCollection();26 List<Movie> movies = collection.getMovies();27

28 PropertyListView movieListView =29 new PropertyListView("movie_list", movies) {30

31 @Override32 protected void populateItem(ListItem item) {33 Movie movie = (Movie) item.getModelObject();34 MovieDisplayPageLink movieLink =35 new MovieDisplayPageLink("movie_link", movie);36 movieLink.add(new Label("title"));37 movieLink.add(new Label("year"));38 item.add(new Check("selected", item.getModel()));39 item.add(movieLink);40 }41 };42 movieCheckGroup.add(movieListView);43 }44

45 @Override46 public void onSubmit() {47 Application app = (Application) this.getApplication();48 MovieCollection collection = app.getCollection();49 for (Movie movie : this.selectedMovies) {50 collection.deleteMovie(movie);51 }52 this.setResponsePage(new MovieListPage());53 }54 }

Figure 4.9: Listing: Movie list form class

Page 43: Wicket Tutorial

Wicket Application Development35 / 55

1 public MovieListPage() {2 MovieListForm movieListForm = new MovieListForm("movie_list_form");3 this.add(movieListForm);4 }

Figure 4.10: Listing: Movie list page class containing movie list form component

Exercise. Add a link to the movie display page which, when clicked, will take the user to the movie edit page. Aftersaving the movie should be to updated in the collection (not added a second time). (p. 52)

Page 44: Wicket Tutorial
Page 45: Wicket Tutorial

Wicket Application Development37 / 55

Chapter 5

Data Persistence

A major problem with the application as implemented so far is that the data the user enters do not persist. Every time,the application starts with an empty collection and added movies are lost when the application is shut down. In thischapter we will see how to store the data in a database. This chapter has nothing to do with Wicket; it just uses variousdata persistence methods and assumes that the reader knows about these.

Let us create a folder to hold the JAR files of the external packages we will need in our project. Go to the "Files" tabnext to the "Projects" tab in the left pane, right click on the toplevel project entry ("MovieDB") and select "New→Other". In the file type selection form, select "Other" from the left list and "Folder" from the right list (Figure 5.1). Inthe next form, type "lib" as the folder name.

vgup30
Typewriter
8-June-2011, Wednesday
vgup30
Underline
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 46: Wicket Tutorial

Figure 5.1: Screenshot: Creating a folder for external libraries in Netbeans

5.1 A Collection Interface

In order to make it easier to switch between different persistence mechanisms, we will first create a simple interfacethat all these mechanisms will implement. In the "Projects" pane, right click on the "itucs.blg361.moviedb" sourcepackage and create a new Java interface with the name "IMovieCollection". The interface has to contain the methodsas shown in the Figure 5.2.

vgup30
Underline
Page 47: Wicket Tutorial

Wicket Application Development39 / 55

1 public interface IMovieCollection {2

3 public List<Movie> getMovies();4

5 public void addMovie(Movie aMovie);6

7 public void deleteMovie(Movie aMovie);8

9 public void updateMovie(Movie aMovie);10 }

Figure 5.2: Listing: Movie collection interface.

The MovieCollection class based on lists already implements this interface; we just have to acknowledge thisby changing the class definition:

public MovieCollection implements IMovieCollection {...

}

We also have to change the code pieces that reference the MovieCollection class so that they will use theIMovieCollection interface. That means changing the Application class as in Figure 5.3 so that the only placewhere the actual collection implementation is used will be the constructor of the application object. Also the referencesto the MovieCollection class in the MovieEditForm and MovieListForm classes have to be changed tothe IMovieCollection interface.

1 public class Application extends WebApplication {2

3 private IMovieCollection collection;4

5 public Application() {6 this.collection = new MovieCollection();7 }8

9 public Class getHomePage() {10 return HomePage.class;11 }12

13 public IMovieCollection getCollection() {14 return this.collection;15 }16 }

Figure 5.3: Listing: Movie collection interface.

5.2 JDBC

To keep things simple and to avoid database installation or configuration issues, we will use SQLite as our database.Download the JDBC driver JAR file for SQLite from the following page and put it in the "lib" directory you havecreated:

vgup30
Underline
vgup30
Underline
Page 48: Wicket Tutorial

http://www.xerial.org/trac/Xerial/wiki/SQLiteJDBC

Right click on your project in the NetBeans "Projects" pane, select "Properties" from the context menu and add thedownloaded JAR file to your project using the "Add JAR/Folder" button in the "Libraries" menu (Figure 5.4).

Figure 5.4: Screenshot: NetBeans project properties form for external libraries

Next, create a database with the name "movies.db" in your home directory and create a table in it using thefollowing SQL statement:

CREATE TABLE MOVIE (ID INTEGER PRIMARY KEY, TITLE VARCHAR(80), YEAR INTEGER)

TipYou can use the SQLite Manager add-on for Firefox to manage SQLite databases:https://addons.mozilla.org/en-US/firefox/addon/5817/

As indicated by the SQL table creation statement above, movie objects now have id attributes. We modify our Movieclass (Figure 5.5) to add this attribute (line 3) and its getter and setter methods (lines 9-15).

Page 49: Wicket Tutorial

Wicket Application Development41 / 55

1 public class Movie {2

3 private Integer id = null;4 private String title;5 private Integer year;6

7 ...8

9 public void setId(Integer anId) {10 this.id = anId;11 }12

13 public Integer getId() {14 return this.id;15 }16

17 ...18 }

Figure 5.5: Listing: Movie class with id attribute

Now we have to implement a MovieCollectionJDBC class (Figure 5.6) which will implement our commoncollection interface but this time using a database to store the data (line 1-3). The database is assumed to be a file withthe name "movies.sqlite" in the user’s home directory (13-16).

Page 50: Wicket Tutorial

1 public class MovieCollectionJDBC implements IMovieCollection {2

3 private Connection db;4

5 public MovieCollectionJDBC() {6 try {7 Class.forName("org.sqlite.JDBC");8 } catch (ClassNotFoundException ex) {9 throw new UnsupportedOperationException(ex.getMessage());

10 }11

12 try {13 String homeDir = System.getProperty("user.home");14 String dbFileName = homeDir + File.separator + "movies.sqlite";15 String jdbcURL = "jdbc:sqlite:" + dbFileName;16 this.db = DriverManager.getConnection(jdbcURL);17 } catch (SQLException ex) {18 throw new UnsupportedOperationException(ex.getMessage());19 }20 }21

22 public List<Movie> getMovies() { ... }23

24 public void addMovie(Movie aMovie) { ... }25

26 public void deleteMovie(Movie aMovie) { ... }27

28 public void updateMovie(Movie aMovie) { ... }29 }

Figure 5.6: Listing: Movie collection class using a database

The methods for getting the movie list, adding a movie, and removing a movie are simple JDBC operations. They arenot in the scope of this tutorial. Only note that, in order to simplify the code, the example throws an Unsuppor-tedOperationException whereever it needs to throw an exception. A real-life application should throw moreappropriate exceptions.

vgup30
Underline
Page 51: Wicket Tutorial

Wicket Application Development43 / 55

1 public List<Movie> getMovies() {2 List<Movie> movies = new LinkedList<Movie>();3 try {4 String query = "SELECT ID, TITLE, YEAR FROM MOVIE";5 Statement statement = this.db.createStatement();6 ResultSet result = statement.executeQuery(query);7 while (result.next()) {8 Integer id = result.getInt("ID");9 String title = result.getString("TITLE");

10 Integer year = result.getInt("YEAR");11 Movie movie = new Movie(title);12 movie.setId(id);13 movie.setYear(year);14 movies.add(movie);15 }16 result.close();17 statement.close();18 } catch (SQLException ex) {19 throw new UnsupportedOperationException(ex.getMessage());20 }21 return movies;22 }

Figure 5.7: Listing: Getting movies from a collection using JDBC

1 public void addMovie(Movie aMovie) {2 try {3 String query = "INSERT INTO MOVIE(TITLE, YEAR) VALUES(?, ?)";4 PreparedStatement statement = this.db.prepareStatement(query);5 statement.setString(1, aMovie.getTitle());6 statement.setInt(2, aMovie.getYear());7 statement.executeUpdate();8 } catch (SQLException ex) {9 throw new UnsupportedOperationException(ex.getMessage());

10 }11 }

Figure 5.8: Listing: Adding a movie to a collection using JDBC

vgup30
Underline
Page 52: Wicket Tutorial

1 public void deleteMovie(Movie aMovie) {2 try {3 String query = "DELETE FROM MOVIE WHERE (ID = ?)";4 PreparedStatement statement = this.db.prepareStatement(query);5 statement.setInt(1, aMovie.getId());6 statement.executeUpdate();7 statement.close();8 } catch (SQLException ex) {9 throw new UnsupportedOperationException(ex.getMessage());

10 }11 }

Figure 5.9: Listing: Deleting a movie from a collection using JDBC

1 public void updateMovie(Movie aMovie) {2 try {3 String query = "UPDATE MOVIE SET TITLE = ?, YEAR = ? WHERE (ID = ?)";4 PreparedStatement statement = this.db.prepareStatement(query);5 statement.setString(1, aMovie.getTitle());6 statement.setInt(2, aMovie.getYear());7 statement.setInt(3, aMovie.getId());8 statement.executeUpdate();9 statement.close();

10 } catch (SQLException ex) {11 throw new UnsupportedOperationException(ex.getMessage());12 }13 }

Figure 5.10: Listing: Updating a movie in a collection using JDBC

After that, we just have to change the collection implementation chosen in the Application constructor:

public Application() {this.collection = new MovieCollectionJDBC();

}

Page 53: Wicket Tutorial

Wicket Application Development45 / 55

Appendix A

Development Environment

I assume that you already have the Java Development Kit (JDK) installed on your computer. This tutorial has beenprepared using the Sun JDK version 1.6.0; you can find it on the Java web site: http://java.sun.com/.

A.1 Installing NetBeans

You can get the NetBeans installer for your operating system from the NetBeans web site:

http://netbeans.org/

This tutorial is based on version 6.8; later versions might or might not support Wicket plugins -or the plugin used inthis tutorial. In case you have problems, you can find this exact version on the page:

http://netbeans.org/downloads/6.8/

On the download page, choose a bundle that includes the "Java Web and EE" component. At the time of this writing,these are "Java" and "All". The "Java" bundle is sufficient for the purposes of this tutorial.

After starting the installer, the welcome page displays the default installation options (Figure A.1). Though you canaccept these defaults, it is recommended that you customize the options and select only the following components(Figure A.2): Base IDE, Java SE, Java Web and EE, Features on Demand, Apache Tomcat.

vgup30
Typewriter
8-June-2011, Wednesday
vgup30
Underline
vgup30
Underline
vgup30
Underline
Page 54: Wicket Tutorial

Figure A.1: Screenshot: NetBeans install welcome page

Figure A.2: Screenshot: NetBeans install option customization form

A.2 Installing the Wicket Plugin

To develop Wicket applications in NetBeans, we will install the Wicket plugin. This plugin contains everythingrequired to develop and run Wicket applications, so no separate Wicket installation is necessary.

vgup30
Underline
vgup30
Underline
Page 55: Wicket Tutorial

Wicket Application Development47 / 55

Download the NetBeans Wicket plugin files at the following site:

http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=-3586

Select "Tools→ Plugins" from the NetBeans menu and open the "Downloaded" tab. Click the "Add Plugins" buttonand select the downloaded files (Figure A.3). Hit the "Install" button and restart NetBeans.

Figure A.3: Screenshot: NetBeans Wicket plugin installation

vgup30
Underline
Page 56: Wicket Tutorial
Page 57: Wicket Tutorial

Wicket Application Development49 / 55

Appendix B

Solutions to Exercises

Chapter: Basics

Add a link from the movie list page to the home page.

MovieListPage.html

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns:wicket="http://wicket.apache.org">

<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>MovieDB</title>

</head><body>

<h2>Movie List</h2>

<ul><li><a href="#" wicket:id="home">Home</a></li>

</ul></body>

</html>

MovieListPage.java

package itucs.blg361.moviedb;

import org.apache.wicket.markup.html.WebPage;import org.apache.wicket.markup.html.link.Link;

public final class MovieListPage extends WebPage {

public MovieListPage() {Link homeLink = new Link("home") {

@Overridepublic void onClick() {

this.setResponsePage(new HomePage());}

};this.add(homeLink);

}

Page 58: Wicket Tutorial

}

Chapter: Application Structure

Arrange the MovieListPage class so that it will use the style sheet and the navigation panel.

MovieListPage.html

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns:wicket="http://wicket.apache.org">

<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>MovieDB</title><link wicket:id="stylesheet" rel="stylesheet" type="text/css" href="#"/>

</head><body>

<div wicket:id="mainNavigation">links to common pages</div>

<h2>Movie List</h2></body>

</html>

MovieListPage.java

package itucs.blg361.moviedb;

public final class MovieListPage extends BasePage {

public MovieListPage() {}

}

Chapter: Data Model

Add a page that will display a movie. Then, organize the movie list page so that the entries are links to pages that willdisplay the selected movie.

MovieDisplayPage.html

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns:wicket="http://wicket.apache.org">

<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>MovieDB</title><link wicket:id="stylesheet" rel="stylesheet" type="text/css" href="#"/>

</head><body>

<div wicket:id="mainNavigation">links to common pages</div>

<h2 wicket:id="title">The Matrix</h2><table>

<tr><th>Year:</th><td wicket:id="year">1999</td>

Page 59: Wicket Tutorial

Wicket Application Development51 / 55

</tr></table>

</body></html>

MovieDisplayPage.java

package itucs.blg361.moviedb;

import org.apache.wicket.markup.html.basic.Label;

public final class MovieDisplayPage extends BasePage {

public MovieDisplayPage(Movie aMovie) {this.add(new Label("title", aMovie.getTitle()));this.add(new Label("year", aMovie.getYear().toString()));

}}

MovieDisplayPageLink.java

package itucs.blg361.moviedb;

import org.apache.wicket.markup.html.link.Link;

public class MovieDisplayPageLink extends Link {

private Movie movie;

public MovieDisplayPageLink(String id, Movie aMovie) {super(id);this.movie = aMovie;

}

@Overridepublic void onClick() {

this.setResponsePage(new MovieDisplayPage(this.movie));}

}

MovieListPage.html

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns:wicket="http://wicket.apache.org">

<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>MovieDB</title><link wicket:id="stylesheet" rel="stylesheet" type="text/css" href="#"/>

</head><body>

<div wicket:id="mainNavigation">links to common pages</div>

<h2>Movie List</h2>

<table>

Page 60: Wicket Tutorial

<tr wicket:id="movie_list"><td>

<a href="#" wicket:id="movie_link"><span wicket:id="title">The Matrix</span>(<span wicket:id="year">1999</span>)

</a></td>

</tr></table>

</body></html>

MovieListPage.java

package itucs.blg361.moviedb;

import java.util.List;import org.apache.wicket.markup.html.basic.Label;import org.apache.wicket.markup.html.list.ListItem;import org.apache.wicket.markup.html.list.PropertyListView;

public final class MovieListPage extends BasePage {

public MovieListPage() {Application app = (Application) this.getApplication();MovieCollection collection = app.getCollection();List<Movie> movies = collection.getMovies();

PropertyListView movieListView =new PropertyListView("movie_list", movies) {

@Overrideprotected void populateItem(ListItem item) {

Movie movie = (Movie) item.getModelObject();MovieDisplayPageLink movieLink =

new MovieDisplayPageLink("movie_link", movie);movieLink.add(new Label("title"));movieLink.add(new Label("year"));item.add(movieLink);

}};

this.add(movieListView);}

}

Chapter: Forms

Add a link to the movie display page which, when clicked, will take the user to the movie edit page. After saving themovie should be to updated in the collection (not added a second time).

MovieCollection.java

package itucs.blg361.moviedb;

import java.util.LinkedList;import java.util.List;

public class MovieCollection {

Page 61: Wicket Tutorial

Wicket Application Development53 / 55

private List<Movie> movies;

public MovieCollection() {this.movies = new LinkedList<Movie>();

}

public List<Movie> getMovies() {return this.movies;

}

public void addMovie(Movie aMovie) {this.movies.add(aMovie);

}

public void deleteMovie(Movie aMovie) {this.movies.remove(aMovie);

}

public void updateMovie(Movie aMovie) {}

}

MovieEditForm.java

package itucs.blg361.moviedb;

import org.apache.wicket.markup.html.form.Form;import org.apache.wicket.markup.html.form.TextField;import org.apache.wicket.model.CompoundPropertyModel;

public class MovieEditForm extends Form {

private boolean newMovie;

public MovieEditForm(String id, Movie aMovie, boolean newMovieFlag) {super(id);

CompoundPropertyModel model = new CompoundPropertyModel(aMovie);this.setModel(model);

this.add(new TextField("title"));this.add(new TextField("year"));

this.newMovie = newMovieFlag;}

@Overridepublic void onSubmit() {

Movie movie = (Movie) this.getModelObject();Application app = (Application) this.getApplication();MovieCollection collection = app.getCollection();if (this.newMovie) {

collection.addMovie(movie);} else {

collection.updateMovie(movie);}

Page 62: Wicket Tutorial

this.setResponsePage(new MovieDisplayPage(movie));}

}

MovieEditPage.java

package itucs.blg361.moviedb;

public final class MovieEditPage extends BasePage {

public MovieEditPage(Movie aMovie) {this.add(new MovieEditForm("movie_edit", aMovie, true));

}

public MovieEditPage(Movie aMovie, boolean newMovieFlag) {this.add(new MovieEditForm("movie_edit", aMovie, newMovieFlag));

}}

MovieDisplayPage.html

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns:wicket="http://wicket.apache.org">

<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>MovieDB</title><link wicket:id="stylesheet" rel="stylesheet" type="text/css" href="#"/>

</head><body>

<div wicket:id="mainNavigation">links to common pages</div>

<h2 wicket:id="title">The Matrix</h2><table>

<tr><th>Year:</th><td wicket:id="year">1999</td>

</tr></table>

<p><a href="#" wicket:id="edit_link">Edit</a></p></body>

</html>

MovieDisplayPage.java

package itucs.blg361.moviedb;

import org.apache.wicket.markup.html.basic.Label;import org.apache.wicket.markup.html.link.Link;

public final class MovieDisplayPage extends BasePage {

private Movie movie;

public MovieDisplayPage(Movie aMovie) {

Page 63: Wicket Tutorial

Wicket Application Development55 / 55

this.movie = aMovie;

this.add(new Label("title", this.movie.getTitle()));this.add(new Label("year", Integer.toString(this.movie.getYear())));

Link editLink = new Link("edit_link") {

@Overridepublic void onClick() {

MovieDisplayPage parent = (MovieDisplayPage) this.getParent();this.setResponsePage(new MovieEditPage(parent.movie, false));

}};this.add(editLink);

}}