<commit_before>= Using Web Sockets

This guide explains how your Shamrock application can utilize web sockets to create interactive web applications.
Because it's the _canonical_ web socket application, we are going to create a simple chat application.

== Prerequisites

To complete this guide, you need:

* less than 15 minutes
* an IDE
* JDK 1.8+ installed with `JAVA_HOME` configured appropriately
* Apache Maven 3.5+

== Architecture

In this guide, we create a straightforward chat application using web sockets to receive and send messages to the other connected users.

image:websocket-guide-architecture.png[alt=Architecture,width=640,height=480]

== Solution

We recommend you to follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.

Clone the Git repository: `git clone https://github.com/protean-project/quickstarts.git`, or download an https://github.com/protean-project/quickstarts/archive/master.zip[archive].

The solution is located in the `using-websockets` https://github.com/protean-project/quickstarts/tree/master/using-websockets[directory].

== Creating the Maven project

First, we need a new project. Create a new project with the following command:

```
mvn org.jboss.shamrock:shamrock-maven-plugin:1.0.0.Alpha1-SNAPSHOT:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=using-websockets \
    -Dextensions="websockets"
```

This command generates the Maven project (without any classes) and import the WebSockets extension.

== Handling web sockets

Our application contains a single class that handles the web sockets.
Create the `org.acme.websocket.ChatSocket` class in the `src/main/java` directory.
Copy the following content into the created file:

[source,java]
----
package org.acme.websocket;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.enterprise.context.ApplicationScoped;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.Session;

@ServerEndpoint("/chat/{username}")         // <1>
@ApplicationScoped
public class ChatSocket {

    Map<String, Session> sessions = new ConcurrentHashMap<>(); // <2>

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        sessions.put(username, session);
        broadcast("User " + username + " joined");
    }

    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
        sessions.remove(username);
        broadcast("User " + username + " left");
    }

    @OnError
    public void onError(Session session, @PathParam("username") String username, Throwable throwable) {
        sessions.remove(username);
        broadcast("User " + username + " left on error: " + throwable);
    }

    @OnMessage
    public void onMessage(String message, @PathParam("username") String username) {
        broadcast(">> " + username + ": " + message);
    }

    private void broadcast(String message) {
        sessions.values().forEach(s -> {
            s.getAsyncRemote().sendObject(message, result ->  {
                if (result.getException() != null) {
                    System.out.println("Unable to send message: " + result.getException());
                }
            });
        });
    }

}
----
1. Configures the web socket URL
2. Stores the currently opened web sockets

== A slick web frontend

All chat applications need a _nice_ UI, well, this one may not be that nice, but does the work.
Shamrock automatically serves static resources contained in the `META-INF/resources` directory.
Creates the `src/main/resources/META-INF/resources` directory and copy this https://github.com/protean-project/quickstarts/blob/master/using-websockets/src/main/resources/assets/index.html[index.html] file in it.

== Run the application

Now, let's see our application in action. Run it with:

```
mvn compile shamrock:dev
```

Then open your 2 browser windows to http://localhost:8080/:

1. Enter a name in the top text area (use 2 different names).
2. Click on connect
3. Send and receive messages

image:websocket-guide-screenshot.png[alt=Application,width=800]

As usual, the application can be packaged using `mvn clean package` and executed using the `-runner.jar` file.<commit_msg>extend the websocket guide (native image, tests)<commit_after>= Using Web Sockets

This guide explains how your Shamrock application can utilize web sockets to create interactive web applications.
Because it's the _canonical_ web socket application, we are going to create a simple chat application.

== Prerequisites

To complete this guide, you need:

* less than 15 minutes
* an IDE
* JDK 1.8+ installed with `JAVA_HOME` configured appropriately
* Apache Maven 3.5+

== Architecture

In this guide, we create a straightforward chat application using web sockets to receive and send messages to the other connected users.

image:websocket-guide-architecture.png[alt=Architecture,width=640,height=480]

== Solution

We recommend you to follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.

Clone the Git repository: `git clone https://github.com/protean-project/quickstarts.git`, or download an https://github.com/protean-project/quickstarts/archive/master.zip[archive].

The solution is located in the `using-websockets` https://github.com/protean-project/quickstarts/tree/master/using-websockets[directory].

== Creating the Maven project

First, we need a new project. Create a new project with the following command:

```
mvn org.jboss.shamrock:shamrock-maven-plugin:1.0.0.Alpha1-SNAPSHOT:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=using-websockets \
    -Dextensions="websockets"
```

This command generates the Maven project (without any classes) and import the WebSockets extension.

== Handling web sockets

Our application contains a single class that handles the web sockets.
Create the `org.acme.websocket.ChatSocket` class in the `src/main/java` directory.
Copy the following content into the created file:

[source,java]
----
package org.acme.websocket;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.enterprise.context.ApplicationScoped;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.Session;

@ServerEndpoint("/chat/{username}")         // <1>
@ApplicationScoped
public class ChatSocket {

    Map<String, Session> sessions = new ConcurrentHashMap<>(); // <2>

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        sessions.put(username, session);
        broadcast("User " + username + " joined");
    }

    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
        sessions.remove(username);
        broadcast("User " + username + " left");
    }

    @OnError
    public void onError(Session session, @PathParam("username") String username, Throwable throwable) {
        sessions.remove(username);
        broadcast("User " + username + " left on error: " + throwable);
    }

    @OnMessage
    public void onMessage(String message, @PathParam("username") String username) {
        broadcast(">> " + username + ": " + message);
    }

    private void broadcast(String message) {
        sessions.values().forEach(s -> {
            s.getAsyncRemote().sendObject(message, result ->  {
                if (result.getException() != null) {
                    System.out.println("Unable to send message: " + result.getException());
                }
            });
        });
    }

}
----
1. Configures the web socket URL
2. Stores the currently opened web sockets

== A slick web frontend

All chat applications need a _nice_ UI, well, this one may not be that nice, but does the work.
Shamrock automatically serves static resources contained in the `META-INF/resources` directory.
Creates the `src/main/resources/META-INF/resources` directory and copy this https://github.com/protean-project/quickstarts/blob/master/using-websockets/src/main/resources/assets/index.html[index.html] file in it.

== Run the application

Now, let's see our application in action. Run it with:

```
mvn compile shamrock:dev
```

Then open your 2 browser windows to http://localhost:8080/:

1. Enter a name in the top text area (use 2 different names).
2. Click on connect
3. Send and receive messages

image:websocket-guide-screenshot.png[alt=Application,width=800]

As usual, the application can be packaged using `mvn clean package` and executed using the `-runner.jar` file.
You can also build the native executable using `mvn package -Pnative`.

You can also test your web socket applications using the approach detailed https://github.com/protean-project/quickstarts/blob/master/using-websockets/src/test/java/org/acme/websocket/ChatTestCase.java[here].
{'fraction_non_alphanumeric': 0.09896395424131232, 'fraction_numerical': 0.006906971724584502, 'mean_word_length': 3.937133724027704, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 19, 'https://': 9, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4253247', 'n_tokens_mistral': 2657, 'n_tokens_neox': 2538, 'n_words': 871}