Skip to content

Commit 685c4bb

Browse files
committed
Update to use latest SDK
1 parent c954b00 commit 685c4bb

File tree

2 files changed

+263
-8
lines changed

2 files changed

+263
-8
lines changed

articles/azure-web-pubsub/tutorial-build-chat.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,11 @@ You may remember in the [publish and subscribe message tutorial](./tutorial-pub-
387387
```java
388388
package com.webpubsub.tutorial;
389389
390-
import com.azure.messaging.webpubsub.WebPubSubClientBuilder;
391390
import com.azure.messaging.webpubsub.WebPubSubServiceClient;
392-
import com.azure.messaging.webpubsub.models.GetAuthenticationTokenOptions;
393-
import com.azure.messaging.webpubsub.models.WebPubSubAuthenticationToken;
394-
391+
import com.azure.messaging.webpubsub.WebPubSubServiceClientBuilder;
392+
import com.azure.messaging.webpubsub.models.GetClientAccessTokenOptions;
393+
import com.azure.messaging.webpubsub.models.WebPubSubClientAccessToken;
394+
import com.azure.messaging.webpubsub.models.WebPubSubContentType;
395395
import io.javalin.Javalin;
396396
397397
public class App {

articles/azure-web-pubsub/tutorial-subprotocol.md

Lines changed: 259 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ Copy the fetched **ConnectionString** and it will be used later in this tutorial
5656
# [Python](#tab/python)
5757
* [Python](https://www.python.org/)
5858

59+
# [Java](#tab/java)
60+
- [Java Development Kit (JDK)](/java/azure/jdk/) version 8 or above
61+
- [Apache Maven](https://maven.apache.org/download.cgi)
62+
5963
---
6064

6165
## Using a subprotocol
@@ -74,7 +78,7 @@ Now let's create a web application using the `json.webpubsub.azure.v1` subprotoc
7478
cd logstream
7579
dotnet new web
7680
dotnet add package Microsoft.Extensions.Azure
77-
dotnet add package Azure.Messaging.WebPubSub --version 1.0.0-beta.3
81+
dotnet add package Azure.Messaging.WebPubSub
7882
```
7983

8084
# [JavaScript](#tab/javascript)
@@ -86,7 +90,7 @@ Now let's create a web application using the `json.webpubsub.azure.v1` subprotoc
8690
npm install --save express
8791
npm install --save ws
8892
npm install --save node-fetch
89-
npm install --save @azure/web-pubsub@1.0.0-alpha.20211102.4
93+
npm install --save @azure/web-pubsub
9094
```
9195

9296
# [Python](#tab/python)
@@ -102,6 +106,42 @@ Now let's create a web application using the `json.webpubsub.azure.v1` subprotoc
102106
pip install azure-messaging-webpubsubservice
103107
```
104108

109+
# [Java](#tab/java)
110+
111+
We will use the [Javalin](https://javalin.io/) web framework to host the web pages。
112+
113+
1. First let's use Maven to create a new app `logstream-webserver` and switch into the *logstream-webserver* folder:
114+
115+
```console
116+
mvn archetype:generate --define interactiveMode=n --define groupId=com.webpubsub.tutorial --define artifactId=logstream-webserver --define archetypeArtifactId=maven-archetype-quickstart --define archetypeVersion=1.4
117+
cd logstream-webserver
118+
```
119+
120+
2. Let's add the Azure Web PubSub SDK and the `javalin` web framework dependency into the `dependencies` node of `pom.xml`:
121+
122+
* `javalin`: simple web framework for Java
123+
* `slf4j-simple`: Logger for Java
124+
* `azure-messaging-webpubsub`: The service client SDK for using Azure Web PubSub
125+
126+
```xml
127+
<dependency>
128+
<groupId>com.azure</groupId>
129+
<artifactId>azure-messaging-webpubsub</artifactId>
130+
<version>1.0.0-beta.6</version>
131+
</dependency>
132+
<!-- https://mvnrepository.com/artifact/io.javalin/javalin -->
133+
<dependency>
134+
<groupId>io.javalin</groupId>
135+
<artifactId>javalin</artifactId>
136+
<version>3.13.6</version>
137+
</dependency>
138+
139+
<dependency>
140+
<groupId>org.slf4j</groupId>
141+
<artifactId>slf4j-simple</artifactId>
142+
<version>1.7.30</version>
143+
</dependency>
144+
```
105145
---
106146

107147
2. Create the server-side to host the `/negotiate` API and web page.
@@ -161,7 +201,7 @@ Now let's create a web application using the `json.webpubsub.azure.v1` subprotoc
161201
var service = context.RequestServices.GetRequiredService<WebPubSubServiceClient>();
162202
var response = new
163203
{
164-
url = service.GenerateClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" }).AbsoluteUri
204+
url = service.GetClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.stream", "webpubsub.joinLeaveGroup.stream" }).AbsoluteUri
165205
};
166206
await context.Response.WriteAsJsonAsync(response);
167207
});
@@ -236,7 +276,71 @@ Now let's create a web application using the `json.webpubsub.azure.v1` subprotoc
236276
server.serve_forever()
237277
238278
```
279+
280+
# [Java](#tab/java)
281+
282+
Let's navigate to the */src/main/java/com/webpubsub/tutorial* directory, open the *App.java* file in your editor, use `Javalin.create` to serve static files:
283+
284+
```java
285+
package com.webpubsub.tutorial;
286+
287+
import com.azure.messaging.webpubsub.WebPubSubServiceClient;
288+
import com.azure.messaging.webpubsub.WebPubSubServiceClientBuilder;
289+
import com.azure.messaging.webpubsub.models.GetClientAccessTokenOptions;
290+
import com.azure.messaging.webpubsub.models.WebPubSubClientAccessToken;
291+
292+
import io.javalin.Javalin;
293+
294+
public class App {
295+
public static void main(String[] args) {
296+
297+
if (args.length != 1) {
298+
System.out.println("Expecting 1 arguments: <connection-string>");
299+
return;
300+
}
301+
302+
// create the service client
303+
WebPubSubServiceClient service = new WebPubSubServiceClientBuilder()
304+
.connectionString(args[0])
305+
.hub("chat")
306+
.buildClient();
307+
308+
// start a server
309+
Javalin app = Javalin.create(config -> {
310+
config.addStaticFiles("public");
311+
}).start(8080);
312+
313+
314+
// Handle the negotiate request and return the token to the client
315+
app.get("/negotiate", ctx -> {
316+
GetClientAccessTokenOptions option = new GetClientAccessTokenOptions();
317+
option.addRole("webpubsub.sendToGroup.stream");
318+
option.addRole("webpubsub.joinLeaveGroup.stream");
319+
WebPubSubClientAccessToken token = service.getClientAccessToken(option);
320+
321+
// return JSON string
322+
ctx.result("{\"url\":\"" + token.getUrl() + "\"}");
323+
return;
324+
});
325+
}
326+
}
327+
```
239328
329+
Depending on your setup, you might need to explicitly set the language level to Java 8. This can be done in the pom.xml. Add the following snippet:
330+
```xml
331+
<build>
332+
<plugins>
333+
<plugin>
334+
<artifactId>maven-compiler-plugin</artifactId>
335+
<version>3.8.0</version>
336+
<configuration>
337+
<source>1.8</source>
338+
<target>1.8</target>
339+
</configuration>
340+
</plugin>
341+
</plugins>
342+
</build>
343+
```
240344
---
241345
242346
3. Create the web page
@@ -252,6 +356,9 @@ Now let's create a web application using the `json.webpubsub.azure.v1` subprotoc
252356
253357
Create an HTML page with below content and save it as `public/index.html`:
254358
359+
# [Java](#tab/java)
360+
361+
Create an HTML page with below content and save it to */src/main/resources/public/index.html*:
255362
---
256363
257364
```html
@@ -309,6 +416,14 @@ Now let's create a web application using the `json.webpubsub.azure.v1` subprotoc
309416
```bash
310417
python server.py "<connection-string>"
311418
```
419+
420+
# [Java](#tab/java)
421+
422+
Now run the below command, replacing `<connection-string>` with the **ConnectionString** fetched in [previous step](#get-the-connectionstring-for-future-use), and open http://localhost:8080 in browser:
423+
424+
```console
425+
mvn compile & mvn package & mvn exec:java -Dexec.mainClass="com.webpubsub.tutorial.App" -Dexec.cleanupDaemonThreads=false -Dexec.args="'<connection_string>'"
426+
```
312427
---
313428
314429
If you are using Chrome, you can press F12 or right-click -> **Inspect** -> **Developer Tools**, and select the **Network** tab. Load the web page, and you can see the WebSocket connection is established. Click to inspect the WebSocket connection, you can see below `connected` event message is received in client. You can see that you can get the `connectionId` generated for this client.
@@ -480,6 +595,123 @@ This will be useful if you want to stream a large amount of data to other client
480595
481596
The code above creates a WebSocket connection to the service and then whenever it receives some data it uses `ws.send()` to publish the data. In order to publish to others, you just need to set `type` to `sendToGroup` and specify a group name in the message.
482597
598+
# [Java](#tab/java)
599+
600+
1. Let's use another terminal and go back to the root folder to create a streaming console app `logstream-streaming` and switch into the *logstream-streaming* folder:
601+
```console
602+
mvn archetype:generate --define interactiveMode=n --define groupId=com.webpubsub.quickstart --define artifactId=logstream-streaming --define archetypeArtifactId=maven-archetype-quickstart --define archetypeVersion=1.4
603+
cd logstream-streaming
604+
```
605+
606+
2. Let's add HttpClient dependencies into the `dependencies` node of `pom.xml`:
607+
608+
```xml
609+
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
610+
<dependency>
611+
<groupId>org.apache.httpcomponents</groupId>
612+
<artifactId>httpclient</artifactId>
613+
<version>4.5.13</version>
614+
</dependency>
615+
<dependency>
616+
<groupId>com.google.code.gson</groupId>
617+
<artifactId>gson</artifactId>
618+
<version>2.8.9</version>
619+
</dependency>
620+
```
621+
622+
3. Now let's use WebSocket to connect to the service. Let's navigate to the */src/main/java/com/webpubsub/quickstart* directory, open the *App.java* file in your editor, and replace code with the below:
623+
```java
624+
package com.webpubsub.quickstart;
625+
626+
import java.io.BufferedReader;
627+
import java.io.IOException;
628+
import java.io.InputStreamReader;
629+
import java.net.URI;
630+
import java.net.http.HttpClient;
631+
import java.net.http.HttpRequest;
632+
import java.net.http.HttpResponse;
633+
import java.net.http.WebSocket;
634+
import java.util.concurrent.CompletionStage;
635+
636+
import com.google.gson.Gson;
637+
638+
public class App
639+
{
640+
public static void main( String[] args ) throws IOException, InterruptedException
641+
{
642+
HttpClient client = HttpClient.newHttpClient();
643+
HttpRequest request = HttpRequest.newBuilder()
644+
.uri(URI.create("http://localhost:8080/negotiate"))
645+
.build();
646+
647+
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
648+
649+
Gson gson = new Gson();
650+
651+
String url = gson.fromJson(response.body(), Entity.class).url;
652+
653+
WebSocket ws = HttpClient.newHttpClient().newWebSocketBuilder().subprotocols("json.webpubsub.azure.v1")
654+
.buildAsync(URI.create(url), new WebSocketClient()).join();
655+
int id = 0;
656+
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
657+
String streaming = reader.readLine();
658+
App app = new App();
659+
while (streaming != null && !streaming.isEmpty()){
660+
String frame = gson.toJson(app.new GroupMessage(streaming + "\n", ++id));
661+
System.out.println("Sending: " + frame);
662+
ws.sendText(frame, true);
663+
streaming = reader.readLine();
664+
}
665+
}
666+
667+
private class GroupMessage{
668+
public String data;
669+
public int ackId;
670+
public final String type = "sendToGroup";
671+
public final String group = "stream";
672+
673+
GroupMessage(String data, int ackId){
674+
this.data = data;
675+
this.ackId = ackId;
676+
}
677+
}
678+
679+
private static final class WebSocketClient implements WebSocket.Listener {
680+
private WebSocketClient() {
681+
}
682+
683+
@Override
684+
public void onOpen(WebSocket webSocket) {
685+
System.out.println("onOpen using subprotocol " + webSocket.getSubprotocol());
686+
WebSocket.Listener.super.onOpen(webSocket);
687+
}
688+
689+
@Override
690+
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
691+
System.out.println("onText received " + data);
692+
return WebSocket.Listener.super.onText(webSocket, data, last);
693+
}
694+
695+
@Override
696+
public void onError(WebSocket webSocket, Throwable error) {
697+
System.out.println("Bad day! " + webSocket.toString());
698+
WebSocket.Listener.super.onError(webSocket, error);
699+
}
700+
}
701+
702+
private static final class Entity {
703+
public String url;
704+
}
705+
}
706+
707+
```
708+
709+
4. Navigate to the directory containing the *pom.xml* file and run the project using the below command
710+
711+
```console
712+
mvn compile & mvn package & mvn exec:java -Dexec.mainClass="com.webpubsub.quickstart.App" -Dexec.cleanupDaemonThreads=false
713+
```
714+
483715
---
484716
485717
You can see there is a new concept "group" here. Group is logical concept in a hub where you can publish message to a group of connections. In a hub, you can have multiple groups and one client can subscribe to multiple groups at the same time. When using subprotocol, you can only publish to a group instead of broadcasting to the whole hub. For details about the terms, check the [basic concepts](./key-concepts.md).
@@ -545,8 +777,19 @@ This will be useful if you want to stream a large amount of data to other client
545777
'webpubsub.joinLeaveGroup.stream']
546778
token = service.get_client_access_token(roles=roles)
547779
```
548-
---
549780
781+
# [Java](#tab/java)
782+
783+
Note that when generating the access token, we set the correct roles to the client in `App.java`:
784+
785+
```java
786+
GetClientAccessTokenOptions option = new GetClientAccessTokenOptions();
787+
option.addRole("webpubsub.sendToGroup.stream");
788+
option.addRole("webpubsub.joinLeaveGroup.stream");
789+
WebPubSubClientAccessToken token = service.getClientAccessToken(option);
790+
791+
```
792+
---
550793
551794
5. Finally also apply some style to `index.html` so it displays nicely.
552795
@@ -623,6 +866,16 @@ for i in $(ls -R); do echo $i; sleep 0.1; done | python stream.py
623866
The complete code sample of this tutorial can be found [here][code-python].
624867
625868
869+
# [Java](#tab/java)
870+
871+
Now you can run below code, type any text and they'll be displayed in the browser in real time.
872+
873+
```console
874+
mvn compile & mvn package & mvn exec:java -Dexec.mainClass="com.webpubsub.quickstart.App" -Dexec.cleanupDaemonThreads=false
875+
```
876+
877+
The complete code sample of this tutorial can be found [here][code-java].
878+
626879
---
627880
628881
@@ -640,3 +893,5 @@ Check other tutorials to further dive into how to use the service.
640893
[code-js]: https://github.com/Azure/azure-webpubsub/tree/main/samples/javascript/logstream/
641894
642895
[code-python]: https://github.com/Azure/azure-webpubsub/tree/main/samples/python/logstream/
896+
897+
[code-java]: https://github.com/Azure/azure-webpubsub/tree/main/samples/java/logstream/

0 commit comments

Comments
 (0)