16. März 2015 | 2 min lesezeit

Request Optimierung in JSF Teil 2

Seit JSF 2.0 bietet das Framework mit dem < f:ajax >-Tag eine einfache und flexible Möglichkeit, Formularfelder und Buttons zu ajaxifizieren. Leider werden in der aktuellen Implementierung aber auf Grund eines Designfehlers oftmals zu viele Daten vom Browser an den Server übermittelt…

Im vorherigen Blog-Post wurde über die Probleme mit JSF Partial Requests berichtet. Diese übertragen immer alle Formulardaten, auch wenn im execute-Teil des <f:ajax/>-Tags eine explizite Einschränkung auf bestimmte Elemente erfolgt ist. Da mit einer Lösung dieses Problems frühestens in JSF 2.3 zu rechnen ist, wird in diesem Blog-Post ein möglicher Lösungsansatz vorgestellt.

Die Formulardaten eines Ajax-POST-Requests werden, ähnlich wie man es von einem GET-Request aus der Browserzeile kennt, anhand eines Query-Strings versendet. Dieser sieht beispielsweise wie folgt aus:

formOne=formOne&formOne%3At1=SOMEVALUE&formOne%3At2=
OTHERVALUE&formOne%3At3=ANOTHEROTHERVALUE&javax.faces.ViewState=…

Die in JSF enthaltene JavaScript-API ist für die Erzeugung dieses Query-Strings zuständig. In der aktuellen Referenzimplementierung werden die zu übermittelnden Werte nicht auf Basis der in „javax.faces.partial.execute“ definierten IDs gefiltert, sondern pauschal das gesamte Formular serialisiert. Für die Serialisierung des Formulars wird in einer for-Schleife über alle darin enthaltenen Elemente iteriert (Listing 1). Dabei werden nur die Formularelementtypen berücksichtigt, die einen Namen haben und als „successfull controls“ feststehen. Letzteres gilt für alle Elemente, die nicht deaktiviert („disabled“) sind, oder im Fall von Check- und Radioboxen einen aktiven Status („on“) haben. Button- und Submitcontrols sowie Elemente ohne direkte Wertebindung werden bei der Serialisierung ignoriert. Die eigentliche Erstellung des Query-Strings findet in der Funktion addField(name, value) statt. Dort werden die Namen- und Wertepaare in das Query-Parameter-Array „qString“ eingefügt, welches am Ende der Methode als String zurückgegeben wird (return qString.join(„“)).

Listing 1:

Um nur noch die gewünschten Elemente an den Server zu übermitteln, muss in der erwähnten for-Schleife ein zusätzlicher Filtermechanismus implementiert werden. Dieser gleicht die IDs (bzw. Namen) aller Formularelemente mit den im execute-String definierten IDs ab. So wird ein jeweiliger Wert nur dann als Query-Parameter gesetzt, wenn dieser auch wirklich auf dem Server verarbeitet werden soll. Listing 2 zeigt die Erweiterung der addField-Funktion, in der nun vor dem Hinzufügen eines Wertepaares zum Query-String überprüft wird, ob dieses überhaupt übertragen werden muss.

Listing 2:

Das beschriebene Problem fällt bei kleinen Formularen nicht ins Gewicht. Da bei JSF aber jeder Ajax-Request ein POST-Request ist und deshalb alle serverseitig gebundenen Komponenten von einer Form umgeben sein müssen, entstehen in der Regel sehr schnell Formulare mit einer Vielzahl von Komponenten. Ajax-lastige JSF-Anwendungen übertragen so oftmals mehrere 100KB zusätzliche Daten an den Server. Dies kann insbesondere bei mobilen Verbindungen zu einem spürbaren Performance-Killer werden. Mit dem hier gezeigten Lösungsansatz lässt sich eine deutliche (vgl. Listing 3) Reduzierung der zu sendenden Datenmengen erreichen.

Listing 3:

Im letzten Teil dieser Blog-Reihe wird die konkrete Umsetzung dieses Lösungsansatzes vorgestellt. Der Sourcecode zu diesem Blogeintrag  befindet sich unter https://github.com/dskgry/lilly


Keine Kommentare

Kontakt

OPEN KNOWLEDGE GmbH

Standort Oldenburg:
Poststraße 1, 26122 Oldenburg

Standort Essen:
II. Hagen 7, 45127 Essen