Wicket-Projekt mit Maven

Es gibt einige Technologien und Frameworks aus dem Java-Umfeld, mit denen ich mich immer mal beschäftigen wollte, wozu ich aber aus Zeitgründen oder mangels Ziel, auf das ich hinarbeiten konnte, nie kam. Und da ich, bevor ich mit meine Diplomarbeit anfange, noch ein wenig Zeit habe, werde ich die Gelegenheit beim Schopfe packen und mich mit Maven, Wicket, Hibernate und anderen Dingen auseinandersetzen.

Einführung in Maven

Anfangen möchte ich erstmal mit Maven, weil alles andere mehr oder weniger darauf aufbauen wird. Zwar ist es natürlich möglich, Frameworks wie Wicket auch ohne Maven auszuprobieren, aber ich will das gleich miteinander verbinden. Am Ende dieses Artikels werden wir ein Grundgerüst für eine auf Wicket basierende Webanwendung haben.

Maven ist ein Werkzeug, das viele Prozesse vereinfacht. Es lassen sich recht einfach Abhängigkeiten zu anderen Projekten und Frameworks verwalten, es unterstützt automatisiertes Testen und vieles mehr, doch stürzen wir uns direkt ins Getümmel und probieren es aus. Ich setze hier voraus, dass ein halbwegs aktuelles JDK installiert und konfiguriert ist und außerdem Java-Kenntnisse vorhanden sind.

Auf der Maven Download-Seite finden wir die aktuellste Version, in meinem Fall ist das die 2.0.9. Das erhaltene Zip entpacken wir z.B. in das Verzeichnis für Programme, in meinem Fall wäre das C:\Program Files\Maven. Nun müssen wir noch zwei Systemvariablen setzen, zum einen M2_HOME, in der das Installationsverzeichnis eingetragen wird (bei mir wie oben erwähnt C:\Program Files\Maven) und zum anderen muss das bin-Verzeichnis von Maven noch zur PATH-Variable hinzugefügt werden (bei mir C:\Program Files\Maven\bin bzw. %M2_HOME%\bin).

Anschließend können wir die Kommandozeile aufrufen und die Version von Maven mit einem einfachen Kommando erfragen, wenn alles richtig gemacht wurde:

$ mvn -v
Maven version: 2.0.9
Java version: 1.6.0_06
OS name: "windows vista" version: "6.0" arch: "x86" Family: "windows"

Wenn das geklappt hat, kann es weitergehen, wenn nicht, dann müssen die ersten Schritte nochmal überprüft werden. Als nächstes legen wir ein neues Maven-Projekt an – das ginge sowohl per Hand, als auch per Archetype-Plugin. Wie wir noch sehen werden, ist Maven selbst eine Art Container, bei dem die Funktionalität durch viele Plugins zustande kommt. Wir wechseln per Kommandozeile in das hoffentlich bereits erstellte Verzeichnis, das unser kleines Testprojekt beinhalten soll und erstellen es:

$ cd myprojects
$ mvn archetype:create -DgroupId=net.rattlab.test -DartifactId=test -DpackageName=net.rattlab.test
[...]
[INFO] OldArchetype created in dir: C:\myproject\test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 secons
[INFO] Finished at: Sun Aug 17 22:01:02 CEST 2008
[INFO] Final Memory: 7M/14M
[INFO] ------------------------------------------------------------------------

Mit diesem Kommando wird ein sogenanntes Goal aufgerufen, in diesem Fall “create” vom PlugIn “Archetype”. Dieses erstellt das Grundgerüst für ein neues Projekt und lädt ggf. benötigte Maven-PlugIns herunter (in diesem Fall das angesprochene Archetype-PlugIn) – darum müssen wir uns nicht selber kümmern. Die übergebenen Parameter sind im Falle von groupId und artifactId Bezeichner, um das Projekt eindeutig identifizieren zu können und ein Package-Name für die zu erzeugende Java-Klasse, die nichts weiter tut, als “Hello World” auszugeben.

