Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Build real-time web applications with Azure Web PubSub SDK for Java. Use when implementing WebSocket-based messaging, live updates, chat applications, or server-to-client push notifications.
.claude/skills/azure-messaging-webpubsub-java/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-17 | ✗→✓ | ▲ Improved | — | — |
| case-21 | ✗→✓ | ▲ Improved | — | — |
| case-12 | ✗→✓ | ▲ Improved | — | — |
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-02 | ✗→✓ | ▲ Improved | — | — |
Build real-time web applications using the Azure Web PubSub SDK for Java.
xml<dependency> <groupId>com.azure</groupId> <artifactId>azure-messaging-webpubsub</artifactId> <version>1.5.0</version> </dependency>
javaimport com.azure.messaging.webpubsub.WebPubSubServiceClient; import com.azure.messaging.webpubsub.WebPubSubServiceClientBuilder; WebPubSubServiceClient client = new WebPubSubServiceClientBuilder() .connectionString("<connection-string>") .hub("chat") .buildClient();
javaimport com.azure.core.credential.AzureKeyCredential; WebPubSubServiceClient client = new WebPubSubServiceClientBuilder() .credential(new AzureKeyCredential("<access-key>")) .endpoint("<endpoint>") .hub("chat") .buildClient();
javaimport com.azure.identity.DefaultAzureCredentialBuilder; WebPubSubServiceClient client = new WebPubSubServiceClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) .endpoint("<endpoint>") .hub("chat") .buildClient();
javaimport com.azure.messaging.webpubsub.WebPubSubServiceAsyncClient; WebPubSubServiceAsyncClient asyncClient = new WebPubSubServiceClientBuilder() .connectionString("<connection-string>") .hub("chat") .buildAsyncClient();
javaimport com.azure.messaging.webpubsub.models.WebPubSubContentType; // Send text message client.sendToAll("Hello everyone!", WebPubSubContentType.TEXT_PLAIN); // Send JSON String jsonMessage = "{\"type\": \"notification\", \"message\": \"New update!\"}"; client.sendToAll(jsonMessage, WebPubSubContentType.APPLICATION_JSON);
javaimport com.azure.core.http.rest.RequestOptions; import com.azure.core.util.BinaryData; BinaryData message = BinaryData.fromString("Hello filtered users!"); // Filter by userId client.sendToAllWithResponse( message, WebPubSubContentType.TEXT_PLAIN, message.getLength(), new RequestOptions().addQueryParam("filter", "userId ne 'user1'")); // Filter by groups client.sendToAllWithResponse( message, WebPubSubContentType.TEXT_PLAIN, message.getLength(), new RequestOptions().addQueryParam("filter", "'GroupA' in groups and not('GroupB' in groups)"));
java// Send to all connections in a group client.sendToGroup("java-developers", "Hello Java devs!", WebPubSubContentType.TEXT_PLAIN); // Send JSON to group String json = "{\"event\": \"update\", \"data\": {\"version\": \"2.0\"}}"; client.sendToGroup("subscribers", json, WebPubSubContentType.APPLICATION_JSON);
java// Send to a specific connection by ID client.sendToConnection("connectionId123", "Private message", WebPubSubContentType.TEXT_PLAIN);
java// Send to all connections for a specific user client.sendToUser("andy", "Hello Andy!", WebPubSubContentType.TEXT_PLAIN);
java// Add connection to group client.addConnectionToGroup("premium-users", "connectionId123"); // Remove connection from group client.removeConnectionFromGroup("premium-users", "connectionId123"); // Add user to group (all their connections) client.addUserToGroup("admin-group", "userId456"); // Remove user from group client.removeUserFromGroup("admin-group", "userId456"); // Check if user is in group boolean exists = client.userExistsInGroup("admin-group", "userId456");
java// Check if connection exists boolean connected = client.connectionExists("connectionId123"); // Close a connection client.closeConnection("connectionId123"); // Close with reason client.closeConnection("connectionId123", "Session expired"); // Check if user exists (has any connections) boolean userOnline = client.userExists("userId456"); // Close all connections for a user client.closeUserConnections("userId456"); // Close all connections in a group client.closeGroupConnections("inactive-group");
javaimport com.azure.messaging.webpubsub.models.GetClientAccessTokenOptions; import com.azure.messaging.webpubsub.models.WebPubSubClientAccessToken; // Basic token WebPubSubClientAccessToken token = client.getClientAccessToken( new GetClientAccessTokenOptions()); System.out.println("URL: " + token.getUrl()); // With user ID WebPubSubClientAccessToken userToken = client.getClientAccessToken( new GetClientAccessTokenOptions().setUserId("user123")); // With roles (permissions) WebPubSubClientAccessToken roleToken = client.getClientAccessToken( new GetClientAccessTokenOptions() .setUserId("user123") .addRole("webpubsub.joinLeaveGroup") .addRole("webpubsub.sendToGroup")); // With groups to join on connect WebPubSubClientAccessToken groupToken = client.getClientAccessToken( new GetClientAccessTokenOptions() .setUserId("user123") .addGroup("announcements") .addGroup("updates")); // With custom expiration WebPubSubClientAccessToken expToken = client.getClientAccessToken( new GetClientAccessTokenOptions() .setUserId("user123") .setExpiresAfter(Duration.ofHours(2)));
javaimport com.azure.messaging.webpubsub.models.WebPubSubPermission; // Grant permission to send to a group client.grantPermission( WebPubSubPermission.SEND_TO_GROUP, "connectionId123", new RequestOptions().addQueryParam("targetName", "chat-room")); // Revoke permission client.revokePermission( WebPubSubPermission.SEND_TO_GROUP, "connectionId123", new RequestOptions().addQueryParam("targetName", "chat-room")); // Check permission boolean hasPermission = client.checkPermission( WebPubSubPermission.SEND_TO_GROUP, "connectionId123", new RequestOptions().addQueryParam("targetName", "chat-room"));
javaasyncClient.sendToAll("Async message!", WebPubSubContentType.TEXT_PLAIN) .subscribe( unused -> System.out.println("Message sent"), error -> System.err.println("Error: " + error.getMessage()) ); asyncClient.sendToGroup("developers", "Group message", WebPubSubContentType.TEXT_PLAIN) .doOnSuccess(v -> System.out.println("Sent to group")) .doOnError(e -> System.err.println("Failed: " + e)) .subscribe();
javaimport com.azure.core.exception.HttpResponseException; try { client.sendToConnection("invalid-id", "test", WebPubSubContentType.TEXT_PLAIN); } catch (HttpResponseException e) { System.out.println("Status: " + e.getResponse().getStatusCode()); System.out.println("Error: " + e.getMessage()); }
bashWEB_PUBSUB_CONNECTION_STRING=Endpoint=https://<resource>.webpubsub.azure.com;AccessKey=... WEB_PUBSUB_ENDPOINT=https://<resource>.webpubsub.azure.com WEB_PUBSUB_ACCESS_KEY=<your-access-key>
| Role | Permission | |------|------------| | webpubsub.joinLeaveGroup | Join/leave any group | | webpubsub.sendToGroup | Send to any group | | webpubsub.joinLeaveGroup.<group> | Join/leave specific group | | webpubsub.sendToGroup.<group> | Send to specific group |
This skill is applicable to execute the workflow or actions described in the overview.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +27 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
Other measured skills in the registry, with their headline benchmark lift.