| 1 | \documentclass[11pt,a4paper]{article} |
|---|
| 2 | |
|---|
| 3 | % packages |
|---|
| 4 | \usepackage{graphicx} |
|---|
| 5 | \usepackage[utf8]{inputenc} |
|---|
| 6 | \usepackage[ngerman]{babel} |
|---|
| 7 | \usepackage[T1]{fontenc} |
|---|
| 8 | \usepackage{listings} |
|---|
| 9 | \usepackage{color} |
|---|
| 10 | \usepackage{fancyhdr} |
|---|
| 11 | |
|---|
| 12 | % style |
|---|
| 13 | \setlength{\textwidth}{150mm} |
|---|
| 14 | \setlength{\textheight}{210mm} |
|---|
| 15 | \pagestyle{fancy} |
|---|
| 16 | \addtolength{\headheight}{1ex} |
|---|
| 17 | \renewcommand{\baselinestretch}{1.2} |
|---|
| 18 | |
|---|
| 19 | % syntax colors |
|---|
| 20 | %\color{<colour>} |
|---|
| 21 | \definecolor{middlegray}{rgb}{0.5,0.5,0.5} |
|---|
| 22 | \definecolor{lightgray}{rgb}{0.8,0.8,0.8} |
|---|
| 23 | \definecolor{orange}{rgb}{0.8,0.3,0.3} |
|---|
| 24 | \definecolor{yac}{rgb}{0.6,0.6,0.1} |
|---|
| 25 | |
|---|
| 26 | % meta |
|---|
| 27 | \title{AJAX + Google Web Toolkit} |
|---|
| 28 | \author{Torben Brodt} |
|---|
| 29 | \date{\today} |
|---|
| 30 | \fancyhead[L]{AJAX + Google Web Toolkit} |
|---|
| 31 | \fancyhead[R]{\thepage} |
|---|
| 32 | \fancyfoot[L]{Fachhochschule Wiesbaden, Medieninformatik} |
|---|
| 33 | \fancyfoot[R]{Torben Brodt} |
|---|
| 34 | \fancyfoot[C]{\ } % keine Seitenzahl unten |
|---|
| 35 | |
|---|
| 36 | % content |
|---|
| 37 | \begin{document} |
|---|
| 38 | \maketitle % erzeugt den Titel mit Autor und Datum |
|---|
| 39 | |
|---|
| 40 | % abstract |
|---|
| 41 | \begin{abstract} |
|---|
| 42 | Die Facharbeit handelt von der AJAX-Technologie - Grundlage moderner Web-Anwendungen. |
|---|
| 43 | Sie beginnt bei der ErklÀrung der drei Basistechnologien DOM, JavaScript und HTTP, gibt ein Programmierbeispiel und geht auf typische Probleme ein. |
|---|
| 44 | Dann wird das Google Web Toolkit erklÀrt und eine BrÌcke zu Java geschlagen. |
|---|
| 45 | Das Google Web Toolkit versucht den Desktop-Entwicklungs-Zyklus auf Web-Anwendungen zu ÃŒbertragen. |
|---|
| 46 | Es werden Grundlegende Java-Kenntnisse und der sichere Umgang mit einer Entwicklungsumgebung vorausgesetzt. |
|---|
| 47 | \end{abstract} |
|---|
| 48 | \newpage |
|---|
| 49 | \tableofcontents |
|---|
| 50 | \newpage |
|---|
| 51 | |
|---|
| 52 | |
|---|
| 53 | \section{Einleitung} \label{sec:intro} |
|---|
| 54 | Seit Web-Seiten existieren, gibt es auch den Begriff der Web-Anwendung. |
|---|
| 55 | Der Begriff hat sich ÃŒber die Jahre stark gewandelt. |
|---|
| 56 | Am Anfang war es die Bezeichnung fÃŒr einfache Formular-Interaktionen. |
|---|
| 57 | Nach dem ersten AJAX-Medienrummel um das Jahr 2005, |
|---|
| 58 | wurden aber neue Technologien bekannt, die eine Web-Anwendung Àhnlich mÀchtig machen konnten, wie man es von Desktop-Anwendungen kennt. |
|---|
| 59 | |
|---|
| 60 | Besonders im professionellen Umfeld wird wegen der einfachen clientseitigen Einrichtung und der strikten Server/Client Trennung verstÀrkt auf Web-Anwendungen gebaut. |
|---|
| 61 | Moderne Web-Anwendungen lassen sich komponentenweise kombinieren, sie greifen ineinander ÃŒber und reagieren sofort Benutzeraktionen. |
|---|
| 62 | |
|---|
| 63 | Die BrÌcke zwischen Web- und Desktop-Welt wird durch gleiche Bedienkonzepte wie z.B. Drag\&Drop, AutovervollstÀndigung oder die sofortige Formularvalidierung geschlagen. |
|---|
| 64 | |
|---|
| 65 | In den folgenden Kapiteln wird erlÀutert, was die grundlegende Technologie 'AJAX' ausmacht und wie man sie als Programmierer fÌr sich nutzen kann. |
|---|
| 66 | Weiter wird auf garantierte Stolpersteine eingegangen und letztendlich eine mögliche Antwort auf verschiedene Probleme prÀsentiert: |
|---|
| 67 | Das Google Web Toolkit. |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | \section{EinfÃŒhrung in AJAX} \label{sec:ajax} |
|---|
| 71 | AJAX steht fÃŒr Asynchronous JavaScript and XML. |
|---|
| 72 | |
|---|
| 73 | Vermutlich weià jetzt niemand mehr als zuvor, doch es sollte immerhin klar geworden sein, |
|---|
| 74 | dass es ein Begriff aus der Informatik ist und man fÃŒr dessen Verwendung weder das gleichnamige Waschmittel, noch den FuÃballverein kennen muss. |
|---|
| 75 | |
|---|
| 76 | AJAX ist keine Programmiersprache, sondern beschreibt das Konzept von drei Technologien: |
|---|
| 77 | DOM zur Manipulation von Web-Seiten, |
|---|
| 78 | JavaScript zur Ereignisbehandlung und |
|---|
| 79 | HTTP zum Nachladen von Daten. |
|---|
| 80 | |
|---|
| 81 | Das Zusammenspiel dieser drei Technologien erlaubt dynamische Websites, |
|---|
| 82 | die durch asynchrone Verbindungen in einer interaktiven Umgebung beliebige Datenmengen bewÀltigen können. |
|---|
| 83 | |
|---|
| 84 | Der Client schickt HTTP-Anfragen an den Server, ohne dass die eigentliche Seite neu geladen wird, oder der Benutzer wÀhrenddessen warten muss. |
|---|
| 85 | |
|---|
| 86 | \subsection{Document Object Model} \label{sec_ajax_dom} |
|---|
| 87 | Das Document Object Model (kurz DOM) ist eine vom W3-Konsortium verabschiedete Norm fÃŒr die Definition einer Baumstruktur und ihrer Traversierungsfunktionen in XML. |
|---|
| 88 | Mit DOM lÀsst sich also ein komplettes HTML Dokument in ein dynamisches Objekt binden. |
|---|
| 89 | |
|---|
| 90 | Das Beispiel zeigt den DOM-Baum einer Standard-Web-Seite, mit Head- und Body-Bereich und mehreren Unterknoten. |
|---|
| 91 | \begin{figure}[htp] |
|---|
| 92 | \centering |
|---|
| 93 | \includegraphics{img/dom.eps} |
|---|
| 94 | \caption{ReprÀsentierung einer Website in einem DOM-Baum} |
|---|
| 95 | \label{fig:ajax_dom} |
|---|
| 96 | \end{figure} |
|---|
| 97 | |
|---|
| 98 | In einer Client-Server-Architektur lÀsst sich DOM sowohl im Backend zur Dokumentengenerierung, |
|---|
| 99 | als auch und im Frontend zum dynamischen Manipulieren nutzen. |
|---|
| 100 | |
|---|
| 101 | \subsection{JavaScript} \label{sec_ajax_javascript} |
|---|
| 102 | Um Verwechslungen vorzubeugen, sei an dieser Stelle gesagt, dass es sich bei JavaScript weder um Java handelt, |
|---|
| 103 | noch dass konzeptionelle Ãhnlichkeiten zwischen den beiden Sprachen existieren. |
|---|
| 104 | JavaScript Code wird nicht fÃŒr die AusfÃŒhrung in einer VirtualMaschine kompiliert, sondern zur Interpretation im Klartext an den Browser ÃŒbertragen. |
|---|
| 105 | Die AusfÌhrung des Codes lÀuft somit nicht auf dem Webserver, sondern auf dem eigenen Rechner ab. |
|---|
| 106 | |
|---|
| 107 | JavaScript lÀuft in einer Sandbox und schrÀnkt darÌber den Zugriff auf Netzwerkfunktionen oder das Dateisystem ein. |
|---|
| 108 | |
|---|
| 109 | Skripte werden in das HTML-Dokument eingebettet, um auf Ereignisse zu reagieren oder die DOM ReprÀsentierung der Website dynamisch zu manipulieren. |
|---|
| 110 | |
|---|
| 111 | Ein simples Beispiel ist der Aufruf der alert-Funktion. |
|---|
| 112 | |
|---|
| 113 | \begin{lstlisting}[caption={JavaScript Hello World!}\label{lst:javascript_example},captionpos=b,language=html] |
|---|
| 114 | <html> |
|---|
| 115 | <head><title>Test</title> |
|---|
| 116 | <script type="text/javascript"> |
|---|
| 117 | alert("Hello World!"); |
|---|
| 118 | </script> |
|---|
| 119 | </head><body> |
|---|
| 120 | </body></html> |
|---|
| 121 | \end{lstlisting} |
|---|
| 122 | |
|---|
| 123 | \begin{figure}[htp] |
|---|
| 124 | \centering |
|---|
| 125 | \includegraphics{img/alert.eps} |
|---|
| 126 | \end{figure} |
|---|
| 127 | |
|---|
| 128 | FÃŒr die Programmierung mit JavaScript gibt es ein umfangreiches Online-Standardwerk unter http://de.selfhtml.org. |
|---|
| 129 | |
|---|
| 130 | |
|---|
| 131 | \subsection{HTTP} \label{sec_ajax_http} |
|---|
| 132 | HTTP ist ein zustandsloses Protokoll zur DatenÃŒbertragung zwischen zwei Computern. |
|---|
| 133 | Ein Computer formuliert eine Anfrage. |
|---|
| 134 | Der andere Computer beantwortet diese mit einem Inhalt. |
|---|
| 135 | |
|---|
| 136 | Normale Websites laden in einem Rutsch. |
|---|
| 137 | Dazu formuliert der Client eine HTTP-Anfrage mit Hostnamen und Pfad. |
|---|
| 138 | Wird die URL www.foo.com/ajax.html im Browser aufgerufen, wird die folgende Anfrage gesendet: |
|---|
| 139 | |
|---|
| 140 | \begin{lstlisting} |
|---|
| 141 | GET /ajax.html HTTP/1.1 |
|---|
| 142 | Host: www.foo.com |
|---|
| 143 | \end{lstlisting} |
|---|
| 144 | |
|---|
| 145 | Der Server beantwortet die Anfrage mit einem Status-Code und den angeforderten Daten: |
|---|
| 146 | \begin{lstlisting}[language=html] |
|---|
| 147 | HTTP/1.1 200 OK |
|---|
| 148 | Content-Type: text/html |
|---|
| 149 | |
|---|
| 150 | <html> |
|---|
| 151 | <head> |
|---|
| 152 | <title>Hello World!</title> |
|---|
| 153 | </head> |
|---|
| 154 | <body> |
|---|
| 155 | Hello World! |
|---|
| 156 | </body> |
|---|
| 157 | </html> |
|---|
| 158 | \end{lstlisting} |
|---|
| 159 | |
|---|
| 160 | Klickt man auf einen Link werden wieder und wieder neue HTTP-Anfragen geschickt und das komplette Dokument neu ÃŒbertragen. |
|---|
| 161 | |
|---|
| 162 | Das folgende Sequenzdiagramm beschreibt den Ablauf von Anfrage und Antwort. |
|---|
| 163 | \begin{figure}[htp] |
|---|
| 164 | \centering |
|---|
| 165 | \includegraphics{img/http-classic.eps} |
|---|
| 166 | \caption{Das klassische HTTP.} |
|---|
| 167 | \label{fig:http-classic} |
|---|
| 168 | \end{figure} |
|---|
| 169 | |
|---|
| 170 | \subsection{Asynchrones HTTP} \label{sec_ajax_asynchronous} |
|---|
| 171 | AJAX erweitert dieses starre Konzept und erlaubt das asynchrone Senden und Empfangen von Daten ÃŒber HTTP. |
|---|
| 172 | Das bedeutet, dass das Dokument nicht komplett geladen werden muss, |
|---|
| 173 | sondern es stattdessen wÀhrend der Laufzeit nachgeladen werden kann. |
|---|
| 174 | WÀhrend des Ladevorgangs kann der Benutzer weiter mit der Seite interagieren, |
|---|
| 175 | da der Browser dafÌr sorgt, dass die asynchrone Anfrage in einem eigenen Thread ablÀuft. |
|---|
| 176 | |
|---|
| 177 | Zudem ist keine Socketverbindung auf Ebene von TCP oder UDP notwendig. |
|---|
| 178 | Das EinfÃŒgen in den DOM Baum erledigt dann JavaScript. |
|---|
| 179 | |
|---|
| 180 | So funktioniert das Zusammenspiel der drei Technologien: |
|---|
| 181 | Die Ajax-Engine reagiert auf einen Klick in der BenutzeroberflÀche, |
|---|
| 182 | schickt daraufhin eine HTTP-Anfrage an den Server und sobald dieser antwortet, |
|---|
| 183 | wertet sie die Antwort aus und fÃŒgt die Informationen mit DOM-Manipulationen in das eigentlich Dokument wieder ein. |
|---|
| 184 | |
|---|
| 185 | \begin{figure}[htp] |
|---|
| 186 | \centering |
|---|
| 187 | \includegraphics{img/http-ajax.eps} |
|---|
| 188 | \caption{Eine AJAX Anfrage ÃŒber HTTP.} |
|---|
| 189 | \label{fig:http-ajax} |
|---|
| 190 | \end{figure} |
|---|
| 191 | |
|---|
| 192 | |
|---|
| 193 | \section{AJAX Programmierung} \label{sec:ajax_programming} |
|---|
| 194 | FÃŒr fertige AJAX Kunstwerke gibt es viele unterschiedliche JavaScript basierte Frameworks. |
|---|
| 195 | FÌr das VerstÀndnis genÌgt es aber sich den AJAX-Kern anzuschauen. |
|---|
| 196 | Dieser besteht aus dem XMLHttpRequest im Browser und der Skriptsprache JavaScript, ÃŒber das dieser angesprochen wird. |
|---|
| 197 | |
|---|
| 198 | \subsection{Ereignisbehandlung mit EventHandlern} \label{sec_ajax_eventhandler} |
|---|
| 199 | Die HTTP-Anfragen werden durch JavaScript Ereignisse ausgelöst. |
|---|
| 200 | EventHandler sind das Bindeglied zwischen HTML und JavaScript. |
|---|
| 201 | Das W3-Konsortium hat sie als HTML-Attribut in den Sprachstandard aufgenommen. |
|---|
| 202 | |
|---|
| 203 | Hier ist ein Handler definiert, der ausgelöst durch einen Mausklick die Funktion foo() aufruft. |
|---|
| 204 | An dieser Stelle wird davon ausgegangen, dass die Funktion foo() existiert. |
|---|
| 205 | Sie wird im Beispiel nachgereicht. |
|---|
| 206 | \begin{lstlisting}[language=html] |
|---|
| 207 | <div onclick="foo()">Container</div> |
|---|
| 208 | \end{lstlisting} |
|---|
| 209 | |
|---|
| 210 | Es sind alle erdenklichen Ereignisse möglich. |
|---|
| 211 | JavaScript kann genauso auf das Fokussieren oder Verlassen von Eingabefeldern reagieren, |
|---|
| 212 | wie auf das Ãberfahren eines Elements mit der Maus. |
|---|
| 213 | |
|---|
| 214 | \subsection{XMLHTTP als Kommunikationsschnittstelle} \label{sec_ajax_xmlhttprequest} |
|---|
| 215 | Das XMLHttpRequest Objekt ist eine API, die den HTTP-Zugriff auf Websites der eigenen Domain\footnote{W3C-Vorschlag fÃŒr eine Cross-Site-Extension in 'XMLHttpRequest 2' unter http://lists.w3.org/Archives/Public/public-webapi/2006Jun/0012.html} erlaubt. |
|---|
| 216 | FÌr die Kommunikation Ìber das HTTP-Protokoll werden die beiden gebrÀuchlichsten Anfrage-Methoden POST und GET genutzt. |
|---|
| 217 | Wurde ein Event ausgelöst und eine Anfrage abgeschickt, Ìbernimmt das XMLHttpRequest den Aufruf der Callback-Methode. |
|---|
| 218 | |
|---|
| 219 | Aus historischen GrÌnden wird das XMLHttpRequest Objektes von den meisten Browser unterschiedlich initialisiert und sollte daher stets gekapselt werden.\footnote{Eine Implementierung fÌr die gÀngigsten Browser findet man unter http://de.wikipedia.org/wiki/XMLHttpRequest} |
|---|
| 220 | |
|---|
| 221 | \subsection{Callback Methoden} \label{sec_ajax_callback} |
|---|
| 222 | Die Callback Methode ist die 'RÃŒckruf'-Funktion mit einer Antwort vom Server. |
|---|
| 223 | Das XMLHTTP Objekt initialisiert die Callback Methode und ruft sie nach jeder readyState-Ãnderungen auf. |
|---|
| 224 | Erst beim Status Vier steht das gesamte Dokument zur VerfÃŒgung. |
|---|
| 225 | |
|---|
| 226 | Wann und ob die readyStates tatsÀchlich wechseln, kann auf Grund vieler Einflussfaktoren wie Bandbreite und Serverauslastung nie garantieren werden. |
|---|
| 227 | Die Callback Methode ist daher als eine void-Funktion ohne RÃŒckgabewert zu implementieren. |
|---|
| 228 | HÀufig nutzt man den Callback, als eine anonyme Methode. |
|---|
| 229 | |
|---|
| 230 | \subsection{VollstÀndiges Beispiel} \label{sec_ajax_example} |
|---|
| 231 | Nun ist alles bekannt, was benötigt wird, um die Funktion foo() zu implementieren. |
|---|
| 232 | Sie soll eine AJAX Anfrage ausfÃŒhren, um eine Liste von Namen nachzuladen. |
|---|
| 233 | Dazu wird die AJAX Klasse initialisiert und eine GET-Anfrage an backend.php geschickt. |
|---|
| 234 | Diese liefert im Beispiel folgendes XML Dokument. |
|---|
| 235 | \begin{lstlisting}[language=xml] |
|---|
| 236 | <root> |
|---|
| 237 | <online>hans</online> |
|---|
| 238 | <online>peter</online> |
|---|
| 239 | <online>gunther</online> |
|---|
| 240 | </root> |
|---|
| 241 | \end{lstlisting} |
|---|
| 242 | |
|---|
| 243 | In unserer anonymen Callback Methode, können wir die Daten mit DOM traversieren und in den Node mit appendChild direkt in den Website-Context einfÌgen. |
|---|
| 244 | \begin{lstlisting}[caption={VollstÀndiges AJAX Beispiel}\label{lst:ajax_example},captionpos=b,language=java] |
|---|
| 245 | function foo() { |
|---|
| 246 | var req = new XMLHttpRequest(); //mozilla implementierung |
|---|
| 247 | req.open('get', 'backend.php'); |
|---|
| 248 | req.onreadystatechange = function() { |
|---|
| 249 | if ((req.readyState == 4) && (req.status == 200)) { |
|---|
| 250 | var domZiel = document.getElementById('context'); |
|---|
| 251 | var xmlQuelle = req.responseXML.getElementsByTagName('online'); |
|---|
| 252 | for(var i=0; i<xmlQuelle.length; i++) { |
|---|
| 253 | domZiel.appendChild(xmlQuelle[i]); |
|---|
| 254 | } |
|---|
| 255 | } |
|---|
| 256 | } |
|---|
| 257 | req.send(null); |
|---|
| 258 | } |
|---|
| 259 | \end{lstlisting} |
|---|
| 260 | |
|---|
| 261 | |
|---|
| 262 | \subsection{Probleme in AJAX} \label{sec_ajax_prob} |
|---|
| 263 | Das Arbeiten mit den am meisten verbreitetsten Web-Technologien HTML und JavaScript stellt die Entwickler vor eine neue Herausforderung. |
|---|
| 264 | |
|---|
| 265 | Bei der normalen GUI-Programmierung kann die Anwendung bereits innerhalb der Entwicklungsumgebung debuggt und getestet werden. |
|---|
| 266 | Da JavaScript-Anwendungen aber erst beim Endbenutzer interpretiert werden, |
|---|
| 267 | benötigt der Entwickler verschiedene Testsysteme aus Betriebssystem- und Browserkombinationen. |
|---|
| 268 | Auch der komplette Klick-Lebenszyklus wird durch das besondere Verhalten der Callback-Methoden und die strikte Trennung zwischen der JavaScript-Frontend-Implementierung und der Backend-Implementierung schier unmöglich zu testen. |
|---|
| 269 | Es werden Testszenarien gebraucht die eine ServerÃŒberlastung emulieren. |
|---|
| 270 | |
|---|
| 271 | Selbst fÃŒr den Benutzer ergeben sich Nachteile. |
|---|
| 272 | Denn das Navigieren Ìber die Browserfunktionen oder das Neuladen der Seite können ohne ein ausgeklÌgeltes Konzept zu Fehlverhalten fÌhren. |
|---|
| 273 | |
|---|
| 274 | Wie der Titel dieser Ausarbeitung nahe legt, heiÃt die Lösung fÃŒr all diese Probleme 'Google Web Toolkit' (oder kurz GWT). |
|---|
| 275 | |
|---|
| 276 | Das GWT erlaubt eine Entwicklung fern von HTML und JavaScript und verwendet dazu hundertprozentig reines Java. |
|---|
| 277 | Dieses Kernkonzept wird in den folgenden Kapiteln erlÀutert. |
|---|
| 278 | |
|---|
| 279 | |
|---|
| 280 | \section{Google Web Toolkit} \label{sec:gwt} |
|---|
| 281 | \subsection{EinfÃŒhrung in das Google Web Toolkit} \label{sec_gwt_intro} |
|---|
| 282 | Das Google Web Toolkit ist ein Java Framework zum Entwickeln von Web-Anwendungen, fÌr die keine Java Umgebung benötigt wird. |
|---|
| 283 | So widersprÃŒchlich das Konzept klingen mag, um so mehr ÃŒberzeugt es durch die vielen Vorteile. |
|---|
| 284 | |
|---|
| 285 | Das komplette Frontend wird zwar in Java entwickelt, |
|---|
| 286 | der GWT-Compiler konvertiert die Java Klassen aber dann zu browserinterpretierten JavaScript- und HTML Codes, |
|---|
| 287 | wie sie auf jedem Webspace und ohne marginale Systemvoraussetzungen verwendet werden können. |
|---|
| 288 | |
|---|
| 289 | Entwickler können ihre fÌr Java bevorzugte Entwicklungsumgebung benutzen. |
|---|
| 290 | Dabei brauchen sie sich nicht mit HTML, JavaScript und vor allem den ganzen Browser-Workarounds auseinander zu setzen. |
|---|
| 291 | Sie können GUIs programmieren, wie sie es bereits von SWING und AWT gewohnt sind, |
|---|
| 292 | ohne dabei auf vorhandene Build- und Testing-Tools verzichten zu mÃŒssen. |
|---|
| 293 | |
|---|
| 294 | |
|---|
| 295 | \subsection{Entwicklungszyklus} \label{sec_devcycle} |
|---|
| 296 | Das GWT arbeitet mit einer Standard-Verzeichnisstruktur, die entweder manuell oder unterstÃŒtzt durch die mitgelieferten Skripte erstellt werden kann. |
|---|
| 297 | FÃŒr Eclipse wird erst ein Projektverzeichnis zum Import in den Workspace erstellt und dann im zweiten Schritt die Anwendung angelegt. |
|---|
| 298 | |
|---|
| 299 | Die Schritte sollten in einem leeren, eigenen Verzeichnis durchgefÃŒhrt werden, da die Verzeichnisstruktur direkt im ausfÃŒhrenden Verzeichnis abgelegt wird. |
|---|
| 300 | \begin{lstlisting}[language=bash] |
|---|
| 301 | projectCreator -eclipse MeineErstesProjekt |
|---|
| 302 | applicationCreator -eclipse MeineErstesProjekt \ |
|---|
| 303 | com.gwt.client.MeineErsteAnwendung |
|---|
| 304 | \end{lstlisting} |
|---|
| 305 | |
|---|
| 306 | Geeignete Entwicklungsumgebungen können das Projektverzeichnis dann als normales Java-Projekt importieren und die eigentiche Programmierung kann beginnen. |
|---|
| 307 | Die Entwicklungsumgebung kann dabei mit Debugging-Möglichkeit, Refactoring-Tools und einer Unit-Testing-Integration unterstÌtzen. |
|---|
| 308 | Die Standard-Verzeichnisstruktur enthÀlt bereits ein einfaches 'Hello World', das im nÀchsten Kapitel zu einer Anwendung wachsen wird. |
|---|
| 309 | |
|---|
| 310 | WÀhrend des Testens wird öfter in den Hosted-Mode gewechselt, der einen Browser innerhalb einer Java VirtualMachine emuliert. |
|---|
| 311 | Die Anwendung kann hier live getestet und - entsprechende Break-Points vorausgesetzt - auch debuggt werden. |
|---|
| 312 | |
|---|
| 313 | Skriptsprachen-Programmierer mÃŒssen ihr 'Try and Run' Konzept nicht verwerfen, |
|---|
| 314 | da der Hosted-Mode-Browser sie weder durch umstÀndliche Entwicklungsumgebungs-Prozesse, |
|---|
| 315 | noch durch lange Kompilierzeiten ausbremst. |
|---|
| 316 | Ãnderungen im Java Quelltext Code werden 'Just in time' ÃŒbernommen. |
|---|
| 317 | |
|---|
| 318 | Wurde entschieden den fertig konfigurierten Tomcat-Server des Toolkits zur Prototype-Backend-Implementierung zu verwenden, |
|---|
| 319 | kann der komplette Anwendungszyklus debuggt werden. |
|---|
| 320 | Dadurch kann ein GUI Klick von vorne, bis hinten debuggt werden, wie es sonst mit AJAX nicht möglich gewesen wÀre. |
|---|
| 321 | |
|---|
| 322 | Wenn die Anwendung fertig erstellt ist und sie mit dem Code im Hosted-Mode zufrieden sind, |
|---|
| 323 | kann die Anwendung mit dem GWT-Compiler in JavaScript- und HTML-Code umgewandelt werden. |
|---|
| 324 | |
|---|
| 325 | Am Ende mÃŒssen die Dateien nur noch auf dem Webserver deployed werden. |
|---|
| 326 | |
|---|
| 327 | |
|---|
| 328 | \section{Technik des GWT} \label{sec:tec} |
|---|
| 329 | \subsection{Compiler} \label{sec_tec_compiler} |
|---|
| 330 | Der Compiler ist das HerzstÃŒck des GWT. Er verarbeitet den programmierten Java-Code und erstellt daraus einen neuen Code aus HTML und JavaScript - |
|---|
| 331 | so wie ein klassischer Java Compiler aus Java-Code einen Bytecode erstellt. |
|---|
| 332 | Der Unterschied ist, dass der erstellte Code ohne Java Runtime Umgebung und mit jedem aktuellen Browser ausgefÃŒhrt werden kann. |
|---|
| 333 | |
|---|
| 334 | Beim Compilieren wird entschieden welche Funktionen des GWT ÃŒberhaupt genutzt werden. |
|---|
| 335 | FÌr eine simple 'Hello World' werden also keine hundert Kilobytes an Bibliotheken mitgeliefert, sondern nur die Funktionen die tatsÀchlich benötigt werden. |
|---|
| 336 | |
|---|
| 337 | AuÃerdem wird der Quelltext komprimiert und komplett in JavaScript Dateien ausgelagert. |
|---|
| 338 | Dadurch kann die gesamte Anwendung vom Browser zwischengespeichert werden. |
|---|
| 339 | |
|---|
| 340 | FÃŒr jede Kombination aus Gebietsschema und Browsertyp wird eine einzelne JavaScript Datei erstellt. |
|---|
| 341 | Das erzeugt zwar mehr Daten auf dem Server (meist in einer GröÃenordnung von Kilobytes), |
|---|
| 342 | aber durch ein automatisches Bootstrap-Skript wird fÃŒr den Benutzer nur die Datei geladen, |
|---|
| 343 | die er tatsÀchlich benötigt. |
|---|
| 344 | |
|---|
| 345 | Wurde vor einen Framework-Einsatz vorher noch zwischen sauberem Code und Mengen an unbenutztem Framework-Code abgewÀgt, |
|---|
| 346 | kann mit dem GWT fast nur gespart werden. |
|---|
| 347 | |
|---|
| 348 | Die eigentliche HTML Datei sorgt nur fÃŒr die Einbindung des JavaScripts. |
|---|
| 349 | |
|---|
| 350 | |
|---|
| 351 | \subsection{ImageBundles} \label{sec_tec_gwt_imagebundles} |
|---|
| 352 | Ein weiterer Grundprozess des GWT ist es die Anzahl an HTTP-Anfragen so gering wie möglich zu halten. |
|---|
| 353 | Auch hierfÃŒr sorgt der Compiler. |
|---|
| 354 | In den meisten Websites sind es Bilder, die die meisten HTTP-Anfragen verursachen. |
|---|
| 355 | Daher haben sich die GWT Entwickler das Konzept der ImageBundles ÃŒberlegt. |
|---|
| 356 | Vielleicht wird der Vorteil anhand eines Beispiels bewusster: |
|---|
| 357 | |
|---|
| 358 | Typische WYSIWYG-Editoren bringen etwa 50 Buttons mit, die dem Anwender eine Office-Àhnliche OberflÀche vermitteln sollen. |
|---|
| 359 | Ein Browser wÃŒrde an dieser Stelle 50 Bilder-Tags im HTML-Quelltext sehen und alle 50 Bilder per HTTP-Anfrage laden. |
|---|
| 360 | Selbst wenn der Besucher die Seite bereits besucht hat und alle Bilder nur aus dem Zwischenspeicher des Browsers geladen werden mÃŒssen, |
|---|
| 361 | mÌssen 50 Verbindungen aufgebaut werden um nachzufragen, ob sich eines der Bilder geÀndert hat. |
|---|
| 362 | Das GWT macht nun aus den 50 Bildern nur ein einziges Bild, das die selbe Datenmenge mitbringt, nur einmalig geladen werden muss und trotzdem zwischengespeichert wird. |
|---|
| 363 | Eingebunden werden die Bilder weiterhin ÃŒber die 50 Bilder-Tags in ihrer OriginalgröÃe. |
|---|
| 364 | Per CSS werden Sie aber so verschoben, dass der Endanwender, bis auf den Geschwindigkeitsvorteil keinen Unterschied mehr merkt. |
|---|
| 365 | \begin{figure}[htp] |
|---|
| 366 | \centering |
|---|
| 367 | \includegraphics{img/imagesample.eps} |
|---|
| 368 | \caption{Hinter einem Bild verstecken sich in Wirklichkeit weitere.} |
|---|
| 369 | \label{fig:imagesample} |
|---|
| 370 | \end{figure} |
|---|
| 371 | |
|---|
| 372 | ImageBundles werden als Interface geschrieben. |
|---|
| 373 | Sollen die Bilder zentral verwaltet werden, werden sie per Ableiten zusammengefasst und der Compiler erstellt ein einziges Bild. |
|---|
| 374 | |
|---|
| 375 | |
|---|
| 376 | \subsection{Remote Procedure Call} \label{sec_tec_gwt_rpc} |
|---|
| 377 | Bisher wurden die optimierten Frontend-Prozesse des GWT vorgestellt. |
|---|
| 378 | FÃŒr die Anbindung an ein Backend nutzt das GWT 'Remote Procedure Calls' (kurz RPC), |
|---|
| 379 | ÃŒber die eine Model-View-Controller Architektur umgesetzt werden kann. |
|---|
| 380 | |
|---|
| 381 | FÃŒr die Prototyp-Entwicklung des Backends bringt das Google Web Toolkit einen Tomcat Server mit. |
|---|
| 382 | Das Toolkit fasst also alles benötige in einem Paket zusammen. |
|---|
| 383 | Falls kein Applikation-Server zur VerfÃŒgung steht, |
|---|
| 384 | stellt dies durch die Standardisierung von Remote Procedure Calls auch kein Problem dar und |
|---|
| 385 | es können andere Programmiersprachen wie PHP, Python oder C\# im Backend genutzt werden. |
|---|
| 386 | |
|---|
| 387 | Eine Besonderheit der RPC Implementierung des GWT, |
|---|
| 388 | die das Debuggen erleichtern, |
|---|
| 389 | sind die polymorphen Klassenhierarchien und das Durchreichen von Exceptions. |
|---|
| 390 | |
|---|
| 391 | Die Implementierung von RemoteProcedure Calls erstreckt sich ÃŒber mehrere Klassen und Interfaces. |
|---|
| 392 | Aufbauend auf dem 'Hello World' wird nun die Beispielanwendung der AJAX-Programmierung implementiert. |
|---|
| 393 | |
|---|
| 394 | Nach Konvention sollten dazu neben dem existierenden Client-Paket noch 'rpc' und 'server' Pakete angelegt werden. |
|---|
| 395 | Das rpc-Paket wird die folgende Klassenstruktur abbilden, die zustÀndig fÌr die Remote Procedure Calls sind. |
|---|
| 396 | Komplexe Datentypen sind erlaubt. |
|---|
| 397 | Daher wird das rpc-Paket auch die Klassen enthalten, die ÃŒber HTTP ausgetauscht werden. |
|---|
| 398 | |
|---|
| 399 | \begin{figure}[htp] |
|---|
| 400 | \centering |
|---|
| 401 | \includegraphics{img/uml.eps} |
|---|
| 402 | \caption{UML Modell der Beispielanwendung 'Status'} |
|---|
| 403 | \label{fig:rpc} |
|---|
| 404 | \end{figure} |
|---|
| 405 | |
|---|
| 406 | Status ist ein Interface das RemoteService erweitert und die tatsÀchliche Implementierung beschreibt. |
|---|
| 407 | Es enthÀlt die Java-Signaturen und wird spÀter vom Backend implementiert. |
|---|
| 408 | \begin{lstlisting}[language=java] |
|---|
| 409 | import com.google.gwt.user.client.rpc.*; |
|---|
| 410 | |
|---|
| 411 | public interface Status extends RemoteService { |
|---|
| 412 | Person[] getActive(); |
|---|
| 413 | void setStatus(Person name, boolean status); |
|---|
| 414 | } |
|---|
| 415 | \end{lstlisting} |
|---|
| 416 | |
|---|
| 417 | StatusAsync ist ein Interface das spÀter im GWT-Frontend-Code instanziiert wird. |
|---|
| 418 | Die Methoden haben keinen RÃŒckgabetyp, erhalten jedoch das parametrisierte AsyncCallback Objekt, das auf die readyState Ãnderungen reagiert. |
|---|
| 419 | \begin{lstlisting}[language=java] |
|---|
| 420 | import com.google.gwt.user.client.rpc.*; |
|---|
| 421 | |
|---|
| 422 | public interface StatusAsync { |
|---|
| 423 | void getActive(AsyncCallback callback); |
|---|
| 424 | void setStatus(Person name, boolean status, AsyncCallback callback); |
|---|
| 425 | } |
|---|
| 426 | \end{lstlisting} |
|---|
| 427 | |
|---|
| 428 | Der Status-Proxy beschreibt die Instantiierung im Frontend. |
|---|
| 429 | Er ist eine StatusAsync Instanz, wird aber vom GWT initialisiert. |
|---|
| 430 | Hier wird er die URL des RPC Moduls des GWT genutzt. |
|---|
| 431 | Alternativ kann man aber auch einen Pfad zur eigenen RPC Implementierung eintragen. |
|---|
| 432 | \begin{lstlisting}[language=java] |
|---|
| 433 | StatusAsync status = |
|---|
| 434 | (StatusAsync) GWT.create(Status.class); |
|---|
| 435 | ServiceDefTarget endpoint = (ServiceDefTarget) status; |
|---|
| 436 | String moduleRelativeURL = GWT.getModuleBaseURL() + "rpc"; |
|---|
| 437 | endpoint.setServiceEntryPoint(moduleRelativeURL); |
|---|
| 438 | |
|---|
| 439 | AsyncCallback callback = new AsyncCallback() { |
|---|
| 440 | public void onSuccess(Object result) { |
|---|
| 441 | Person[] list = (Person[]) result; |
|---|
| 442 | for(int i=0; i<list.length; i++) { |
|---|
| 443 | Window.alert(list[i].getName()); |
|---|
| 444 | } |
|---|
| 445 | } |
|---|
| 446 | |
|---|
| 447 | public void onFailure(Throwable caught) { |
|---|
| 448 | Window.alert(caught.getMessage()); |
|---|
| 449 | } |
|---|
| 450 | }; |
|---|
| 451 | \end{lstlisting} |
|---|
| 452 | |
|---|
| 453 | Wird die Anwendung mit dem mitgelieferten Tomcat-Server getestet, |
|---|
| 454 | muss das Backend das Status-Interface implementieren und der Pfad zum Servlet in der gwt-Modulkonfiguration eingefÃŒgt werden. |
|---|
| 455 | In der public/MeineErsteAnwendung.gwt.xml wird dazu ein neuer XML-Knoten unter '<module>' eingefÃŒgt. |
|---|
| 456 | \begin{lstlisting}[language=xml] |
|---|
| 457 | <servlet path="/rpc" class="com.gwt.server.StatusImpl"/> |
|---|
| 458 | \end{lstlisting} |
|---|
| 459 | |
|---|
| 460 | |
|---|
| 461 | |
|---|
| 462 | \section{Elemente des GWT} \label{sec:elements} |
|---|
| 463 | Neben den behandelten Performance-Vorteilen, durch die erst eine Reaktionszeit Àhnlich der von Desktop- möglich wurde, |
|---|
| 464 | bringt das GWT Basiselemente fÌr die GUI-Programmierung und Konzepte um die Usability von Web-Anwendungen zu erhöhen mit. |
|---|
| 465 | |
|---|
| 466 | \subsection{Panels} \label{sec:gwt_panels} |
|---|
| 467 | Wer grafische OberflÀchen bereits mit Java erstellt hat, kennt das Layout-Manager-Konzept von Swing und AWT. |
|---|
| 468 | Abgesehen von ein paar Besonderheiten von HTML-Elementen wird das Konzept beliebig kombinierbarer Panels auch im GWT angewandt. |
|---|
| 469 | |
|---|
| 470 | Panels sind Container um andere Elemente aufzunehmen. |
|---|
| 471 | Es gibt verschiedene Panels fÃŒr Layout und Content. |
|---|
| 472 | Ein typisches Beispiel fÃŒr ein Layout-Panel ist das DockPanel. |
|---|
| 473 | Es kann als Grundlayout verwendet werden und Àhnelt dem BorderLayout von AWT. |
|---|
| 474 | |
|---|
| 475 | \begin{figure}[htp] |
|---|
| 476 | \centering |
|---|
| 477 | \includegraphics{img/panel.eps} |
|---|
| 478 | \end{figure} |
|---|
| 479 | |
|---|
| 480 | \subsection{Widgets} \label{sec:gwt_widgets} |
|---|
| 481 | Hinter Widgets versteckt sich der deutsche Begriff 'grafisches Bedienelement'. |
|---|
| 482 | Das GWT versteht sich auf Webanwendungen, und so wird es auch die gewohnten Browser-Elemente aus Usability-Aspekten behalten. |
|---|
| 483 | Neben den fÃŒr HTML Entwickler bekannten Elementen wie Eingabefeld, Button und Auswahlbox bringt das GWT aber noch weitere, aus Desktop-Applikationen bekannte Widgets mit. |
|---|
| 484 | Dazu zÀhlen der Tree fÌr eine Baumdarstellung eines Verzeichnisbaums, |
|---|
| 485 | die MenuBar fÃŒr eine MenÃŒleiste, |
|---|
| 486 | die TabBar fÃŒr das Container-Wechsel ÃŒber eine Reiterleiste, |
|---|
| 487 | das StackPanel oder die RichTextArea fÃŒr WYSIWYG-Editoren. |
|---|
| 488 | |
|---|
| 489 | AuÃerdem gibt es neben Kalender- und Zeichenwidgets auch 'Drag \& Drop' Elemente aus der aktiven OpenSource Community hinter dem GWT. |
|---|
| 490 | |
|---|
| 491 | |
|---|
| 492 | \subsection{Implementierung der Browser-History} \label{sec:usability_history} |
|---|
| 493 | Ein typischer Kritikpunkt und Stolperstein bei Web-Anwendungen ist die Browserhistorie, |
|---|
| 494 | die entweder nicht funktioniert oder von der kontextuell abgeraten wird. |
|---|
| 495 | |
|---|
| 496 | Das asynchrone Konzept von AJAX macht ein Neuladen der Website unnötig, wodurch es fÌr den Browser keinen Anlass gibt einen History-Eintrag zu erstellen. |
|---|
| 497 | Dadurch, dass sich fÌr den Benutzer aber Inhalte Àndern, nimmt er an, dass er den 'ZurÌck'-Button nutzen kann. |
|---|
| 498 | |
|---|
| 499 | Es gibt verschiedene Workarounds fÃŒr dieses Problem, die sich zu Quasi-Entwurfsmustern entwickelt haben, aber nicht einfach zu implementieren sind. |
|---|
| 500 | |
|---|
| 501 | Das GWT hat diese Implementierung bereits vorgenommen und kann vom Programmierer abstrakt genutzt werden. |
|---|
| 502 | Hier zeigt sich wieder der Vorteil eines Frameworks: |
|---|
| 503 | Gibt es in der Zukunft eine bessere Technik braucht der Entwickler nur die Google JAR auszutauschen. |
|---|
| 504 | |
|---|
| 505 | Die Implementierung funktioniert mit der Schnittstelle HistoryListener, die onHistoryChanged(String token) implementiert. |
|---|
| 506 | Das Token lÀsst sich wie ein Dateiname behandeln. |
|---|
| 507 | Dadurch kann jede GUI-Aktion durch ein Token abgebildet werden. |
|---|
| 508 | |
|---|
| 509 | |
|---|
| 510 | \subsection{Internationalisierung} \label{sec:tec_internationalization} |
|---|
| 511 | Das GWT unterstÌtzt den Entwickler mit verschiedenen Möglichkeiten um sowohl die Sprache, |
|---|
| 512 | als auch unterschiedliche Zahlen- oder Datumsformaten zu internationalisieren. |
|---|
| 513 | |
|---|
| 514 | Die bevorzugte Art der Implementierung ist die statische bei der die Sprachvariablen schon zur Compilierzeit befÃŒllt werden. |
|---|
| 515 | WÀhlt man stattdessen die dynamische Internationalisierung werden dem Benutzer alle Dateien mitgeliefert. |
|---|
| 516 | |
|---|
| 517 | Bei der statischen Variante wird ein Interface mit je einer Methode pro Eigenschaft erstellt. |
|---|
| 518 | \begin{lstlisting}[language=java] |
|---|
| 519 | public interface MyLang extends Constants { |
|---|
| 520 | String helloWorld(); |
|---|
| 521 | String sliceOfSpam(); |
|---|
| 522 | } |
|---|
| 523 | \end{lstlisting} |
|---|
| 524 | |
|---|
| 525 | Eine Instanz dieser Schnittstelle greift dann auf eine Property-Datei namens MyLang.properties zu. |
|---|
| 526 | Wurde eine weitere Sprache (z.B. 'en') ÃŒber die globale Konfigurationsdatei gwt.xml bekannt gemacht, |
|---|
| 527 | wird auch fÃŒr die Sprache 'en' und die Datei MyLang\_en.properties ein JavaScript kompiliert. |
|---|
| 528 | |
|---|
| 529 | Die Sprache wird je nach Browserkonfiguration automatisch gewÀhlt. |
|---|
| 530 | Mit dem GET-Parameter 'locale' lÀsst sie sich aber auch erzwingen. |
|---|
| 531 | |
|---|
| 532 | |
|---|
| 533 | \subsection{Eigene Skripte} \label{sec:scripting} |
|---|
| 534 | Es ist gÀngige Praxis neue Widgets zu bauen indem vorhandene Widgets und Panels des GWT kombiniert werden. |
|---|
| 535 | Das erleichtert die Pflege bei Versionsupdates und verhindert, dass der Programmierer wieder auf JavaScript Ebene herunter muss um Ãnderungen einzupflegen. |
|---|
| 536 | |
|---|
| 537 | Falls aber doch individuelle Effekte, fertige Bildergallerien oder Ãhnliches benötigt werden, |
|---|
| 538 | bietet das GWT Ìber JSNI die Möglichkeit normalen JavaScript Code einzubinden. |
|---|
| 539 | |
|---|
| 540 | Soll eine solche Methode geschrieben werden, wird das SchlÃŒsselwort 'native' und eine spezielle Kommentarsyntax verwendet. |
|---|
| 541 | Wie im folgenden Beispiel zu sehen, ist selbst ein Zugriff auf Attribute und Methoden des GWT möglich. |
|---|
| 542 | |
|---|
| 543 | Der Zugriff auf 'window' und 'document' ist gekapselt und nur Ìber die Variablen \$wnd und \$doc möglich. |
|---|
| 544 | |
|---|
| 545 | \begin{lstlisting}[language=java] |
|---|
| 546 | public class JSNIExample { |
|---|
| 547 | void foo(String s) { |
|---|
| 548 | private FlowPanel fp = new FlowPanel(); |
|---|
| 549 | private Button b1 = new Button(s+" 1"); |
|---|
| 550 | private Button b2 = new Button(s+" 2"); |
|---|
| 551 | } |
|---|
| 552 | |
|---|
| 553 | public native void foo(JSNIExample x, String s) /*-{ |
|---|
| 554 | $wnd.alert(msg); |
|---|
| 555 | this.@book.JSNIExample::foo(Ljava/lang/String;)(s); |
|---|
| 556 | }-*/; |
|---|
| 557 | } |
|---|
| 558 | \end{lstlisting} |
|---|
| 559 | |
|---|
| 560 | |
|---|
| 561 | \newpage |
|---|
| 562 | |
|---|
| 563 | \begin{thebibliography}{99} |
|---|
| 564 | \bibitem{gwtinaction} |
|---|
| 565 | Robert Hanson \& Adam Tacy: |
|---|
| 566 | {\em GWT im Einsatz}. |
|---|
| 567 | Hanser Verlag, |
|---|
| 568 | 2007, ISBN 3446412417 |
|---|
| 569 | \bibitem{entwicklerpress} Ralph Steyer: |
|---|
| 570 | {\em Das Google Web Toolkit. schnell + kompakt}. |
|---|
| 571 | Entwickler.Press, |
|---|
| 572 | 2007, ISBN 3939084379 |
|---|
| 573 | \bibitem{dewsbury} Ryan Dewsbury: |
|---|
| 574 | {\em Das Google Web Toolkit. schnell + kompakt}. |
|---|
| 575 | Addison-Wesley Longman, Amsterdam |
|---|
| 576 | 2007, 0321501969 |
|---|
| 577 | \bibitem{official} Google: |
|---|
| 578 | {\em Offizielle Dokumentation}. |
|---|
| 579 | http://code.google.com/webtoolkit/ |
|---|
| 580 | \end{thebibliography} |
|---|
| 581 | |
|---|
| 582 | \newpage |
|---|
| 583 | |
|---|
| 584 | \end{document} |
|---|