Craig Tataryn started his career as a Visual Basic programmer, but don't hold that against him!  The system he helped create was a cutting edge, n-tiered revenue collection system whose transactions per second metric was off the charts!  Around the year 2000 he discovered Struts and never looked back.  A professional Java developer for close to a decade, Craig has worked on a wide variety of projects ranging from Recruiting, Purchase order, Revenue collection and Mortgage systems.  More recently Craig has written web services for children's educational toys and has honed his skills on Wicket, Facebook and iPhone application development.  "I love to learn and more importantly I love to teach.  Hoarding knowledge is one of the most petty and selfish things you can do, especially as a contractor.  This is why I always make it a point to document and share my knowledge with my client's employees" Craig has posted 2 posts at DZone. View Full User Profile

Wicket Tutorial Series: Setting Up the Project

03.10.2009
| 20381 views |
  • submit to reddit

Each day this week will feature a new article with an in-depth look at the creation process behind setting up a Java project and implementing the frontend with Apache Wicket.

Wicket is a Java web application framework which allows “Designers” (people good with Dreamweaver) and “Developers” (people good with Java and Databases) to collaborate on a project with minimal chances of stepping on each other’s toes or wearing each other’s hats.

The beauty of Wicket is that it uses plain xhtml pages as it’s templating markup. This means that html pages can be loaded into Dreamweaver (or whatever tool the Designer is comfortable with) and they will look very close to the same as they would when rendered on the deployment web server.

Workflow

The basic workflow involved in creating and maintaining html rendered by Wicket is as follows:

wicket-sequence-diagram

  1. The Designer creates the html for the website and fleshes it out with “mock” sections. For instance in the application we intend to create during our Five Days of Wicket will be a pastebin application called “Mystic Paste”. In our application we’ll have an “Add Code to Mystic Paste” page, mock data might include some user created content in the textarea of the page. All css/images, etc… are setup such that if they were to be put on a webserver, everything would work.
  2. The Developer needs to flesh out the dynamic areas of the webpage, that is, he needs to instruct Wicket where it will need to show information from the server. The developer does this by decorating the designer’s html page with special Wicket tags and attributes. Because these tags and attributes are just considered part of another namespace separate from xhtml’s, editors like Dreamweaver and browsers will simply ignore them
    - It is important to note: The developer will still keep the “mocked” sections of the page intact, this is so the page renders and looks fleshed out on its own. The mocked sections will be replaced by real data when rendered by Wicket.
  3. The Developer hands the file back to the Designer. The Designer is free to make further edits, so long as he/she does not remove or manipulate the Wicket tags and attributes present in the file. If the Designer does need to remove any Wicket tags or attributes, they need to consult the Developer as such an action will “break” the webpage when Wicket renders it.

Example Wicket Page

Here is an example of a Wicket page. This example was taken from Manning Publishing’s book “Wicket in Action”:

<html>
<head>
<title>Cheesr - Making cheese taste beta</title>
<link href="style.css" rel="stylesheet" />
</head>
<body>
<div id="container">
<div id="header">...</div>
<div id="contents">
<div id="main">
<div wicket:id="cheeses" class="cheese">
<h3 wicket:id="name">Gouda</h3>
<p wicket:id="description">Gouda is a Dutch...</p>
<p>
<span wicket:id="price">$1.99</span>
<a wicket:id="add" href="#">add to cart</a>
</p>
</div>
<wicket:remove>
<!-- this section will be removed by wicket, it's only purpose is to flesh out the page -->
<div class="cheese">
<h3>Emmental</h3>
<p>Emmental is a Swiss che...</p>
<p>
<span>$2.99</span>
<a href="#">add to cart</a>
</p>
</div>
</wicket:remove>
</div>
<div id="cart">...</div>
</div>
</div>
</body>
</html>

This looks almost 100% like a normal webpage would look, the only difference is the addition of the “wicket:XXX” attributes and tags sprinkled through the document. The parts of the document using the special Wicket namespace modifiers will be replaced/removed in the final markup when Wicket renders the page to the user’s browser. Notice the “<wicket:remove>” element? This is where your designer can put a “mocked” version of what that area of the page should look like. You as a developer can take that mocked html and divide it out into a template that is dynamically driven from the backend.

Here is how the final page looks if you were to simply load the page into a web browser (or Dreamweaver) from your hard drive:

