Forschungszentrum Informatik Universität Karlsruhe (TH) Information Process Engineering Web-Technologien im praktischen Einsatz Erstellung einer Bildsuchmaschine mit Apache Wicket Andreas Walter WS 2009/2010 SVN Tutorial Tutorial Folien und Sourcen zum Download http://www.awalter.info/wicket/ Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 2 Motivation: EU Projekt IMAGINATION Anforderungen Anwendung soll in JAVA entwickelt werden Anwendung soll vollständig webbasiert sein und AJAX verwenden, um desktop-charakter zu erzeugen Anwendung muss verteilt entwickelt werden, erfordert Versionskontrolle (auch von verwendeten Bibliotheken) Integrationskontrolle von Teilentwicklungen Webrahmenwerk, da Wechsel der Entwickler möglich muss leicht erlernbar sein Quelltext muss leicht lesbar sein Einfache Änderung des Seitenlayouts Anwendung durchläuft mehrere Zyklen (vom Prototyp an) Seitenlayout durch Partner für Design Informationsintegration & Web-Portale WS 2009/10 3 Gliederung Web-Technologien im praktischen Einsatz Infrastruktur aufbauen Framework wählen Wicket Tutorial Erstellung einer Bildsuchmaschine mit Wicket Features von Wicket Wicket im Vergleich zu anderen Frameworks Wicket Schritt für Schritt zur Erstellung einer Bildsuchmaschine Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 4 Infrastruktur aufbauen JUnit: automatisches Testen der Programmfunktionen Maven: Build Kontrolle „continous integration server“ JUnit JUNIT: http://www.junit.org/ Zweck: Ermöglicht die Definition von Testfällen, um die Richtigkeit von Quelltexten zu überprüfen Beispiel Methode public int getResult() muss „1“ zurückgeben Test in Junit: assertEquals(getResult(),1) Falls int !=1 bricht der Test mit Fehlermeldung ab JUnit ermöglicht die Integrationskontrolle von Anwendungsteilen In IMAGINATION: Test von verteilt entwickelten Anwendungsteilen Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 6 Maven: Build Kontrolle (1) Maven Homepage: http://maven.apache.org/ Maven ermöglicht Definition von Modulen einer umfangreichen Anwendung Definition der Abhängigkeiten, z.B. JAR Files (Lucene, MySQL JDBC Treiber) und der für Anwendung benötigten Versionsnummern Automatische Durchführung von Kompilierung, JUnit-Tests, Deployment Direktes Starten von Webanwendungen in Servlet-Container Integration der Anwendung in Eclipse Ermöglicht einheiltliche Programmstrukturen Src/main/java: Verzeichnis für JAVA Packages Src/test/java: Verzeichnis für JUnit Tests Target/classes: Verzeichnis für JAVA classes Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 7 Maven: Build Kontrolle (2) Wichtige Build Targets von maven (jeweils darüberliegende targets werden automatisch durchgeführt) mvn mvn mvn mvn compile: Kompiliert die Anwendung test: Durchführung der JUnit Tests install: Generierung von JAR Files deploy: Aufladen der JAR Files auf einen Server mvn jetty:run : Starten von Jetty Servlet Container mvn eclipse:eclipse: Erstellung von Eclipse Projekts Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 8 continous integration server(1) Zweck Sorgen für automatische Erstellung von builds einer verteilt erstellten Anwendung Ablauf Quellcodes werden in SVN Repository eingestellt Projekte basieren auf Maven Projekte enthalten JUnit Tests Continous integration server prüft regelmässig SVN Repository auf Änderungen Bei Änderungen wird automatisch ein Build durchgeführt Benachrichtigung der Entwickler bei Fehlern Ermöglicht in Zusammenarbeit mit maven die automatische Integrationskontrolle von Teilentwicklungen und die Versionierung der Software Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 9 continous integration server(2) Beispiel: Hudson - https://hudson.dev.java.net/ Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 10 Auswahl des richtigen Frameworks Wartbarkeit Lesbarkeit Model View Controler vs. Eventbasierten Frameworks Langfristige Wartbarkeit „Trennung von Anwendung und Darstellung“ ist nicht so wichtig? „Trennung von Anwendung und Darstellung kann jedes Web Framework?“ Sicher? Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 12 Wartbarkeit in JSP 1.0 <html> <head> <title>A JSP example</title> </head> <body> <% %> <% %> String[] valueArray = {"This", "is", "a", „string", „array", "example"}; int i; for (i = 0; i < valueArray.length; i++) { <%= valueArray[i] %> } </body> </html> <%> <%> ?? Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 13 Wartbarkeit in JSP 1.1, 1.2 etwas schöner mit JSF Tags <BODY> <f:view> <h:dataTable value=„#{articleListBean.articles}“> <h:column> <h:outputText value=„Article“/> <h:column> <h:column> <ho:outputText value=„article.name“/> </h:column> </h:dataTable> <f:view> </BODY> Kann das die Designabteilung auch? Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 14 Ideale Wartbarkeit Pures HTML – ein Framework muss das unterstützen <html > <head> <title>Login Form mit Facelets<title> </head> <body> Login: <form id='myForm' jsfc='h:form'> <input type='text' id='myInput' jsfc='h:inputText' value='# {SimpleBean.name}' /> <input type='submit' value='Abschicken' id='myBtn' jsfc='h:commandButton' /> </form> </body> </html> Das kann die Designabteilung Rahmenwerk: JSF mit Erweiterung Facelets Und der Entwickler muss nur Marken einfügen, hier ‚jsfc‘ als Referenz zu JSF-Komponenten Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 15 Einfache Änderungen des Seitenlayouts Möglich, wenn HTML und Anwendungscode strikt getrennt sind Was viele Rahmenwerke versprechen, aber nicht immer halten Aus Praxis: ideal ist, ein Rahmenwerk erzwingt die Trennung, sonst wird die Trennung (meist aus zeitgründen, Bequemlichkeit, …) nicht eingehalten Ein Rahmenwerk die Formatierung von Komponenten mit CSS ermöglicht Trennung ist wichtig Nicht jedes Framework erfüllt diese Anforderung Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 16 Lesbarkeit (1) Was macht dieses nette kleine Skript: $result = "$1\n" while m { < \s* A \s+ HREF \s* = \s* "([[^"\ ]*)" \s* > } gsix; In Perl zur Extraktion von Links in HTML Texten <A HREF=„http://www.fzi.de“> => http://www.fzi.de Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 17 Lesbarkeit (2) Was bedeutet das: listen = (1..5).to_a.map {|i| "#{i} tes Element"} In grails für for (int i=1;i<=5;i++){ liste[i] = i +‚ .tes Element'; } Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 18 Lesbarkeit vor Effizienz! Speziell bei wechselnden Teilnehmer Knappe Skripttexte schwer lesbar und nachvollziehbar Zeitaufwendig, sich in knappe Skripte anderer einzuarbeiten Skriptsprachen, können zu unlesbaren Quelltexten „verleiten“ Bei vielen Beteiligten: besser JAVA statt Skripte Daher auch in IMAGINATION Entscheidung für JAVA basierendes Framework Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 19 Model View Controller vs. Event basiertem Framework (1) Ablauf eines http-request / response mit MVC http request kommt an, Framework ruft Controller auf Controller sucht (meist auf Konfigurationsdateien basierend) passende Action aus Request Parameter werden in ein Action Bean geschrieben und validiert, http Request, Action Bean und Response werden an Action Klasse weitergegeben Action Class setzt Anwendungslogik um Action Class ruft Controller auf, um View zu generieren Controller ruft View auf (z.B. JSP Seite), um Ausgabe zu generieren Rückgabe der Response Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 20 Model View Controller vs. Event basiertem Framework (2) Eventbasiert: http-request / response Framework erhält http-Request, ermittelt verantwortliche Seiten und Komponenten Request wird in Event übersetzt (z.B. onSubmit.). Jede Komponente hat eigenen Eventhandler (vgl. swing). Jede von Event betroffene Komponente führt Event aus (Anwendungslogik) und rendert sich selbst. Framework gibt response zurück Möglichkeiten mit eventbasiertem Frameworks Abstraktion von request / response Prinzip von http => objektorientierte Erstellung von wiederverwendbarek Komponenten möglich Eventbasiertes Prinzip ermöglicht direkte Integration von AJAX für Events der Komponenten, weniger Konfiguration und meistens weniger Quelltext (im Vergleich von Wicket zu MVC basierenden Frameworks wie Struts , JSF) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 21 Auswahl des Web-Frameworks Beispiel: ImageNotion ImageNotion enthält viele Events, die einzelne Komponenten aktualisieren, z.B. Layoutbilder anzeigen Annotation von Bildern und Bildteilen Ontologieerstellung => Ideal ist ein eventbasiertes Rahmenwerk Strikte Trennung von Anwendung und Darstellung nötig Umfangreicher AJAX – Support nötig => Auswahl Web Framework: Wicket 1.3 Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 22 Apache Wicket Features Vergleich mit anderen Frameworks Wicket 1.4 URL: http://wicket.apache.org/ Aktuelle Version: 1.4 Offizielles Apache Projekt seit Juli 2007 Wiki: http://cwiki.apache.org/WICKET/ Dokumentation und Beispiele http://www.wicket-library.com/ Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 24 Features von Wicket (1) Entwicklung der Anwendung mit JAVA Alleinige Verwendung von JAVA und HTML Kein erlernen von Konzepten / Sprachen oder Funktionen nötig Keine XML Konfigurationen nötig (ausser web.xml für Servlet Container) weniger Fehlerquellen und weniger Entwicklungsaufwand Eventbasiertes Komponentenmodell basierend auf JAVA-Objekten Eventhandler für Komponenten wie in SWING Ermöglicht Erstellung von wieder verwendbaren Komponenten Einfache und direkte Integration von AJAX möglich Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 25 Features von Wicket (2) Strikte Trennung von Darstellung und Anwendung Sämtliche Darstellung basiert auf XHTML Strikte Trennung von Anwendungsentwicklung mit JAVA Objekten und Seitendesign mit HTML Integration von Komponenten mit HTML Tags (<wicket:id=“..“ .. >) Abstraktion von Basistechnologie http Seitenversionierung, ermöglicht unter anderem „Back Button Support“ für Formulare (vermeidet wiederholtes Senden und unerwünschte Seiteneffekte von POST requests) Automatisches Sessionhandling: Typesafe Session - keine manuelle Sessionverwaltung nötig Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 26 Features von Wicket (3) Internationalisierung einfache Integration von mehreren Sprachen basierend auf i18n Standard Support sehr guter Support durch die Mailingliste, kurze Reaktionszeiten auf Anfragen Open Source Quelltextanalyse ermöglicht Suche nach Bugs in Framework oder Deaktivierung von nicht benötigten Funktionen Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 27 Wicket im Vergleich mit anderen Frameworks Wicket ermöglicht die komplette Programmierung der Anwendung in JAVA, ohne Verwendung weiterer Konfigurationsfiles (JSF, Struts) oder domainspezifischen Sprachen , ist somit auch einfacher erlernbar. Umfangreicher AJAX Support bereits im Framework integriert, keine Erweiterungen hierfür notwendig (z.B. Ajax in JSF Standard nicht möglich, nur mit Erweiterungen wie z.B. Ajax4JSF Saubere Trennung von Anwendung und Darstellung. Struts verwendet JSP Seiten, in JSF entsprechende Trennung nur durch Einsatz von Faceletts (SEAM) möglich Sehr agiles Entwicklerteam, das (ungewohnt) direkt auf Anforderungen der Nutzer des Frameworks reagiert und Wünsche umsetzt. Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 28 Wicket Tutorial Aufbau einer Bildsuchmaschine Struktur Startseite Login Bildsuche Registrierung Bildergebnis Anzeige Layoutbild Upload Bilder Datenhaltung Bilddateien Bildbeschreibung (Keywords, Bildnamen) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 Userdaten 30 Download und Installation 1. Download und Installation von Maven 2. MySql Server installieren, neue Datenbank und User, z.B. Datenbank „wickettutorial“, User/Pass: wicket 3. Tutorials unter SVN Adresse (z.B. mit Tourtoise SVN) https://svn.awalter.info/docs/vorlesung/webportale/wicke t-tutorial Benutzer: tutorial , Passwort: wicket 4. Konsole starten, in SVN Verzeichnis in Unterordner workspace wechseln Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 31 Maven (1) Profiles.xml editieren Dient zur Anpassung der Konfiguration an eigenes System Ermöglicht Betrieb des gleichen Maven Projects auf unteschiedlichen Systemen, z.B. lokal, Continous integration server, etc Hier Zugangsdaten mysql Eigene Verzeichnisdaten <properties> <jdbc.uri>jdbc:mysql://localhost:3306/wickettutorial</jdbc.uri> <jdbc.username>wicket</jdbc.username> <jdbc.password>wicket</jdbc.password> <setup.imageArchiveDirectory>#directory#/workspace/searchimpl/src/main/webapp/site/img/ar chive</setup.imageArchiveDirectory> <setup.imageURL>http://localhost:8080/image/</setup.imageURL> <setup.thumbnailSize>150</setup.thumbnailSize> <setup.layoutSize>450</setup.layoutSize> </properties> Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 32 Maven (2) Pom.xml Datei in Verzeichnis „Workspace“ Definiert die Abhängigkeiten des Projekts, z.B. Wicket in 1.3.5 soll verwendet werden <properties> <wicket.version>1.3.5</wicket.version> … <dependency> <groupId>org.apache.wicket</groupId> <artifactId>wicket</artifactId> <version>${wicket.version}</version> </dependency> Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 33 Maven (3) Pom.xml in „searchimpl“ <packaging>war</packaging> Output soll „War“ File sein, zur Integration in beliebigem Servlet-Container Initialisierung von Maven Mit Konsole auf „workspace“ Verzeichnis wechseln „mvn test“ (lädt alle benötigten JAR Files, dauert etwas) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 34 Integration in Eclipse Version 3.2 oder 3.3 Eingabe „mvn eclipse:eclipse“ Eclipse starten Workspace importieren: File -> Import -> General -> Existing Project into Workspace : Auf Verzeichnis „workspace“ des Tutorials wechseln Ok Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 35 Eclipse (2): M2 Repo Variable setzen Eclipse benötigt Information zu Repository von Maven Ort: Verzeichnis von Maven/repo Konfiguration in Eclipse Window->Preferences->JAVA-> Build Path->Classpath Variables : Add new Name: M2_REPO Directory: Repo von Maven Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 36 Testen der Konfiguration und Datenbankinstallation Project enthält JUnit Test, dass Konfiguration testet und bei Erfolg alle benötigten Tabellen und Daten installiert Starten Run -> JUNIT -> New Run a single test in „searchimpl“ Test class: „CreateAndPersistanceTest“ „Apply“; „Run“ Bei Fehlern zurück zu Maven(1) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 37 Wicket Tutorial Persistence und ORM mit Spring Beans erstellen Ort: info.awalter.tutorial.beans Beans: Model der Anwendung, Datenintegration ApplicationSetup String imageArchiveDirectory; int thumbnailSize; int layoutSize; int imagesPerPage; String imageURL; Enthält Setup Informationen für die Anwendung Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 39 ImageData: Bildinformationen ImageData Enthält Informationen zu den anzuzeigenden Bildern: int imageid; String imagename; String keywords; String outputType; // thumb: small image | layout: big size Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 40 Beans : IndexWord und SearchRequest IndexWord Dient zum Speichern von Index-Wörtern Ermöglicht Autocomplete bei Suchanfragen String indexword; SearchRequest Nimmt eine Suchanfrage vom Frontend entgegen String searchword; Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 41 Bean: User User Speichert die Informationen eines Users Hier: nur username, password, email private private private private private int userId; String sessionId; String username; String password; String email; Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 42 Persistence: Tabellen in Datenbank erstellen User und Bilddaten müssen langfristig gespeichert Hier: Mapping der Objekte auf relationales DBMS mysql Tabelle : Registeredusers UserId` INTEGER `SessionID` VARCHAR(100) `Username` VARCHAR(45) `Password` VARCHAR(45), `Email` VARCHAR(100) INDEX: UNIQUE `UniqueUsername`(`Username`)) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 43 Persistence (2) Tabelle : images `imageid` INTEGER `imagename` VARCHAR(45) `keywords` VARCHAR(255) PRIMARY KEY(`imageid`) INDEX `keywordindex`(`keywords`) <- Volltextindex Tabelle keywordindex `keyword` VARCHAR(50) DEFAULT '', UNIQUE uniquekeyword(`keyword`) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 44 Spring: Object Relational Mapping (ORM) Spring Framework: http://www.springframework.org/ Inversion of control: Anwendung kennt nur die Interfaces, Spring initiert die benötigten Implementierungen Ermöglicht Abstraktion von DBMS (durch untersch. Implementierungen) Direkter Aufruf der entsprechenden Objekte aus Anwendung möglich (injection) Initiierung von Objekten (z.B. ApplicationSetup) Integriertes ORM Vorgehen Interface erstellen Implementierung Setup Spring: applicationContext.xml Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 45 Methoden für User: UserManagerDao Ort: info.awalter.tutorial.persistence.user Interface UserManagerDao public List getUsers(); public User getUserByUsernamePassword(String username, String password); public boolean changePassword(int UserId, String password); public User updateUserData(User user); public User getUserByCookieId(String cookieId); public User getUserByUserId(int userid); public boolean setUserSessionId(int userid, String cookieId); public User createUser(User user); public boolean deleteUser(User user); public boolean isUsernameInList(String username); Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 46 UserManagerDao: Spring setup applicationContext.xml <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroymethod="close"> <property name="driverClassName"><value>org.gjt.mm.mysql.Driver</value></property> <property name="url"><value>${jdbc.uri}</value></property> <property name="username"><value>${jdbc.username}</value></property> <property name="password"><value>${jdbc.password}</value></property> <property name="initialSize"><value>10</value></property> <property name="maxActive"><value>10</value></property> <property name="maxIdle"><value>20000</value></property> </bean> Name des Beans in Anwendung <bean id="persistenceuser" class="info.awalter.tutorial.persistence.user.UserManagerDaoJdbc"> <property name="dataSource"><ref local="dataSource"/></property> </bean> Zu verwendende Implementierung Zu verwendende Datenquelle Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 47 Methoden für ImageData Ort: info.awalter.tutorial.persistence.images Interface ImageManagerDao public public public public public List getAllImages(); List searchImages(String keywords); ImageData insertImage(ImageData i); boolean updateImage(ImageData i); boolean deleteImage(ImageData i); public byte[] loadImageFile(ImageData i, String outputType ); public boolean saveImageFile(ImageData i,InputStream input); public boolean deleteImageFile(ImageData i); public List getAllIndexKeywords(); public List getAllIndexKeywordsStartingWith(String start); public boolean insertIndexKeyword(String keyword); Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 48 Persistence: Zusammenfassung Beans erstellen: Model in der Webanwendung Datenbank erstellen Framework für ORM verwenden Hier: Spring Alternativ: Hybernate (speziell wenn Transaktionen benötigt werden) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 49 Wicket Tutorial Anwendung erstellen Erstellen einer Wicket Anwendung Ort: info.awalter.tutorial.application SearchApplication: In Wicket: Setup der ganzen Anwendung direkt in JAVA (statt in XML Konfigurationsdateien, z.B. JSF) Authorisierung SearchAuthorizationStrategy storeAuthStrategy = new SearchAuthorizationStrategy(); Ort der HTML-Dateien Standard: im gleichen Verzeichnis wie JAVA File Anpassung: alternativer Ort resourceSettings.addResourceFolder( "site/html" ); Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 51 Anwendung (2) SearchApplication (Fortsetzung) Seiten auf feste Verzeichnisse mounten this.mountBookmarkablePage("/login", Login.class); Home Page der Anwendung festlegen public Class getHomePage() { return Home.class; } Spring Injection initialisieren addComponentInstantiationListener(new SpringComponentInjector(this)); Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 52 Anwendung in Servlet Container initialisieren Initialisierungen mit web.xml (Standard in Servlet Container) Ort: src/main/webapp/WEB-INF/web.xml Setup von Spring und Context Listener <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> Wicket Anwendung initialisieren <init-param> <param-name>applicationClassName</param-name> <param-value>info.awalter.tutorial.application.SearchApplication</param-value> </init-param> Mapping der Anwendung auf Hauptverzeichnis: localhost:8080/ <filter-mapping> <filter-name>search</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 53 Anwendung: Authorisierung Ort: info.awalter.tutorial.application SearchAuthorizationStrategy implements IAuthorizationStrategy if (SecuredSearchPage.class.isAssignableFrom(componentClass)) … Interface, dass zugangsbeschränkte Seiten implementieren if (session.isUserLoggedIn()) { return true; // User ist authorisiert } // sonst weiterleitung auf Login login=new Login(); throw new RestartResponseAtInterceptPageException(login.getClass()); Authorisierung mit Interfaces Session hält Userinformationen: Login setzt isUserLoggedIn auf true für berechtigte User Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 54 Context eines Users SearchSession Hält Zustände eines Users SessionId (Identifikation des Users über http) Locale: bevorzugte Sprache des Users Authorisierungsinformationen Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 55 Home Page: Die Startseite der Anwendung Ort: org.apache.wicket.markup.html.WebPage Home extends PageTemplate Templating Ermöglicht einheitlichen Look aller Seiten Logo Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 Top Menu 56 Templates Ort: src/main/webapp/site/html/info/awalter/tutorial/pages PageTemplate.html Definiert einheitliches Layout der Seite HTML Markup zur Erweiterung der Seite: <wicket:child> Here comes the child content </wicket:child> Inhalt der erweiterten Seiten wird dort eingefügt. HTML Markup in erweiterten Seiten, z.B. in Home.html <wicket:extend> … html markup <wicket:extend> Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 57 Wicket Markups Verbindung von HTML und Anwendung Alle Komponenten bekommen eine wicket id (String). Dieser wird in HTML Text an entsprechenden Stellen platziert. HTML Marken für Komponenten: <span wicket:id=„komponentenid“/> Links: <a wicket:id="linkToHome" class="standardlink">Über</A> Aufruf in Wicket, z.B. für Link BookmarkablePageLink linkToHome = new BookmarkablePageLink("linkToHome", Home.class); Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 58 Internationalisierung Unterstützung bei Seiten / Templates Dateien werden mit entsprechenden Endungen des Ländercodes versehen, z.B: PageTemplate_de.html : deutsche Version PageTempate.html : Default = englische Version Unterstützung für Ausgaben in Anwendungen Propertie-Files mit Namen entsprechend der Klasse + Sprachendung, z.B. home_de.properties Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 59 Page Template Funktionen <span wicket:id="toparea„/> Lädt Komponente „SmallLoginForm“, wenn der User unregistriert ist, sonst das Suchmenü Schreibt Seitentitel: Abstrakte Methode getPageTitle(); Konkrete Klassen schreiben ihren Seitentitel in Methode, PageTemplate füllt Labelkomponente für Seitentitel Erstellt Links auf statische Seiten Wichtigste Arten von Links in wicket: Link : mit Event „onClick“: Links die nur während einer Session gültig sind BookmarkablePageLink: Links die man auch Bookmarken kann (entspricht „mount“ Befehl in SeachApplication) AjaxLink: löst ein AjaxEvent aus, gibt eine Componente zurück an Ajax Request Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 60 Home Funktionen der Startseite Anzeige eines zufällig geladenen Bildes Anzeige eines statischen Textes Alle statischen Seiten (also auch About, etc) werden von StaticTemplate erweitert => immer Anzeige des zufällig erzeugten Bildes Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 61 Erstellung eigener Komponenten info.awalter.tutorial.pages.user.SmallLoginPanel Eigene Komponenten: extends Panel HTML Markup: <wicket:panel> … HTML Inhalt des Panels </wicket:panel> Komponente dann an beliebigen Stellen in Seite einbindbar. Seite Home nun darstellbar Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 62 Starten der Anwendung aus Eclipse Merve Tomcat Plugin installieren http://merve.sourceforge.net/updates/eclipse-3.2/ Alternativ: mvn jetty:run Run->Merve Tomcat Plugin -> New Context Root Dir: searchimpl/src/main/webapp/ Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 63 Startseite der Demo Anwendung Komponente: SmallLoginPanel Internationalisierung Komponente: DisplayRandomImage Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 64 Formulare in wicket Formulare nehmen User-Eingaben entgegen Ereignis: onSubmit() Hauptkomponenten: TextField, Password, TextArea, … Daten an Formulare binden Prinzip: Jede Formularkomponente bekommt Signatur einer Bean-Variablen oder einer Variablen in Klasse Eingaben werden an diese Variable gebunden Beispiel: TextField user = new TextField("username"); Bean oder Klasse benötigt Variable „username“ und Methoden getUsername, setUSername Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 65 Formulare: Modelle in Wicket PropertyModel: bindet eine Methode, z.B. für Labels geeignet new PropertyModel(this,"pageTitle") (aus PageTemplate) CompoundPropertyModel: bindet alle get/set Methoden einer Bean oder Klasse final User userbean=new User(); form.setModel(new CompoundPropertyModel(userbean)); Siehe z.B. in Login, Register Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 66 Validatoren für Usereingaben Automatisches validieren von Usereingaben vor Abruf der onSubmit() Methode eines Formulares Ablauf (z.B. in info.awalter.tutorial.pages.user.Register) 1. FeedbackPanel Componente einbinden in Seite add(new FeedbackPanel("feedback")); -> Wicket schreibt automatischFeedback in diesen Panel 2. Validatoren an Formelemente binden (aus org.apache.wicket.validation.validator.) EmailAddressValidator validiert E-Mail Format Eingabe erforderlich: formelement. setRequired(true); Mindestlänge erforderlich: MinimumLengthValidator Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 67 Ajax Integration für Formularelemente An Formularelemente können Events gebunden werden, die mittels Ajax abgearbeitet werden. Diese ermöglichen z.B. Autocomplete oder direkte Information der User über Fehleingaben Beispiel Reaktion auf Fehleingaben: Register user.add(new AjaxFormComponentUpdatingBehavior("onchange") { target.addCompontent(…); } Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 68 Beispiel: Registrierungsformular Ort: info.awalter.tutorial.pages.user.Register 1. Bean User wird als CompoundPropertyModel gebunden 2. Formular enthält Textfelder username, email und Passwortfeld password 3. Minlength Validatoren für username / password: 4 Email Validator für Feld email 4. onSubmit Event: Wicket validiert Eingaben, bricht bei unkorrekten Eingaben ab und sendet Fehlerstring an FeedbackPanel 5. onSubmit: falls alle Eingaben richtig sind wird onSubmit Methode des Formulars abgearbeitet 6. Methode prüft, ob username bereits existiert, falls nicht wird bean an Spring bean zur Speicherung gesendet userdao.createUser(userbean); 7. User wird in Session eingeloggt 8. Weiterleitung auf Startseite Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 69 Login Formular Alle Seiten, die durch unberechtigte User nicht betreten werden dürfen implementieren Interface SecuredSearchPage, z.B. LayoutPage Wicket leitet bei entsprechenden unberechtigten Aufrufen den Nutzer an Login Formular weiter Login Formular hat (vgl. Register bean user als model). Nimmt username / password entgegen, wenn user vorhanden userdao.getUserByUsernamePassword wird user in Session gesetzt (Authorisiert) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 70 UserMenuPanel: Starten von Suchanfragen Übermittlung der Suchanfragen mit Formular Textfeld für Suchanfragen enthält Autocomplete Funktion Umsetzung Verwendung der Wicket-Komponente AutoCompleteTextField searchword = new AutoCompleteTextField("searchword") Funktion: sendet „onkeyup“ Events per Ajax Nimmt Eingabe, z.b. input = „b“ entgegen Suche entsprechender Wörter mit imagedao imagedao.getAllIndexKeywordsStartingWith(input); Rückgabe der passenden Keywords als Liste Schnell integriert, keine JAVA-Script Programmierung nötig Bei onSubmit: Aufruf der Seite SearchResultPage mit Suchanfrage Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 71 SearchResultPage: Generierung von Suchergebnisseiten SearchResultPage Komponenten Anzeige von 8 Bildern pro Seite als Thumbnailtabelle Vor / Zurück Navigation Ruft die nächsten Seite per Ajax auf Aktualisiert nur die Thumbnailtabelle AjaxLink previousPage = new AjaxLink("previousPage"){ public void onClick(AjaxRequestTarget target) { // set currentpage +1 : setCurrentPage(getCurrentPage()-1); // remove current content from thumbnailtable thumbnailtable.removeAll(); // set table and return to ajaxrequest target.addComponent(getThumbnailTable()); }; Anzeige der Treffermenge: statisch Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 72 Generierung der Thumbnailtabelle Ort: info.awalter.tutorial.pages.search.thumbnailtable Verwendung von RepeatableView ImageTableRow: generiert Zeilen <TABLE wicket:id="tablerow" BORDER=0 > <tr> </tr> </TABLE> ImageTableCol: generiert Spalten <wicket:panel> <td wicket:id="tablecol" width="200" valign=bottom> </td> </wicket:panel> Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 73 UploadNewImages: neue Bilder aufladen UploadNewImages Nutzung der Wicket Komponente MultiFileUploadField und UploadProgressBar aus Wicket Extension Bibliothek Bilder aufladen nur über normale Formulare möglich! onSubmit(): Nimmt Bilddateien entgegen image=imagedao.insertImage(image); prüft, ob Bild mit Dateinamen bereits existiert. Falls ja kommt Fehlermeldung zurück imagedao.saveImageFile(image, upload.getInputStream()); speichert die Bilddatei in Archivverzeichnis Rückgabe der Erfolgs / Fehlermeldung als RepeatableView aus Labels bestehend Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 74 Logout Logout Beendet Session des Users this.getSession().invalidate(); Entfernt alle Zustände der Usersession Login beendet Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 75 Testen von Wicket Anwendungen: wickettester WicketTester Ermöglicht Durchführung von JUnit Tests für Wicket-Seiten ohne jedesmal den Servletcontainer starten zu müssen Auch Wicket Tests mit Spring-Integration möglich Siehe hierzu: TestSearchApplication (Context muss manuell initiiert werden) Beispiel: WicketApplicationTest Ort: info.awalter.tutorial.wickettest Aufruf einer Seite: tester.startPage(home); tester.assertRenderedPage(home.getClass()); => prüft, ob Seite Home richtig erstellt werden kann Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 76 Wickettester (2) Test von Formularen Login login=new Login(); tester.startPage(login); tester.assertRenderedPage(login.getClass()); // set form values: use FormTester FormTester form = tester.newFormTester("loginForm"); form.setValue("username", "fzi"); form.setValue("password", "web"); // submit form form.submit(); Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 77 Zusammenfassung Gezeigt wurde mit dieser Demo-Anwendung Build-Kontrolle Integration von Daten mittels Beans und Springframework Integration von Spring in Wicket Einheitliches Layout mit Templating und Internationalisierung Integration von eigenen Komponenten und Nutzung von Standardkomponenten Formulare erstellen, Datenbindung von Beans, Validierung Integration von AJAX-Funktionen Testen von Wicket-Anwendungen Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 78 Exkurs: ImageNotion In Demo Anwendung: Suche „Anna“ zeigt unterschiedliche Sachverhalte (Hund namens Anna, Frau namens Anna) Gewünscht Unterscheidung bereits bei Anfrage Ausblick Lösung durch semantische Techniken (Vorlesungen A. Schmidt) Umsetzung für Bilder: ImageNotion (demo) Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 79 Quellen Wicket Homepage: http://wicket.apache.org/ Wicket Erweiterungen http://www.wicket-library.com Vergleich Wicket / Struts http://cwiki.apache.org/WICKET/struts.html Vergleich Wicket / JSF http://ptrthomas.wordpress.com/2007/05/14/a-wicketuser-tries-jsf/ Vergleich Wicket / Tapestry http://agileskills2.org/blog/2007/09/my_thoughts_on_the_ differences.html Informationsintegration & Web-Portale WS 2007/08 WS 2009/10 80