Doch schauen wir uns erstmal an, was im Projekt-Verzeichnis zu finden ist. Dort gibt es neben einem Verzeichnis für die Source-Code eine Datei namens pom.xml, in der die Konfiguration des Projekts zu finden ist. Diese Datei und die Verzeichnisstruktur hätte man auch selber per Hand erstellen können – das Archetype-Plugin also nimmt uns nur etwas Arbeit ab, wirklich nötig wäre es in diesem Fall aber nicht. Doch zurück zur pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>net.rattlab.test</groupId>
  <artifactId>test</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>test</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Hier tauchen die als Argument übergebenen artifactId und groupId wieder auf, begleitet von einer Version – diese drei Parameter identifizieren den konkreten Stand eines Projekts. Weiterhin interessant ist der Teil, der die Abhängigkeiten (Dependencies) definiert – in diesem Falle ist standardmäßig JUnit, ein Testing-Framework, integriert. Mehr ist hier nicht nötig, da die weitere Verzeichnisstruktur dem Maven-Standard entspricht und damit nicht konfiguriert werden muss. Möchte man diese aber ändern, so sind natürlich auch mehr Zeilen in der pom.xml nötig.

Jetzt wollen wir das Projekt aber noch hübsch in ein JAR verpacken und anschließend ausführen. Dazu wechseln wir ins Projekt-Verzeichnis und führen eine nächste Anweisung aus, die diesmal aber nicht nur ein Goal enthält, sondern einen Lifecycle anstößt – dabei werden mehrere Goals ausgeführt und, falls nötig, die als Abhängigkeiten definierten JARs runtergeladen und im lokalen Repository gespeichert.

cd test
$ mvn install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building test
[INFO]    task-segment: [install]
[INFO] ------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to C:\myprojects\test\target\classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Compiling 1 source file to C:\myprojects\test\target\test-classes
[INFO] [surefire:test]
[INFO] Surefire report directory: C:\myprojects\test\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running net.rattlab.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] [jar:jar]
[INFO] Building jar: C:\myprojects\test\target\test-1.0-SNAPSHOT.jar
[INFO] [install:install]
[INFO] Installing C:\myprojects\test\target\test-1.0-SNAPSHOT.jar to
C:\Users\ex-ratt\.m2\repository\net\rattlab\test\test\1.0-SNAPSHOT\test-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Sun Aug 17 22:32:15 CEST 2008
[INFO] Final Memory: 8M/16M
[INFO] ------------------------------------------------------------------------

Das Log verrät uns, dass automatisch Tests ausgeführt wurden, der Quellcode kompiliert, ein JAR erstellt und anschließend ins lokale Maven-Repository kopiert wurde – und das alles nur mit einem Befehl. Jetzt schließen wir noch einen kleinen Funktionstest an:

$ java -cp target/test-1.0-SNAPSHOT.jar net.rattlab.test.App
Hello World!

Das sollte jetzt nur als klitzekleiner Einstieg in Maven dienen, da ich nun damit arbeiten werde. Weitergehende Informationen zu diesem nützlichen Werkzeug finden sich in Sonatypes Maven: The Definitive Guide, mit dem ich selber den Einstieg vollzogen habe – meinem kleinen Beispiel sieht man das auch an, wenn man es mit dem ersten Beispiel des Buches vergleicht. Allerdings handelt es sich dabei eben auch um das typische Einstiegsbeispiel, auch auf der Webseite von Maven wird es im Guide Maven in 5 Minutes behandelt.

Ein erstes Wicket-Projekt

Jetzt erstellen wir ein weiteres kleines Projekt, das ebenfalls nur eine kleine Meldung ausgiebt, diesmal aber im Browser. Wie anfangs erwähnt wollen wir damit unsere ersten kleinen Schritte mit dem Web-Framework Wicket wagen. Auf der Webseite von Apache Wicket gibt es eine QuickStart-Anleitung, in der praktischerweise schon das Maven-Kommando steht, das wir an unsere Bedürfnisse anpassen:

$ mvn archetype:create -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.3.4 -DgroupId=net.rattlab -DartifactId=wickettest
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'archetype'.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:create] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Setting property: classpath.resource.loader.class => 'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.
[INFO] Setting property: velocimacro.messages.on => 'false'.
[INFO] Setting property: resource.loader => 'classpath'.
[INFO] Setting property: resource.manager.logwhenfound => 'false'.
[INFO] [archetype:create] [WARNING] This goal is deprecated. Please use mvn archetype:generate instead
[INFO] Defaulting package to group ID: net.rattlab
Downloading: http://repo1.maven.org/maven2/org/apache/wicket/wicket-archetype-quickstart/1.3.4/wicket-archetype-quickstart-1.3.4.jar
4/12K
7/12K
11/12K
12/12K
12K downloaded
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating OldArchetype: wicket-archetype-quickstart:1.3.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: net.rattlab
[INFO] Parameter: packageName, Value: net.rattlab
[INFO] Parameter: package, Value: net.rattlab
[INFO] Parameter: artifactId, Value: wickettest
[INFO] Parameter: basedir, Value: C:\myprojects
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] ********************* End of debug info from resources from generated POM ***********************
[INFO] OldArchetype created in dir: C:\myprojects\wickettest
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Mon Aug 18 16:32:00 CEST 2008
[INFO] Final Memory: 7M/14M
[INFO] ------------------------------------------------------------------------