cheesr-wicket

Preparing for Setup

Deviating a bit from the Standard Wicket Convention

One of the first things a developer notices when starting out with Wicket is the convention where Wicket likes having its html template files live at the same level and in the same packages as it’s Java source files. Sure you can jump through hoops to get Wicket to load the html template files from elsewhere but a nice compromise is to simply keep your html template files within the same package directory structure but in a source folder separate from the Java classes. Why? Well quite simply to keep your designers (Dreamweaver folks!) from having to grab Java source files along with the html files they are working on. It will just confuse them and clutter their directories.

You can of course stick with the typical “Java source files along side html” convention if you wish, but I find it much cleaner to separate them during design time, and have Maven combine them only at build time into the target war (which it will gladly do automagically).

Project Folder Structure
.
|-- pom.xml
|-- src
| `-- main
| |-- filters
| |-- java
| | `-- com
| | `-- mysticcoders
| | `-- mysticpaste
| | |-- model
| | |-- persistence
| | | |-- exception
| | | |-- hibernate
| | |-- services
| | `-- web
| | |-- ajax
| | |-- pages
| | |-- panels
| | `-- servlet
| |-- resources
| | |-- com
| | | `-- mysticcoders
| | | `-- mysticpaste
| | | |-- spring
| | | `-- web
| | | |-- ajax
| | | |-- pages
| | | `-- panels
| | `-- log4j.properties
| |-- sql
| `-- webapp
| |-- WEB-INF
| |-- images
| |-- js
| `-- css
  • src/main: maven builds source and resources from this directory to the main deployable target (i.e. our war file)
    • filters: we keep a set of “filters” files that maven can use to interpolate variables at build time. What does this mean? It means that inside your configuration files, the files you use to setup database connections or file paths, you can insert variable place holders like ${db.host}. When maven does a build, it looks up the correct filter file to use and looks for the key=value part corresponding to “db.host” and inserts it into the configuration file for you. This ensures that you are able to configure your application per environment you deploy to (i.e. DEV, QA, PROD, etc…) by having different filter files with the same keys but different values. For more information see Maven’s documentation on filtering resource.
    • java/*: this folder will contain all of the application’s source code. Everything from the database access code, wicket code and services code for the mysticpaste application (see below).
      • model: all “domain” classes, that is, classes that represent the objects in the application. For mysticpaste you’ll see classes like “PasteItem” which represents an item pasted to the mysticpaste.
      • persistence: at this level of the persistence package a list of interfaces will be kept. The interfaces comprise the basic access layer the services layer will use to save, retrieve and update items to/from the paste bin.
        • exception: the peristence layer needs to tell the services layer when things have gone wrong. It does this via delcaring and throwing exceptions.
        • hibernate: such is our case, our persistence interfaces will be implemented via the ORM known as Hibernate. This package will store all of the custom hibernate implementations and hibernate specific classes
      • services: The services layer will be stored here. Both the generic interfaces and their implementation classes. The persistence layer will be injected via spring.
      • web: this folder is where our Wicket classes will reside and it’s split into several category packages which are as follows:
        • ajax: mysticpaste uses Ajax to render portions of its UI. The wicket classes which render the xml/html to be injected dynamically into the page are stored here.
        • pages: standard Wicket page classes which are used throughout the application are stored here
        • panels: reusable panel classes are stored here. Panels may be included within Wicket pages for sake of templating
        • servlet: any run of the mill servlet code we need is stored here. A good example might be an ImageUploadServlet
    • resources/*: the resources folder will hold our non-java based files. Noteably html files and spring confguration files
      • spring: Holds any spring configuration files needed to wire the services and persistence layer
      • web: this folder and all subfolders mirror the packages under src/main/java/…/web and hold the .html files that the Wicket page/panel classes use as their templates. As described above, a “standard” wicket application simply stores the .html files along side their Wicket classes under src/main/java/…/web, however we want to keep these files separate from the Java source so as to keep the directory our designers checkout from version control contianing only the files they need to work on.
    • sql: any sql scripts we need to keep handy for building the mysticpaste database.
    • webapp: this folder will keep the files which live at the base directory of our war file
      • WEB-INF: where you keep your web.xml file
      • images: any image resource, .gif/.png/.jpg files your webapp will reference
      • js: javascript files your webapp will reference
      • css: style sheets your webapp uses
  • src/test/*: All files which reside under this folder are test classes and resources needed to support the tests. Maven will build everything under src/main/java and add it to the class path of the JUnit or TestNG classes you create.
    • java: JUnit or TestNG test classes which will be run during a build
    • resources: resource files which are needed to support the tests

Getting Started

Since we are using Maven as our build tool we can take advantage of the fact that the fine folks at the Wicket project have created a specialized “archetype“ which creates a skeleton web application complete with a folder structure which mimics roughly what we have outlined above and Maven pom.xml file used to build a war. The Wicket contributors have even gone one step further and have created a little web page which will, based off a few drop down options, generate the maven command you need to execute in order to create the boiler plate Wicket project. You can find this web page over on the Apache Wicket site under the “Quick Start” link.

wicket-archetype1

Copying the above Maven command creates a Skeleton Wicket Project

To be precise, the command I used was:

mvn archetype:create
-DarchetypeGroupId=org.apache.wicket
-DarchetypeArtifactId=wicket-archetype-quickstart
-DarchetypeVersion=1.3.5
-DgroupId=com.mysticcoders
-DartifactId=mysticpaste

And I ended up with the following folder structure:

.
`-- mysticpaste
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mysticcoders
| | |-- HomePage.html
| | |-- HomePage.java
| | `-- WicketApplication.java
| |-- resources
| | `-- log4j.properties
| `-- webapp
| `-- WEB-INF
| `-- web.xml
`-- test
`-- java
`-- com
`-- mysticcoders
|-- Start.java
`-- TestHomePage.java

