Problem
Der Benutzer startet einen Request der mehrere Sekunden dauert. Während dieser Zeit soll dem Benutzer eine Progress Bar angezeigt werden, die ihm den Fortschritt in Echtzeit anzeigt.Lösung
p:progressBar kann mit PrimePush in Echtzeit aktualisiert werden.
Dieses Tutorial zeigt Ihnen, wie Sie p:progressBar zusammen mit PrimePush kombinieren können, um dem Benutzer den Fortschritt in Echtzeit anzuzeigen. Zusätzlich wird p:blockUI verwendet, um alle Eingaben des Benutzers zu blockieren.
![]() |
Abb. 1: Realtime Progress Bar |
SVN
Das fertige Projekt kann per SVN von http://xpert-ivy-hacker-source-code.googlecode.com/svn/trunk/PrimePush in den Xpert.ivy Designer importiert werden.
Code
Hinweis: Sie benötigen den Preview Release 'Rothorn' von Xpert.ivy und müssen PrimePush installiert haben.
Starten Sie die Engine und probieren Sie das Realtime ProgressBar Beispiel aus. Drück man auf Start, so wird eine p:progressBar angezeigt, die in Echtzeit von der Logic aktualisiert wird.
Schauen wir uns zuerst den Code der View an.
Code Snippet 1: View Code
Auf den Zeilen 15 - 18 wird eine p:blockUI definiert, die eine p:progressBar und ein Label anzeigt sobald der p:commandButton gedrückt wird. Wichtig ist, dass widgetVar definiert wird, damit wir in der handleProgress JavaScript Funktion auf die p:progressBar Komponente zugreifen können und den Prozentsatz setzen können (Zeile 5).
handleProgress nimmt einen JSON-String entgegen, der per eval in ein JavaScript Objekt umgewandelt wird (Zeile 4). Dieses Objekt enthält die Attribute progress und msg. progress ist der Fortschritt in Prozent und msg das Label das angezeigt werden soll.
Doch von wo wird handleProgress aufgerufen? Die Antwort ist auf Zeile 20 zu finden. Diese definiert per p:socket eine Verbindung zum Server und erlaubt uns, Nachrichten vom Server direkt an den Client zu senden. Die Verbindung zum Server ist im Idealfall ein Websocket. Falls Websockets nicht zur Verfügung stehen, wird eine Comet Verbindung aufgebaut. Dies braucht Sie aber nicht zu interessieren, da PrimePush automatisch die best mögliche Verbindung verwendet.
onMessage von p:socket ist die JavaScript Funktion die aufgerufen werden soll, wenn eine neue Nachricht vom Server auf den Client gepusht wurde.
Das channel Attribut von p:socket ist der Kanal worauf auf neue Nachrichten gehört wird. In diesem Fall ist dies der Wert, der in dem Datenklassen-Attribut channel des Html User Dialog steht. Er wird dynamisch beim Start generiert, da jede Instanz der View einen eigenen Kanal benötigt, damit die Updates nur bei dem Benutzer zu sehen sind, der den p:commandButton gedrückt hat.
Öffnen Sie nun die Logic von RealtimeProgressBar. Beim starten des Html User Dialog wird zuerst der Kanal per in.channel = "/realtime/" + java.util.UUID.randomUUID().toString(); generiert. Dies stellt sicher, dass jede Instanz der View einen eigenen Kanal hat.
Die Script-Steps die bei startLongRunningProcess durchlaufen werden senden alle eine Nachricht an die View. Dies wird per PushContextFactory.getDefault().getPushContext().push(in.channel, "{ 'progress' : 10, 'msg' : 'Daten aufbereiten'}"); gemacht. Der zweite Parameter ist der JSON-String der von handleProgress per eval in ein JavaScript Objekt umgewandelt wird.
Starten Sie die Engine und probieren Sie das Realtime ProgressBar Beispiel aus. Drück man auf Start, so wird eine p:progressBar angezeigt, die in Echtzeit von der Logic aktualisiert wird.
Schauen wir uns zuerst den Code der View an.
Code Snippet 1: View Code
Auf den Zeilen 15 - 18 wird eine p:blockUI definiert, die eine p:progressBar und ein Label anzeigt sobald der p:commandButton gedrückt wird. Wichtig ist, dass widgetVar definiert wird, damit wir in der handleProgress JavaScript Funktion auf die p:progressBar Komponente zugreifen können und den Prozentsatz setzen können (Zeile 5).
handleProgress nimmt einen JSON-String entgegen, der per eval in ein JavaScript Objekt umgewandelt wird (Zeile 4). Dieses Objekt enthält die Attribute progress und msg. progress ist der Fortschritt in Prozent und msg das Label das angezeigt werden soll.
Doch von wo wird handleProgress aufgerufen? Die Antwort ist auf Zeile 20 zu finden. Diese definiert per p:socket eine Verbindung zum Server und erlaubt uns, Nachrichten vom Server direkt an den Client zu senden. Die Verbindung zum Server ist im Idealfall ein Websocket. Falls Websockets nicht zur Verfügung stehen, wird eine Comet Verbindung aufgebaut. Dies braucht Sie aber nicht zu interessieren, da PrimePush automatisch die best mögliche Verbindung verwendet.
onMessage von p:socket ist die JavaScript Funktion die aufgerufen werden soll, wenn eine neue Nachricht vom Server auf den Client gepusht wurde.
Das channel Attribut von p:socket ist der Kanal worauf auf neue Nachrichten gehört wird. In diesem Fall ist dies der Wert, der in dem Datenklassen-Attribut channel des Html User Dialog steht. Er wird dynamisch beim Start generiert, da jede Instanz der View einen eigenen Kanal benötigt, damit die Updates nur bei dem Benutzer zu sehen sind, der den p:commandButton gedrückt hat.
Öffnen Sie nun die Logic von RealtimeProgressBar. Beim starten des Html User Dialog wird zuerst der Kanal per in.channel = "/realtime/" + java.util.UUID.randomUUID().toString(); generiert. Dies stellt sicher, dass jede Instanz der View einen eigenen Kanal hat.
Die Script-Steps die bei startLongRunningProcess durchlaufen werden senden alle eine Nachricht an die View. Dies wird per PushContextFactory.getDefault().getPushContext().push(in.channel, "{ 'progress' : 10, 'msg' : 'Daten aufbereiten'}"); gemacht. Der zweite Parameter ist der JSON-String der von handleProgress per eval in ein JavaScript Objekt umgewandelt wird.
Weiterführende Ressourcen
Über den Author: Heinrich Spreiter ist der Gründer von xpertivyhacker.ch. Kontaktieren Sie ihn auf Xing und Twitter