Hier geben wir zusätzlich einen konkreten Archetype an, anhand dessen dann das Projekt erstellt wird. Dieser Archetype wird, genauso wie andere Projekte, ebenfalls mittels einer GroupId und einer ArtifactId identifiziert. Abseits davon, dass hier der Wicket-Archetype geladen und das Projekt erstellt wurde, fällt mir jetzt erst auf, dass archetype:create offenbar veraltet ist und stattdessen archetype:generate benutzt werden soll. Das sollte ich wohl demnächst mal ausprobieren.

Die pom.xml unseres Wicket-Testprojekts ist jetzt schon um einiges größer, als die unseres ersten Beispiels. Hinzugekommen sind jede Menge Abhängigkeiten, unter anderem natürlich zu Wicket, aber auch zu zwei Loggern und Jetty, einem Servlet-Container, den wir gleich auch noch nutzen werden.

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>net.rattlab</groupId>
	<artifactId>wickettest</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<!-- TODO project name  -->
	<name>quickstart</name>
	<description></description>

	<!-- TODO
		<organization>
		<name>company name</name>
		<url>company url</url>
		</organization>
	-->

	<licenses>
		<license>
			<name>The Apache Software License, Version 2.0</name>
			<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
			<distribution>repo</distribution>
		</license>
	</licenses>

	<dependencies>
		<!--  WICKET DEPENDENCIES -->

		<dependency>
			<groupId>org.apache.wicket</groupId>
			<artifactId>wicket</artifactId>
			<version>${wicket.version}</version>
		</dependency>
		<!-- OPTIONAL 
			<dependency>
			<groupId>org.apache.wicket</groupId>
			<artifactId>wicket-extensions</artifactId>
			<version>${wicket.version}</version>
			</dependency>
		-->

		<!-- LOGGING DEPENDENCIES - LOG4J -->

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.4.2</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>

		<!--  JUNIT DEPENDENCY FOR TESTING -->
		 <dependency>
				 <groupId>junit</groupId>
				 <artifactId>junit</artifactId>
				 <version>3.8.2</version>
				 <scope>test</scope>
		 </dependency>

		<!--  JETTY DEPENDENCIES FOR TESTING  -->

		<dependency>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>jetty</artifactId>
			<version>${jetty.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>jetty-util</artifactId>
			<version>${jetty.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>jetty-management</artifactId>
			<version>${jetty.version}</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<resources>
			<resource>
				<filtering>false</filtering>
				<directory>src/main/resources</directory>
			</resource>
			<resource>
				<filtering>false</filtering>
				<directory>src/main/java</directory>
				<includes>
					<include>**</include>
				</includes>
				<excludes>
					<exclude>**/*.java</exclude>
				</excludes>
			</resource>
		</resources>
		<testResources>
			<testResource>
				<filtering>false</filtering>
				<directory>src/test/java</directory>
				<includes>
					<include>**</include>
				</includes>
				<excludes>
					<exclude>**/*.java</exclude>
				</excludes>
			</testResource>
		</testResources>
		<plugins>
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<configuration>
					<downloadSources>true</downloadSources>
				</configuration>
			</plugin>			
		</plugins>
	</build>

	<properties>
		<wicket.version>1.3.4</wicket.version>
		<jetty.version>6.1.4</jetty.version>
	</properties>

</project>

Weiterhin fällt auf, dass die Versionen von Wicket und Jetty ausgelagert wurden. Ganz unten in der Datei sieht man die Abschnitt “properties” und das ist in diesem Fall deswegen nützlich, weil die gleichen Versionsnummern mehrmals gebraucht werden. Außerdem werden noch weitere Dinge konfiguriert, auf die ich aktuell nicht eingehen möchte – Einzelheiten zur pom.xml findet man im weiter oben verlinkten Buch.

Wir wollen uns jetzt mit dem aus meiner Sicht interessanterem Teil beschäftigen, nämlich der eben erstellten Wicket-Anwendung. Im Verzeichnis C:\myprojects\wickettest\src\main\net\rattlab (mag bei euch anders lauten) liegen drei Dateien, zwei Java-Dateien und eine im HTML-Format. Letztere beinhält eine einfache Webseite:

<html>
    <head>
        <title>Wicket Quickstart Archetype Homepage</title>
    </head>
    <body>
        <strong>Wicket Quickstart Archetype Homepage</strong>
        <br/><br/>
        <span wicket:id="message">message will be here</span>
    </body>
</html>

Das sieht erstmal recht normal aus, nur das Attribut wicket:id wird dem HTML-Kenner neu sein. Über dieses Attribut spricht Wicket bestimmte Elemente im Code an, wie wir in der zu dieser Seite gehörenden Java-Klasse HomePage.java sehen:

package net.rattlab;

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

/**
 * Homepage
 */
public class HomePage extends WebPage {

	private static final long serialVersionUID = 1L;

	// TODO Add any page properties or variables here

    /**
	 * Constructor that is invoked when page is invoked without a session.
	 *
	 * @param parameters
	 *            Page parameters 	 */
    public HomePage(final PageParameters parameters) {

        // Add the simplest type of label
        add(new Label("message", "If you see this message wicket is properly configured and running"));

        // TODO Add your page's components here
    }
}

Dieser Webseite wird dein Label mit dem Text “If you see this message wicket is properly configured and running” zugewiesen. Dieses Label hat eine id namens “message”, die dem Wert des wicket:id Attributs im HTML-Code gleicht. Wie wir gleich im Browser sehen werden, wird der Text im span-Element durch den des Labels ersetzt.

Die letzte Datei schließlich ist die WicketApplication.java, in der die Webanwendung konfiguriert wird. In unserem einfachen Beispiel wird nur die Einstiegsseite angegeben, die aufgerufen werden soll, wenn kein spezieller Pfad in der Adresszeile angegeben wird:

package net.rattlab;

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

/**
 * Application object for your web application. If you want to run this application without deploying, run the Start class.
 *
 * @see wicket.myproject.Start#main(String[])
 */
public class WicketApplication extends WebApplication
{
    /**
     * Constructor
     */
	public WicketApplication()
	{
	}

	/**
	 * @see wicket.Application#getHomePage()
	 */
	public Class getHomePage()
	{
		return HomePage.class;
	}

}

Nun wollen wir den Kram aber auch mal ausprobieren. Dafür nutzen wir das Jetty-PlugIn, das bereits in der pom.xml konfiguriert wurde, wechseln ins Projektverzeichnis und führen es aus:

$ cd wickettest
$ mvn jetty:run
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO] ------------------------------------------------------------------------
[INFO] Building quickstart
[INFO]    task-segment: [jetty:run]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing jetty:run
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Nothing to compile - all classes are up to date
[INFO] [jetty:run]
[INFO] Configuring Jetty for project: quickstart
[INFO] Webapp source directory = C:\myprojects\wickettest\src\main\webapp
[INFO] web.xml file = C:\myprojects\wickettest\src\main\webapp\WEB-INF\web.xml
[INFO] Classes = C:\myprojects\wickettest\target\classes
[INFO] Context path = /wickettest
[INFO] Tmp directory =  determined at runtime
[INFO] Web defaults = org/mortbay/jetty/webapp/webdefault.xml
[INFO] Web overrides =  none
[INFO] Webapp directory = C:\myprojects\wickettest\src\main\webapp
[INFO] Starting jetty 6.1.12rc1 ...
INFO  - Application                - [WicketApplication] init: Wicket core library initializer
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IBehaviorListener, method=public abstract void org.apache.wicket.behavior.IBehaviorListener.onRequest()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IBehaviorListener, method=public abstract void org.apache.wicket.behavior.IBehaviorListener.onRequest()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IFormSubmitListener, method=public abstract void org.apache.wicket.markup.html.form.IFormSubmitListener.onFormSubmitted()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IFormSubmitListener, method=public abstract void org.apache.wicket.markup.html.form.IFormSubmitListener.onFormSubmitted()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=ILinkListener, method=public abstract void org.apache.wicket.markup.html.link.ILinkListener.onLinkClicked()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=ILinkListener, method=public abstract void org.apache.wicket.markup.html.link.ILinkListener.onLinkClicked()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IOnChangeListener, method=public abstract void org.apache.wicket.markup.html.form.IOnChangeListener.onSelectionChanged()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IOnChangeListener, method=public abstract void org.apache.wicket.markup.html.form.IOnChangeListener.onSelectionChanged()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IRedirectListener, method=public abstract void org.apache.wicket.IRedirectListener.onRedirect()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IRedirectListener, method=public abstract void org.apache.wicket.IRedirectListener.onRedirect()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IResourceListener, method=public abstract void org.apache.wicket.IResourceListener.onResourceRequested()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IActivePageBehaviorListener, method=public abstract void org.apache.wicket.behavior.IBehaviorListener.onRequest()]
INFO  - RequestListenerInterface   - registered listener interface [RequestListenerInterface name=IActivePageBehaviorListener, method=public abstract void org.apache.wicket.behavior.IBehaviorListener.onRequest()]
INFO  - WebApplication             - [WicketApplication] Started Wicket version 1.3.4 in development mode
[INFO] Started Jetty Server