Now obviously we’ll have to rearrange a few things, for instance I want my base package to be com.mysticcoders.mysticpaste, but that’s easy enough to do once we are in an IDE. For now, let’s test this example webapp out and see if it works. To do that switch into the mysticpaste directory (the directory that has pom.xml in it) and type the following:

mvn jetty:run

This will start up a Jetty webapp container running on port 8080 (if you have something running there already, use the -Djetty.port=<portNum> option). Startup a webbrowser and navigate to http://localhost:8080/mysticpaste/ You should see:

jetty-quickstart

Published at DZone with permission of its author, Craig Tataryn.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Bjorn Vandenheede replied on Wed, 2009/03/11 - 9:54am

How come the quickstart command of Wicket just doesn't work for me?  Trying the following:

 

mvn -e archetype:create -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.3.5 -DgroupId=com.mysticcoders -DartifactId=mysticpaste

 

Just gives me

 

...

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Error creating from archetype

Embedded error: The META-INF/maven/archetype.xml descriptor cannot be found.
[INFO] ------------------------------------------------------------------------
[INFO] Trace
org.apache.maven.lifecycle.LifecycleExecutionException: Error creating from archetype
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:583)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:512)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:482)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.jav
a:330)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:227)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:142)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:336)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:129)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:287)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
        at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
        at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
        at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
Caused by: org.apache.maven.plugin.MojoExecutionException: Error creating from archetype
        at org.apache.maven.plugin.archetype.MavenArchetypeMojo.execute(MavenArchetypeMojo.java:197)
        at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:451)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:558)
        ... 16 more
Caused by: org.apache.maven.archetype.ArchetypeDescriptorException: The META-INF/maven/archetype.xml descriptor cannot b
e found.
        at org.apache.maven.archetype.DefaultArchetype.createArchetype(DefaultArchetype.java:185)
        at org.apache.maven.plugin.archetype.MavenArchetypeMojo.execute(MavenArchetypeMojo.java:188)
        ... 18 more

 

Is this a wicket archtype problem, or something wrong with my maven setup (2.0.9), ...?

Craig Tataryn replied on Wed, 2009/03/11 - 12:32pm in response to: Bjorn Vandenheede

It's quite possible your local maven repo is corrupted.  Do this, navigate to your local repo (i.e. ~/.m2/repository) and delete the folder under org/apache/wicket that pertains to the quickstart archetype and try again.  It should re-download the archetype from the maven repos.

 Good luck!

Bjorn Vandenheede replied on Wed, 2009/03/11 - 5:08pm

Removing the wicket-archetype-quickstart directory and rerunning the command made it work.  Thanks for the help.

Shane Hayes replied on Thu, 2009/09/03 - 3:16pm

The maven create project does not get the same defaults as creating a native wicket project (in netbeans), it is missing things like the header and navigation defaults.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.