Unsere Datenschutzrichtlinie wird in Kürze aktualisiert. Bitte sehen Sie sich die Vorschau an.

Java EE 7: Web Services

Implementieren eines Java-Endpoints für einen WebSocket

Testen Sie unsere 2015 Kurse

10 Tage kostenlos!

Jetzt testen Alle Abonnements anzeigen
WebSockets können nicht nur von Webseiten, sondern auch von Java-Clients angesprochen werden. Hier sehen Sie, wie dabei vorzugehen ist und wie eine ClientEndpoint-Implementierung aussehen kann.

Transkript

Auch wenn WebSockets üblicherweise mit Webseiten und JavaScript assoziiert sind, ist es doch auch möglich, einen WebSockets Client mit Java zu implementieren. Genau das werden wir in diesem Video machen. Wir werden klären, was wir dafür benötigen, und wir werden einen Client für einen Endpoint implementieren. Wenn wir einen Client mit Java implementieren wollen, haben wir eigentlich gar nicht so viel Arbeit, denn die WebSocket API kennt auch eine Client-Implementierung und eine Implementierung ist letztlich nichts anderes, als eine Klasse, die mit der @ClientEndpoint-Annotation versehen ist. In dieser Klasse kann es dann diverse Methoden geben. Diese Methoden verhalten sich analog zu dem Server Endpoint, das heißt, sie sind ganz normale Methoden, die wir definieren und sie sind dann annotiert. Eine Methode mit der Annotation @OnOpen wird zum Beispiel aufgerufen, wenn eine Verbindung geöffnet wird. Eine Methode mit der Annotation @OnMessage wird aufgerufen, sobald eine Nachricht eintrifft. Eine Methode mit der Annotation @OnError wird aufgerufen, falls ein Verbindungsfehler oder ein anderer Fehler aufgetreten ist. Eine Methode mit der Annotation @OnClose wird aufgerufen, wenn die Verbindung geschlossen wird. Die einzige wirkliche Aufgabe, die der Client hat, ist diese Methoden zu implementieren und seine eigene lokale UserSession-Instanz vorzuhalten, die er beim Aufbau der Verbindung erhält. Auf Ebene dieser UserSession-Instanz wird dann die weitere Verarbeitung vorgenommen werden. Sehen wir uns nun einmal an, wie wir dies umsetzen können. Bevor wir uns der eigentlichen Implementierung zuwenden können, benötigen wir allerdings eine Referenzimplementierung der Java API for WebSockets. Diese Referenzimplementierung gibt es in Form des Tyrus Projekts unter https://tyrus. java.net und auf Ebene der Homepage von diesem Tyrus Projekt können Sie dann in den Bereich Download wechseln, dort sehen Sie die Dependencies aufgelistet und hier finden Sie alles, was Sie benötigen, und das ganze entweder mit Maven zu machen oder wenn Sie das ganz alleine machen wollen, dann können Sie hier über den Link Tyrus Standalone Client an die Stelle kommen, wo Sie die benötigten Artefakte für Maven sehen können oder den Standalone Client als JAR-Archiv herunterladen können. Nachdem sie das JAR-Archiv heruntergeladen haben, können Sie es Ihrer Applikation hinzufügen, ansonsten, wenn Sie es per Maven machen wollen, fügen Sie die entsprechende Dependency Ihrem Projekt hinzu. Ich habe diesen Standalone Client nun bereits heruntergeladen und auf mein Projekt gezogen und dort reinkopiert und nun kann ich den entsprechenden Build Path anpassen. Und zwar füge ich das JAR-Archiv, was sich hier in meinem Projekt befindet, dem Build Path hinzu. Wir befinden uns hier übrigens in einer ganz normalen Java-Applikation. Das heißt, dieses Projekt WebSocketsClient ist ein ganz normales Java-Projekt, indem ich aber schon mal ein, zwei Sachen vorbereitet habe. Und zwar gibt es hier eine Konsolenapplikation, die ist auch schon mal grundsätzlich vorbereitet und hier werden Eingaben entgegengenommen, die jemand über die Konsole eingibt und dann an den Endpoint geschickt, also an den WebSocket geschickt und wir haben hier schon Platzhalter drin, damit wir wissen, dass wir einen Endpoint definieren müssen und eine neue Nachricht dann auch entgegennehmen und ausgeben müssen. Und es gibt eine Klasse mit dem Namen ChatClientEndpoint, die ist auch schon vorbereitet. Das ist eine ganz normale klasse und hier in diese Klasse werden wir nun die Logik implementieren, die wir benötigen, um den ClientEndpoint zu implementieren. Vorher allerdings möchte ich Ihre Aufmerksamkeit noch auf das Interface Dieses Interface essageHandler kann von Clients, also von aufrufenden Komponenten genutzt werden, um die Nachrichten, die vom WebSocket kommen, dann entgegenzunehmen. Das heißt, die aufrufende Komponente implementiert das und kann dann ihrerseits informiert werden. Sie bindet sich dann über die Methode addMessageHandler an diesen ChatClientEndpoint und wird dann benachrichtigt. Ebenfalls schon vorbereitet ist eine Methode sendMessage, mit der wir eine Nachricht verschicken können. Genug der Vorrede, lassen Sie uns nun zur Implementierung dieses ChatClientEndpoints kommen. Im ersten Schritt werde ich nun diese Klasse mit der Annotation @ClientEndpoint versehen und sie somit als einen Endpoint auf Client Seite markieren. Ich füge nun noch eine private Member Variable vom Typ Session hinzu -aus dem javax.websocket Package muss das bitte die Session sein- und die nenne ich userSession und die ist Initiale null. Nun definiere ich die Methoden, die von diesem ClientEndpoint bereitgestellt werden, wenn Nachrichten reinkommen, wenn eine Verbindung aufgebaut wird oder wenn sie geschlossen wird. Zunächst widmen wir uns der Methode, die aufgerufen wird, wenn eine Verbindung aufgebaut wird. Das ist die Methode onOpen, der Name ist frei wählbar, ich entscheide mich aber für diesen eher klassischen Namen und hier bekomme ich vom WebSocket Client oder vom WebSocket Container meine lokale Session rein übergeben und zwar in der Variablen userSession. Was ich jetzt hier mache, ist, ich binde die Instanzvariable userSession an die hier übergebene Variable, damit habe ich die vorgehalten und kann sie dann im weiteren Verlauf benutzen. Ich annotiere diese Methode mit @OnOpen. Die nächste Methode ist die Methode onClose. Diese Methode wird aufgerufen, wenn die Verbindung getrennt wird. Sie erwartet zwei Parameter, nämlich einmal die Session, die gerade getrennt worden ist und einen zweiten Parameter vom Typ CloseReason, der mir Auskunft darüber gibt, warum die Verbindung getrennt worden ist. Wir ignorieren hier diesen zweiten Parameter und löschen einfach nur unsere Session. Wir annotieren diese Methode mit @OnClose. Nun implementiere ich die Methode onMessage, die wird aufgerufen, wenn eine Nachricht eintrifft. Ihr Parameter ist einfach nur eine Zeichenkette. Sollte mir eine Instanz des hier unten definierten messageHandler zugewiesen sein, dann rufe ich diese Instanz auf, übergebe ihr die Nachricht und verlagere damit die Kontrolle auf die aufrufende Komponente, die dann ihrerseits eine entsprechende Implementierung bereitstellen wird. Und zwar mache ich das über die Methode handleMessage und gebe dann hier die Nachricht weiter. Ich annotiere diese Methode mit @OnMessage. Nachdem ich nun eine Referenz auf die userSession bereits besitze, kann ich diese userSession in der Methode sendMessage auch benutzen, um eine Nachricht an den Endpoint zu senden. Das mache ich, indem ich auf ihrer Ebene, also auf der Ebene der userSession-Instanz, die ich halte, die Methode getAsyncRemote aufrufe. Da bekomme ich ein Remote Handle, mit dem kann ich asynchron arbeiten, das heißt, es ist nicht blockierend, was ich jetzt mache. Und da gibt es die Methode sendText und da kann ich die übergebene Nachricht mit versenden. Dann haben wir eigentlich schon fast alles erledigt, das einzige, was wir noch implementieren müssen, ist das eigentliche Aufbauen der Verbindung. Das mache ich im Constructor. Das muss ich nicht im Construktor machen, aber ich mache es der Bequemlichkeit halber jedoch im Construktor. Man kann dafür natürlich noch eine extra Methode bereitstellen. Hier erwarte ich die Angabe einer URI-Instanz, indem ich die Adresse des anzusprechenden WebSockets. Ich erzeuge jetzt hier eine WebSocketContainer-Instanz und zwar hole ich mir die über die statische Methode getWebSocketContainer, der Container Provider Klasse. Mit Hilfe dieses Containers verbinde ich mich mit dem Server. Der erste Parameter ist die aufzurufende Implementierung von ClientEndpoint, die benutzt wird, wenn Nachrichten eintreten, wenn die Verbindung aufgebaut wird und so weiter und so fort und der zweite Parameter ist die Adresse. Es kann hierbei so einer Exception kommen, deswegen behandle ich das in einem try/catch Block. Damit ist diese ClientEndpoint-Implementierung fertig und kann genutzt werden. In meiner Konsolenapplikation möchte ich diesen Endpoint nun benutzen. Für diesen Zweck wechsle ich dorthin zurück und kann mich nun daranmachen, die verschiedenen Aufgaben, die hier noch drinstehen, umzusetzen. Zunächst einmal werden wir nun eine Instanz dieses ClientEndpoints definieren und dabei übergeben wir die Adresse, die aufzurufen ist. Diese Adresse übergeben wir in Form einer URI-Instanz und die zeigt auf ws:// -ws als Protokoll steht für WebServices- jetzt kommt der Name der Maschine und eventuelle Portangaben und nun kommt der Pfad zur Applikation, in der der Endpoint -in unserem Falle heißt dieser Endpoint Chat, bereitgestellt ist. Es kann hier zu einer Exception kommen, deswegen füge ich die entsprechende Froze Deklaration der Methodensignatur hinzu. Nun muss ich noch einen messageHandler definieren, für neue Nachrichten, die reinkommen. Das mache ich hier gleich inline, indem ich dieses Interface anonym implementiere und hier mache ich nichts anderes, als die einkommende Nachricht wieder auszugeben. Diesen messageHandler übergebe ich nun ein die Methode addMessageHandler des gerade eben erzeugten ChatClientEndpoints und bin nun fast fertig. Das letzte, was ich noch benötige, ist die hier noch vorgesehene Logik, um eine Nachricht zu senden. Das Ganze geschieht ja hier innerhalb dieser while-Schleife und solange hier eine neue Nachricht eingegeben wird und Enter gedrückt wird, wird die dann an den Server gesendet. Das machen wir durch Aufruf auf client.sendMessage und hier übergeben wir die entgegengenommene Nachricht. Das war es dann, damit ist die Implementierung auf Ebene der Konsolenapplikation abgeschlossen. Nun starte ich zunächst die Webapplikation. Das kann dann einige Sekunden dauern, bis diese Webapplikation läuft und ganz interessant: Ich bekomme hier eine Nachricht, dass wir einen WebSocket bereitgestellt haben, nämlich hier, dass der entsprechende WebSocket definiert worden ist. Jetzt kann ich meinen Client starten und wie Sie gesehen haben, gab es eine Fehlermeldung, weil die Adresse nicht korrekt war. So, wenn die Adresse nun korrekt ist, wird das Ganze auch funktionieren und ich kann in der Konsole eine Nachricht eingeben. Ich bekomme dann die entsprechende Rückgabe. Sie sehen, das funktioniert einwandfrei. In diesem Video haben wir uns mit der Implementierung eines ClientEndpoints für einen WebSocket befasst. Wir haben geklärt, wie wir solch einen ClientEndpoint aufbauen können, wir haben über die entsprechenden Methoden gesprochen und wir haben einen Konsolenclient geschrieben, der mit diesem Endpoint auf Serverseite interagieren kann.

Java EE 7: Web Services

Steigen Sie ein in die Java-Enterprise-Welt und lernen Sie, wie Nachrichten ausgetauscht und Dienste definiert werden.

5 Std. 13 min (30 Videos)
Derzeit sind keine Feedbacks vorhanden...
 

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!