Die hier gezeigt Ausgabe wird vermutlich nicht alles sein, da Wicket in unserem Fall die Konsole gleichzeitig für das eigene Log nutzt und unter anderem davor warnt, dass es im Entwicklungs-Modus läuft. Jetzt können wir jedenfalls einen Browser unserer Wahl aufrufen und in die Adressezeile http://localhost:8080/wickettest/ eingeben und wenn alles funktioniert hat, dann erscheint dort jetzt die einfache Seite mit dem Label-Text. Um den Server zu beenden, drücken wir im Eingabefenster STRG+C, dann fährt er sich herunter.

Der Vollständigkeit halber wollen wir uns kurz noch die web.xml ansehen. In dieser Datei wird dem Servlet-Container, in unserem Fall Jetty, mitgeteilt, bei welchem Pfad welches Servlet aufzurufen ist. Ein Servlet ist die ursprüngliche Art und Weise, mit Java eine Webanwendung zu schreiben und darauf basieren auch alle Web-Frameworks, in Berührung damit kommen wir aber kaum. So also sieht die c:\myprojects\wickettest\src\main\webapp\WEB-INF\web.xml (mein lokaler Pfad) aus:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	 version="2.4">

	<display-name>wickettest</display-name>

	 <!--  
	      There are three means to configure Wickets configuration mode and they are
	      tested in the order given. 
	      1) A system property: -Dwicket.configuration
	      2) servlet specific <init-param>
	      3) context specific <context-param>
	      The value might be either "development" (reloading when templates change)
	      or "deployment". If no configuration is found, "development" is the default.
	-->

	<filter>
		<filter-name>wicket.wickettest</filter-name>
 		<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
		<init-param>
			<param-name>applicationClassName</param-name>
			<param-value>net.rattlab.WicketApplication</param-value>
 		</init-param>
 	</filter>

 <filter-mapping>
  <filter-name>wicket.wickettest</filter-name>
	<url-pattern>/*</url-pattern>
 </filter-mapping>


</web-app>

Ganz unten sehen wir das filter-mapping, dort werden URLs anhand eines Musters (englisch Pattern) einem bestimmten Servlet zugewiesen, das unter filter konfiguriert wird. Jetzt haben wir also ein Grundgerüst, mit dem wir Wicket nach Belieben ausprobieren können.

Ergänzende Informationen

Es gibt einen Wicket Quickstart Screencast von Alastair Maw, in dem nochmal die wesentlichen Dinge gezeigt werden, die auch in diesem Artikel stehen. Außerdem zeigt er, wie man das Projekt nach Eclipse importiert, um anschließend daran zu arbeiten.

Wer sich mehr Details zum Grundkonzept von Wicket wünscht, der kann sich mal das Probekapitel 1 vom Buch Wicket in Action herunterladen. Das Buch ist fast erschienen (befindet sich im Druck, als eBook ist es bereits erhältlich) und wurde von zwei Wicket-Entwicklern geschrieben. Neben Kapitel 1 und 8 findet man dort auch ein Bonuskapitel 15, in dem erklärt wird, wie man sein Wicket-Projekt aufsetzen kann. Dabei wird unter anderem auch auf Ant und Maven eingegangen und da es von Hand entwickelt wird, findet man dort auch mehr Erklärungen zu den Elementen der pom.xml und web.xml, als hier bei mir. Lesen lohnt sich also.

Ein weiteres Buch ist “Enjoying Web Development with Wicket”, von dem man sich die ersten drei Kapitel herunterladen kann. Abgesehen davon findet man auf der Seite von Apache Wicket und auf wicket-library.com noch weitere Beispiele und Dokumentationen.

Ich werde meinen Eindruck von Wicket demnächst jedenfalls noch vertiefen und eine erste kleine Beispielanwendung schreiben, die ich hier in Form eines Tutorials veröffentlichen werde.

1 Pingback

  1. Wicket Feedreader - rattlab.net 21. September 2008 um 11:58

Keine Antworten

Hinterlasse eine Antwort