-
Notifications
You must be signed in to change notification settings - Fork 36
/
getting-started.xml
232 lines (216 loc) · 12 KB
/
getting-started.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
<?xml version="1.0"?>
<!--
Copyright (c) 2013, 2017 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary
Licenses when the conditions for such availability set forth in the
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
version 2 with the GNU Classpath Exception, which is available at
https://www.gnu.org/software/classpath/license.html.
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
-->
<!DOCTYPE chapter [<!ENTITY % ents SYSTEM "tyrus.ent" > %ents; ]>
<chapter xmlns="http://docbook.org/ns/docbook"
version="5.0"
xml:lang="en"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd
http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd"
xml:id="getting-started">
<title>Getting Started</title>
<para>
This chapter provides a quick introduction on how to get started building
WebSocket services using &ja4w; and Tyrus. The example described here presents how to implement
simple websocket service as JavaEE web application that can be deployed on any servlet container
supporting Servlet 3.1 and higher. It also discusses starting Tyrus in standalone mode.
</para>
<section xml:id="getting-started-wsapi-artifact">
<title>WebSocket Services Using &ja4w;</title>
<para>
First, to use the &ja4w; in your project you need to depend on the following artifact:
<programlisting language="xml" linenumbering="unnumbered"><dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<version>&apiversion;</version>
</dependency>
</programlisting>
</para>
<section>
<title>Creating Annotated Server Endpoint</title>
<para>
In this section we will create a simple server side websocket endpoint which will echo the received
message back to the sender. We will deploy this endpoint on the container.
</para>
<para>
In &ja4w; and Tyrus, there are two basic approaches how to create an endpoint - either annotated endpoint,
or programmatic endpoint.
By annotated endpoint we mean endpoint constructed by using annotations (<code>jakarta.websocket.server.ServerEndpoint</code>
for server endpoint and <code>jakarta.websocket.ClientEndpoint</code> for client endpoint), like in
<link linkend="websocket-annotated-echo-endpoint">"Annotated Echo Endpoint"</link>.
<example xml:id="websocket-annotated-echo-endpoint">
<title>Annotated Echo Endpoint</title>
<programlisting language="java" linenumbering="numbered">@ServerEndpoint(value = "/echo")
public class EchoEndpointAnnotated {
@OnMessage
public String onMessage(String message, Session session) {
return message;
}
}
</programlisting>
</example>
</para>
<para>
The functionality of the <code>EchoEndpointAnnotated</code> is fairly simple - to send the received message
back to the sender. To turn a POJO (Plain Old Java Object) to WebSocket server endpoint, the annotation
<code>@ServerEndpoint(value = "/echo")</code> needs to be put on the POJO - see line 1. The URI path of the endpoint
is <code>"/echo"</code>. The annotation <code>@OnMessage</code> - line 3 on the method <code>public String
onMessage(String message, Session session)</code> indicates that this method
will be called whenever text message is received. On line 5 in this method the message is sent back to
the user by returning it from the message.
</para>
<para>
The application containing only the <code>EchoEndpointAnnotated</code> class can be deployed to the container.
</para>
</section>
<section>
<title>Client Endpoint</title>
<para>
Let's create the client part of the application. The client part may be written in JavaScript or any
other technology supporting WebSockets. We will use &ja4w; and Tyrus to demonstrate how to develop
programmatic client endpoint.
The following code is used as a client part to communicate with the <code>EchoEndpoint</code> deployed on server
using Tyrus and &ja4w;.
</para>
<para>
The example <link linkend="websocket-client-endpoint">"Client Endpoint"</link> utilizes the concept
of the programmatic endpoint. By programmatic endpoint we mean endpoint which is created by extending
class <code>jakarta.websocket.Endpoint</code>.
The example is standalone java application which needs to depend on some Tyrus artifacts to work
correctly, see <link linkend="standalone-mode">"Tyrus Standalone Mode"</link>.
In the example first the <code>CountDownLatch</code> is initialized. It is needed as a bocking data
structure - on line 31 it either waits for 100 seconds, or until it gets counted down (line 22).
On line 9 the <code>jakarta.websocket.ClientEndpointConfig</code> is created - we will need it later
to connect the endpoint to the server. On line 11 the <code>org.glassfish.tyrus.client.ClientManager</code>
is created. it implements the <code>jakarta.websocket.WebSocketContainer</code> and is used to connect
to server. This happens on next line. The client endpoint functionality is contained in the <code>
jakarta.websocket.Endpoint</code> lazy instantiation. In the <code>onOpen</code> method new MessageHandler
is registered (the received message is just printed on the console and the latch is counted down). After
the registration the message is sent to the server (line 25).
<example xml:id="websocket-client-endpoint">
<title>Client Endpoint</title>
<programlisting language="java" linenumbering="numbered">public class DocClient {
private static CountDownLatch messageLatch;
private static final String SENT_MESSAGE = "Hello World";
public static void main(String [] args){
try {
messageLatch = new CountDownLatch(1);
final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
ClientManager client = ClientManager.createClient();
client.connectToServer(new Endpoint() {
@Override
public void onOpen(Session session, EndpointConfig config) {
try {
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
System.out.println("Received message: "+message);
messageLatch.countDown();
}
});
session.getBasicRemote().sendText(SENT_MESSAGE);
} catch (IOException e) {
e.printStackTrace();
}
}
}, cec, new URI("ws://localhost:8025/websockets/echo"));
messageLatch.await(100, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
}
}</programlisting>
</example>
</para>
</section>
<section xml:id="websocket-programmatic-endpoint">
<title>Creating Server Endpoint Programmatically</title>
<para>
Similarly to <link linkend="websocket-client-endpoint">"Client Endpoint"</link> the server registered endpoint
may also be the programmatic one:
<example xml:id="websocket-programmatic-echo-endpoint">
<title>Programmatic Echo Endpoint</title>
<programlisting language="java" linenumbering="numbered">public class EchoEndpointProgrammatic extends Endpoint {
@Override
public void onOpen(final Session session, EndpointConfig config) {
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}</programlisting>
</example>
</para>
<para>
The functionality of the <code>EchoEndpointProgrammatic</code> is fairly simple - to send the received message back to the sender.
The programmatic server endpoint needs to extend <code>jakarta.websocket.Endpoint</code> - line 1.
Mehod <code>public void onOpen(final Session session, EndpointConfig config)</code> gets called once new
connection to this endpoin0t is opened. In this method the <code>MessageHandler</code> is registered to the
<code>jakarta.websocket.Session</code> instance, which opened the connection. Method <code>public void
onMessage(String message)</code> gets called once the message is received. On line 8 the message
is sent back to the sender.
</para>
</section>
<para>
To see how both annotated and programmatic endpoints may be deployed please check the section Deployment.
In short: you need to put the server endpoint classes into WAR, deploy on server and the endpoints will
be scanned by server and deployed.
</para>
<section xml:id="standalone-mode">
<title>Tyrus in Standalone Mode</title>
<para>
</para>
<para>
To use Tyrus in standalone mode it is necessary to depend on correct Tyrus artifacts.
The following artifacts need to be added to your pom to use Tyrus:
<programlisting language="xml" linenumbering="unnumbered"><dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-server</artifactId>
<version>&version;</version>
</dependency>
<dependency>
<groupId>org.glassfish.tyrus</groupId>
<artifactId>tyrus-container-grizzly-server</artifactId>
<version>&version;</version>
</dependency></programlisting>
</para>
<para>
Let's use the very same example like for &ja4w; and deploy the <code>EchoEndpointAnnotated</code> on the
standalone Tyrus server on the hostname "localhost", port 8025 and path "/websockets", so the endpoint
will be available at address "ws://localhost:8025/websockets/echo".
<programlisting language="java" linenumbering="unnumbered">public void runServer() {
Server server = new Server("localhost", 8025, "/websockets", null, EchoEndpoint.class);
try {
server.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please press a key to stop the server.");
reader.readLine();
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}
}</programlisting>
</para>
</section>
</section>
</chapter>