Monday, April 29, 2024
HomeJavaFind out how to construct functions with the WebSocket API for Java...

Find out how to construct functions with the WebSocket API for Java EE and Jakarta EE


Oracle Java Certification, Java Prep, Java Certification Exam, Java Tutorial and Materials, Java Career, Java Skills, Java Jobs
WebSocket is a two-way communication protocol that lets purchasers ship and obtain messages over a single connection to a server endpoint. The Jakarta WebSocket API, a part of the Jakarta EE platform, can be utilized to develop WebSocket server endpoints in addition to WebSocket purchasers. This text offers a quick overview of the Jakarta WebSocket specification, and I’ll present the best way to assemble an utility utilizing WebSockets.

I’ll cowl the Jakarta WebSocket API because it stands as a part of the Jakarta EE 9 platform launch. That mentioned, the examples on this article will work with Jakarta EE 8 or Java EE 7 or Java EE 8 functions. The primary distinction is that the namespace for Jakarta EE 9 is jakarta.*; in earlier releases, it was javax.*. Due to this fact, if you’re utilizing a earlier launch, change the namespace to javax.*.

WebSocket is a vendor-independent commonplace. For those who’re curious in regards to the WebSocket protocol, it’s lined in depth in IETF RFC 6455. Many tutorials are revealed on-line. It’s also possible to learn the documentation for the WebSocket interface in JDK 15.

To speak with WebSocket, you could configure a server endpoint. The best endpoint is a regular Java class that both is annotated with @ServerEndpoint or extends the jakarta.websocket.Endpoint summary class.

An endpoint additionally comprises a way that’s annotated with @OnMessage. The @ServerEndpoint annotation accepts the URI at which the WebSocket server will settle for messages that must be despatched. The URI can be used to register purchasers as recipients for WebSocket messages.

The next easy endpoint accepts a string-based message on the endpoint URI /basicEndpoint and performs an exercise with that message as soon as it has been acquired. A consumer can connect with the server endpoint URI to open the connection, which is able to stay open for sending and receiving messages throughout the session.

@ServerEndpoint(worth = “/basicEndpoint”)

public class BasicEndpoint { 

    @OnMessage

    public void onMessage(Session session,

                                  String message){

        // carry out an motion

    }

}

Within the following sections, you’ll see the wide range of choices obtainable for creating more-sophisticated WebSocket options. Nevertheless, the general idea for producing a WebSocket endpoint stays very a lot the identical because the earlier instance.

Digging into the specification

You’ll be able to develop WebSocket endpoints utilizing both an annotation-based or programmatic strategy. You should utilize the @ServerEndpoint annotation to specify {that a} class is used as a WebSocket server endpoint. The choice to utilizing @ServerEndpoint is to increase the jakarta.websocket.Endpoint summary class. The examples for this text use the annotation strategy. Equally, you should utilize the @ClientEndpoint annotation to specify that a regular Java class is used to just accept WebSocket messages. @ServerEndpoint and @ClientEndpoint can specify the next attributes:

◉ worth: Specifies a URI path at which the server endpoint will likely be deployed.

◉ decoders: Specifies a listing of courses that can be utilized to decode incoming messages to the WebSocket endpoint. Courses implement the Decoder interface.

◉ encoders: Specifies a listing of courses that can be utilized to encode outgoing messages from the WebSocket endpoint. Courses implement the Encoder interface.

◉ subprotocols: Specifies a string-based checklist of supported subprotocols.

◉ configurator: Lists a customized implementation of ServerEndpointConfiguration.Configurator.

The specification defines quite a lot of annotations that may be positioned on methodology declarations of a WebSocket endpoint class. Every of the annotations can be utilized solely as soon as per class, and they’re used to brighten strategies which comprise implementations which are to be invoked when the corresponding WebSocket occasions happen. The tactic annotations are as follows:

◉ @OnOpen: When it’s specified on a way, will probably be invoked when a WebSocket connection is established. The tactic can optionally specify Session as the primary parameter and EndpointConfig as a second parameter.

◉ @OnMessage: When it’s specified on a way, will probably be invoked when a message is acquired. The tactic can optionally specify Session as the primary parameter and String (message) as a second parameter.

◉ @OnClose: When it’s specified on a way, will probably be invoked when a WebSocket connection is closed. The tactic can optionally specify Session as the primary parameter and CloseReason as a second parameter.

◉ @OnError: When it’s specified on a way, will probably be invoked when an Exception is being thrown by any methodology annotated with @OnOpen, @OnMessage, or @OnClose. The tactic can optionally specify Session as the primary parameter together with Throwable parameters.

Configuring a WebSocket mission

To get began with Jakarta WebSocket, you could both add the websocket-api dependency to a mission or add the jakarta-ee dependency to utilize the whole platform. Each the Jakarta EE full profile and the online profile comprise the Jakarta WebSocket dependency.

<dependency>

            <groupId>jakarta.platform</groupId>

            <artifactId>jakarta.jakartaee-api</artifactId>

            <model>${jakartaee}</model>

</dependency>

For tasks that may comprise an @ClientEndpoint, you could add an implementation as a dependency. On this case, I add the Tyrus consumer implementation by including the next dependency. (Challenge Tyrus, from Oracle, is a JSR 356 Java API for WebSocket reference implementation.)

<dependency>

            <groupId>org.glassfish.tyrus.bundles</groupId>

            <artifactId>tyrus-standalone-client</artifactId>

            <model>2.0.0-M3</model>

 </dependency>

Making a chat utility utilizing WebSocket

Right here’s an utility that makes use of WebSocket server endpoints with a JavaScript WebSocket consumer to ship and obtain messages. This specific instance, known as AcmeChat, makes use of Maven, however one other construct system comparable to Gradle would work simply as properly. This instance will likely be deployed to Payara 5.202 operating on Jakarta EE 9.

To comply with alongside, you may clone the supply code from GitHub.

The WebSocket endpoint. To start, create a Maven internet utility and add the Jakarta EE 9 API dependency, together with any others which may be used, as proven in Itemizing 1. On this state of affairs, you can additionally use the Jakarta EE Net Profile to make the appliance lighter.

Itemizing 1. Including the Jakarta EE 9 API dependency

<mission xmlns=”http://maven.apache.org/POM/4.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

         xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.employeeevent</groupId>

    <artifactId>AcmeChat</artifactId>

    <model>1.0-SNAPSHOT</model>

    <packaging>struggle</packaging>

    <identify>AcmeChat-1.0-SNAPSHOT</identify>

    

    <properties>

        <maven.compiler.supply>1.8</maven.compiler.supply>

        <maven.compiler.goal>1.8</maven.compiler.goal>

        <endorsed.dir>${mission.construct.listing}/endorsed</endorsed.dir>

        <mission.construct.sourceEncoding>UTF-8</mission.construct.sourceEncoding>

        <failOnMissingWebXml>false</failOnMissingWebXml>

        <jakartaee>9.0.0-RC3</jakartaee>

    </properties>

    

    <dependencies>

        <dependency>

            <groupId>jakarta.platform</groupId>

            <artifactId>jakarta.jakartaee-api</artifactId>

            <model>${jakartaee}</model>

        </dependency>

        <dependency>

            <groupId>org.primefaces</groupId>

            <artifactId>primefaces</artifactId>

            <model>8.0</model>

        </dependency>

        <dependency>

            <groupId>org.glassfish.tyrus.bundles</groupId>

            <artifactId>tyrus-standalone-client</artifactId>

            <model>2.0.0-M3</model>

        </dependency>

    </dependencies>

    

    <construct>

        <plugins>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-compiler-plugin</artifactId>

                <model>3.1</model>

                <configuration>

                    <supply>1.8</supply>

                    <goal>1.8</goal>

                    <compilerArguments>

                        <endorseddirs>${endorsed.dir}</endorseddirs>

                    </compilerArguments>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-war-plugin</artifactId>

                <model>2.3</model>

                <configuration>

                    <failOnMissingWebXml>false</failOnMissingWebXml>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-dependency-plugin</artifactId>

                <model>2.6</model>

                <executions>

                    <execution>

                        <part>validate</part>

                        <targets>

                            <objective>copy</objective>

                        </targets>

                        <configuration>

                            <outputDirectory>${endorsed.dir}</outputDirectory>

                            <silent>true</silent>

                            <artifactItems>

                                <artifactItem>

                                    <groupId>jakarta.platform</groupId>

                                    <artifactId>jakarta.jakartaee-api</artifactId>

                                    <model>${jakartaee}</model>

                                    <kind>pom</kind>

                                </artifactItem>

                            </artifactItems>

                        </configuration>

                    </execution>

                </executions>

            </plugin>

        </plugins>

    </construct>

</mission>

Oracle Java Certification, Java Prep, Java Certification Exam, Java Tutorial and Materials, Java Career, Java Skills, Java Jobs

Subsequent, create the WebSocket server endpoint class named com.employeeevent.acmechat.ChatEndpoint. The supply code for this class is proven in Itemizing 2. Annotate the category with @ServerEndpoint and specify a URI path of “/chatEndpoint/{username}” for the worth attribute. Be aware the trail parameter that’s enclosed in curly braces on the finish of the URI. This permits the endpoint to just accept a parameter. On this case, I will likely be sending a message that’s composed of a Java object. Due to this fact, I want to make use of an encoder and decoder to translate the message from the consumer to the server. I can specify an encoder and decoder through attributes of @ServerEndpoint.

Itemizing 2. Creating the WebSocket server endpoint class

package deal com.employeeevent.acmechat;

import jakarta.inject.Inject;

import java.io.IOException;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

import java.util.concurrent.CopyOnWriteArraySet;

import jakarta.websocket.EncodeException;

import jakarta.websocket.OnClose;

import jakarta.websocket.OnError;

import jakarta.websocket.OnMessage;

import jakarta.websocket.OnOpen;

import jakarta.websocket.Session;

import jakarta.websocket.server.PathParam;

import jakarta.websocket.server.ServerEndpoint;

@ServerEndpoint(worth = “/chatEndpoint/{username}”,

        encoders = {MessageEncoder.class},

        decoders = {MessageDecoder.class})

public class ChatEndpoint {

    

    @Inject

    ChatSessionController chatSessionController;

    personal static Session session;

    personal static Set<Session> chatters = new CopyOnWriteArraySet<>();

    @OnOpen

    public void messageOpen(Session session,

            @PathParam(“username”) String username) throws IOException,

            EncodeException {

        this.session = session;

        Map<String,String> chatusers = chatSessionController.getUsers();

        chatusers.put(session.getId(), username);

        chatSessionController.setUsers(chatusers);

        chatters.add(session);

        Message message = new Message();

        message.setUsername(username);

        message.setMessage(“Welcome ” + username);

        broadcast(message);

    }

    @OnMessage

    public void messageReceiver(Session session,

            Message message) throws IOException, EncodeException {

        Map<String,String> chatusers = chatSessionController.getUsers();

        message.setUsername(chatusers.get(session.getId()));

        broadcast(message);

    }

    @OnClose

    public void shut(Session session) {

        chatters.take away(session);

        Message message = new Message();

        Map<String,String> chatusers = chatSessionController.getUsers();

        String chatuser = chatusers.get(session.getId());

        message.setUsername(chatuser);

        chatusers.take away(chatuser);

        message.setMessage(“Disconnected from server”);

    }

    @OnError

    public void onError(Session session, Throwable throwable) {

        System.out.println(“There was an error with session ” + session.getId());

    }

    personal static void broadcast(Message message)

            throws IOException, EncodeException {

       

        chatters.forEach(session -> {

            synchronized (session) {

                attempt {

                    session.getBasicRemote().

                            sendObject(message);

                } catch (IOException | EncodeException e) {

                    e.printStackTrace();

                }

            }

        });

    }

}

Then, the endpoint class declares a discipline, recognized as session, that’s used to carry the WebSocket Session and one other Set<Session>, recognized as chatters, to carry every of the related chat consumer periods. The category additionally injects an @ApplicationScoped controller class entitled ChatSessionController for storing customers in a easy HashMap, which is proven in Itemizing 3.

Itemizing 3. Endpoint class declaring fields to carry the WebSocket session and chat consumer periods

@Named

@ApplicationScoped

public class ChatSessionController implements java.io.Serializable {

    

    personal Map<String, String> customers = null;

    

    public ChatSessionController(){}

    

    @PostConstruct

    public void init(){

         customers = new HashMap<>();

    }

    /**

     * @return the customers

     */

    public Map<String, String> getUsers() {

        return customers;

    }

    /**

     * @param for the customers

     */

    public void setUsers(Map<String, String> customers) {

        this.customers = customers;

    }

    

}

The ChatEndpoint class declares 4 strategies for dealing with the WebSocket server occasions and a way named broadcast() that’s used to broadcast messages to every of the related purchasers, all of that are described beneath:

personal static void broadcast(Message message)

            throws IOException, EncodeException {

       

        chatters.forEach(session -> {

            synchronized (session) {

                attempt {

                    session.getBasicRemote().

                            sendObject(message);

                } catch (IOException | EncodeException e) {

                    e.printStackTrace();

                }

            }

        });

}

◉ The printed() methodology is personal and static, and it accepts a Message object. The tactic merely traverses the set of chat periods, saved inside the chatters discipline, and inside a synchronized block calls upon the getBasicRemote().sendObject() methodology for every session, sending the Message object.

◉ The messageOpen() methodology, annotated with @OnOpen, is executed when the connection is opened. The tactic accepts a Session and an @PathParam string, which accepts the username substitute variable that’s contained inside the @ServerEndpoint worth attribute. Subsequent, the Session and username are each saved, and a Message object is constructed utilizing the username and message textual content, and eventually the message is broadcast through the invocation of the published() methodology.

◉ The messageReceiver() methodology, annotated with @OnMessage, is executed when the WebSocket message is acquired. The tactic accepts a Session and Message; it makes use of the ChatSessionController to acquire the username of the consumer related to the session and shops it within the Message object. The message is then broadcast by passing the Message to the published() methodology.

◉ The shut() methodology, annotated with @OnClose, is invoked when the connection is closed. This methodology accepts a Session, which is then faraway from the Set of chatters, in addition to the chatusers Map. The session is then used to acquire the corresponding username from the ChatSessionController, and it’s saved in a brand new Message object, which is subsequently broadcast to alert the opposite chatters that the consumer has disconnected.

◉ The onError() methodology, annotated with @OnError, is invoked at any time when one of many different annotated strategies throws an exception. This WebSocket endpoint can settle for messages from any WebSocket consumer, so long as the consumer has an energetic session with the endpoint. To speak with the endpoint, the consumer will connect with the next URI: ws://<hostname>:<port>/AcmeChat/chatEndpoint.

The WebSocket consumer. You’ll be able to write a consumer in quite a lot of languages and nonetheless have the power to speak with the WebSocket endpoint. On this instance, I wrote the consumer in JavaScript and invoked it through a Jakarta Server Faces entrance finish.

Have a look at Itemizing 4, which comprises the supply code for the consumer. Be aware that the physique of the consumer is written in Jakarta Server Faces and makes use of PrimeFaces elements for the consumer interface. The consumer interface comprises an inputText discipline for the username, an inputTextarea for the message, and two commandButton widgets.

One of many commandButton widgets invokes a JavaScript perform named chatRelay(), which opens a connection to the WebSocket. The opposite button invokes a JavaScript perform named ship() to ship the message from the inputTextarea to the WebSocket endpoint.

Itemizing 4. Supply code for the consumer

<html xmlns=”http://www.w3.org/1999/xhtml”

      xmlns:h=”http://xmlns.jcp.org/jsf/html”

      xmlns:p=”http://primefaces.org/ui”

      xmlns:f=”http://xmlns.jcp.org/jsf/core”>

    <h:head>

        <script kind=”textual content/javascript”>

                var ws;

                perform chatRelay()

                {

                    var username = doc.getElementById(“chatForm:username”).valueOf();

                    if (“WebSocket” in window)

                    {

                        var json = {

                            ‘username’: username,

                            ‘message’: “”

                        };

                        // Open WebSocket

                        ws = new WebSocket(“ws://localhost:8080/AcmeChat/chatEndpoint/” + username.worth);

                        ws.onopen = perform ()

                        {

                            // Carry out dealing with when connection is opened

                        };

                        ws.onmessage = perform (evt)

                        {

                            var json = JSON.parse(evt.knowledge);

                            var currentValue = doc.getElementById(‘output’).innerHTML;

                            doc.getElementById(‘output’).innerHTML =

                                    currentValue +

                                    ‘<br />’ +

                                    json.username + “: ” + json.message;

                        };

                        ws.onclose = perform ()

                        {

                            // websocket is closed.

                            alert(“Connection is closed…”);

                        };

                    } else

                    {

                        // The browser does not assist WebSocket

                        alert(“WebSocket NOT supported by your Browser!”);

                    }

                }

            perform ship() {

                var username = doc.getElementById(‘chatForm:username’).valueOf();

                var message = doc.getElementById(‘chatForm:chatText’).valueOf();

                var json = {

                    ‘username’: username.worth,

                    ‘message’: message.worth

                };

                ws.ship(JSON.stringify(json));

                return false;

            }

        </script>

    </h:head>

    <h:physique>

        <h:kind id=”chatForm”>

            <h:outputLabel for=”username” worth=”Username: “/>

            <p:inputText id=”username” />

            <br/>

            <p:commandButton id=”wsRelay” kind=”button” worth=”Join”

                             onclick=”chatRelay();” replace=”chatText,sendMessage”/>

            <br/><br/>

            <p:inputTextarea id=”chatText” cols=”30″ rows=”10″ type=”visibility: #{chatSessionController.customers ne null? ‘seen’:’hidden’}”></p:inputTextarea>

            <br/><br/>

            <p:commandButton id=”sendMessage” kind=”button” worth=”Ship”

                             type=”visibility: #{chatSessionController.customers ne null? ‘seen’:’hidden’}”

                             onclick=”ship();”/>

        </h:kind>

        <br/><br/>

        <div id=”output”></div>

    </h:physique>

</html>

To open a connection to the endpoint, the chatRelay() perform accepts the username from the consumer. Subsequent, it checks to make sure that the consumer’s browser will work with WebSockets and, if it gained’t, a message is offered on the consumer. If the browser is suitable with WebSockets, a brand new JSON object is created, passing the username and message textual content. The WebSocket is then opened by passing the URI to the WebSocket endpoint and appending the username to be handed in as a path parameter, for instance:

ws = new WebSocket(“ws://localhost:8080/AcmeChat/chatEndpoint/” + username.worth);

At this level, the WebSocket consumer is listening for responses from the server, and there are callback features that await the server responses. The ws.onopen perform, proven beneath, is invoked when the connection is opened, invoking any dealing with code which may be current:

ws.onopen = perform ()

        {

  // Carry out dealing with

        };

The ws.onmessage perform, proven beneath, accepts an occasion parameter. The occasion is the message that has been acquired from the server endpoint. On this case, I used the JavaScript JSON API to parse the info and populate the chat display with the incoming message textual content.

ws.onmessage = perform (evt)

        {

            var json = JSON.parse(evt.knowledge);

            var currentValue = doc.getElementById(‘output’).innerHTML;

            doc.getElementById(‘output’).innerHTML =

                    currentValue +

                    ‘<br />’ +

                    json.username + “: ” + json.message;

        };

The ws.onclose perform, proven beneath, is invoked when the WebSocket server connection is disconnected, performing any processing code, as required. An instance can be a case the place the community connection was misplaced or the WebSocket endpoint was shut down. In such a case, the consumer might be alerted that the connection was closed.

ws.onclose = perform ()

        {

            // websocket is closed.

            alert(“Connection is closed…”);

        };

As soon as the consumer session has been began and the WebSocket consumer is listening, any messages acquired from the WebSocket endpoint will likely be revealed through the ws.onmessage handler. The JavaScript ship() perform, proven beneath, is then used to ship any messages that the consumer varieties into the inputTextarea to the server endpoint for broadcasting to any listening purchasers. The ship() perform creates a JSON object from the consumer username and message and sends it to the endpoint utilizing the ws.ship perform, together with somewhat assist from the JSON.stringify utility to assist parse the JSON.

perform ship() {

    var username = doc.getElementById(‘chatForm:username’).valueOf();

    var message = doc.getElementById(‘chatForm:chatText’).valueOf();

    var json = {

        ‘username’: username.worth,

        ‘message’: message.worth

    };

    ws.ship(JSON.stringify(json));

    return false;

}

Utilizing this consumer configuration, two or extra completely different purchasers can connect with the identical WebSocket endpoint and talk with one another in chat-room type.

The decoder and encoder. When the JavaScript consumer sends a message to the endpoint, it’s in JSON format. The WebSocket endpoint accepts a plain previous Java object named Message, which comprises the username and message. The decoder and encoder courses rework the client-side messages to the server-side message object, and vice versa. The Jakarta WebSocket API makes it straightforward to develop decoders and encoders by merely implementing the Decoder or Encoder interfaces, respectively.

Itemizing 5 reveals the Decoder class implementation, which is known as MessageDecoder. This class decodes the client-side message right into a Message object for processing by the WebSocket server. The interface makes use of generics to implement the decoder for the accepted Java object. The category overrides 4 strategies: init(), willDecode(), decode(), and destroy().

Very like the WebSocket endpoint, the decoder could be very a lot event-based. The init() methodology accepts an EndpointConfig object, and it’s invoked when the message is distributed from the consumer to the endpoint. The willDecode() methodology, which accepts a string-based message, is invoked subsequent to return a boolean indicating whether or not the incoming message is within the appropriate format. If the message is within the appropriate format, the decode() methodology is invoked, once more accepting a string-based message in JSON format, and the message is decoded into the Message object for processing through the endpoint. Lastly, the destroy() methodology is invoked when the consumer session turns into invalid.

Itemizing 5. The Decoder class implementation

package deal com.employeeevent.acmechat;

import java.io.StringReader;

import jakarta.json.Json;

import jakarta.json.JsonObject;

import jakarta.websocket.DecodeException;

import jakarta.websocket.Decoder;

import jakarta.websocket.EndpointConfig;

public class MessageDecoder implements Decoder.Textual content<Message> {

  @Override

  public Message decode(String jsonMessage) throws DecodeException {

    JsonObject jsonObject = Json

        .createReader(new StringReader(jsonMessage)).readObject();

    Message message = new Message();

    message.setUsername(jsonObject.getString(“username”));

    message.setMessage(jsonObject.getString(“message”));

    return message;

  }

  @Override

  public boolean willDecode(String jsonMessage) {

    attempt {

      // Verify if incoming message is legitimate JSON

      Json.createReader(new StringReader(jsonMessage)).readObject();

      return true;

    } catch (Exception e) {

      return false;

    }

  }

  @Override

  public void init(EndpointConfig ec) {

    System.out.println(“Initializing message decoder”);

  }

  @Override

  public void destroy() {

    System.out.println(“Destroyed message decoder”);

  }

}

Itemizing 6 reveals the Encoder class implementation, which is known as MessageEncoder. This class encodes the server-side Message object to a JsonObject to be handed again to the consumer for processing. The interface makes use of generics to implement the encoder for the accepted Java object.

The category then overrides three strategies: init(), encode(), and destroy(). Once more, very like the WebSocket endpoint, the encoder could be very a lot event-based in that the init() methodology accepts an EndpointConfig object, and it’s initiated as soon as for every consumer session that’s opened. The encode() methodology accepts the item being encoded, on this case Message, and performs processing to translate that object into JSON earlier than it’s despatched again to the consumer. Lastly, the destroy() methodology is invoked when the consumer session turns into invalid.

Itemizing 6. The Encoder class implementation

package deal com.employeeevent.acmechat;

import jakarta.json.Json;

import jakarta.json.JsonObject;

import jakarta.websocket.EncodeException;

import jakarta.websocket.Encoder;

import jakarta.websocket.EndpointConfig;

public class MessageEncoder implements Encoder.Textual content<Message> {

  @Override

  public String encode(Message message) throws EncodeException {

    JsonObject jsonObject = Json.createObjectBuilder()

        .add(“username”, message.getUsername())

        .add(“message”, message.getMessage()).construct();

    return jsonObject.toString();

  }

  @Override

  public void init(EndpointConfig ec) {

    System.out.println(“Initializing message encoder”);

  }

    @Override

    public void destroy() {

        System.out.println(“Destroying encoder…”);

    }

    

}

The consumer endpoint

You’ll be able to develop a consumer endpoint to speak with a WebSocket server endpoint. The best consumer endpoint is a regular Java class that’s annotated with @ClientEndpoint. You’ll be able to see the complete supply code of a ClientEndpoint instance in Itemizing 7.

Itemizing 7. Code for a consumer endpoint

@ClientEndpoint

public class BasicClient {

    

    Session session = null;

    personal MessageHandler handler;

    

    public BasicClient(URI endpointURI) {

        attempt {

            WebSocketContainer container = ContainerProvider.getWebSocketContainer();

            container.connectToServer(this, endpointURI);

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

    

    @OnOpen

    public void onOpen(Session session){

        this.session = session;

        attempt {

        session.getBasicRemote().sendText(“Opening connection”);

        } catch (IOException ex){

            System.out.println(ex);

        }

    }

    

    public void addMessageHandler(MessageHandler msgHandler) {

        this.handler = msgHandler;

    }

    

    @OnMessage

    public void processMessage(String message) {

        System.out.println(“Obtained message in consumer: ” + message);

    }

    

    public void sendMessage(String message) {

        attempt {

            this.session.getBasicRemote().sendText(message);

        } catch (IOException ex) {

            Logger.getLogger(BasicClient.class.getName()).log(Degree.SEVERE, null, ex);

        }

    }

    

     public static interface MessageHandler {

        public void handleMessage(String message);

    }

On this instance, the ClientEndpoint is known as BasicClient. A Session and MessageHandler are declared inside the class, and the constructor accepts a URI. Upon instantiation through the constructor, a ContainerProvider.getWebsocketContainer() is known as to acquire a WebsocketContainer occasion recognized as container. The container.connectToServer() methodology is then invoked, passing the endpoint URI to instantiate the consumer connection.

The consumer comprises a way named onOpen(), which is annotated with @OnOpen, and accepts a Session. This methodology is invoked when the ClientEndpoint connection is open, and it units the session after which calls upon the getBasicRemote().sendText() methodology to ship a message to the consumer to point the connection is open.

The consumer additionally comprises a way named processMessage(), annotated with @OnMessage, which accepts a string. This methodology is known as upon when a message is acquired from the ServerEndpoint. The consumer sendMessage() methodology additionally accepts a string, and it calls upon the session.getBasicRemote().sendText() methodology to ship the message to the ServerEndpoint.

This specific instance additionally comprises an inside MessageHandler interface and an addMessageHandler() methodology, that are used to ship the messages from the consumer. You should utilize the next code to work with the consumer:

// open websocket

remaining BasicClient clientEndPoint = new BasicClient(

        new URI(“ws://localhost:8080/AcmeChat/basicEndpoint”));

// add listener

clientEndPoint.addMessageHandler(new BasicClient.MessageHandler() {

    public void handleMessage(String message) {

        System.out.println(message);

    }

});

// ship message to websocket

clientEndPoint.sendMessage(“Message despatched from consumer!”);

WebSocket customization

Typically you have got a requirement to develop customized implementations, comparable to consumer/server handshake insurance policies or state processing. For such circumstances, the ServerEndpointConfig.Configurator offers an possibility permitting you to create your individual implementation. You’ll be able to implement the next strategies to supply custom-made configurations:

◉ getNegotiatedSubProtocol(Checklist<String> supported, Checklist<String> requested): Permits a custom-made algorithm to find out the choice of the subprotocol that’s used

◉ getNegotiatedExtensions(Checklist<Extension> put in, Checklist<Extension> requested): Permits a custom-made algorithm to find out the choice of the extensions which are used

◉ checkOrigin(String originHeaderValue): Permits the specification of an origin-checking algorithm

◉ modifyHandshake(ServerEndpointConfig sec, HandshakeRequest req, HandshakeResponse res): Permits for modification of the handshake response that’s despatched again to the consumer

◉ getEndpointInstance(Class<T> endpointClass): Permits a custom-made implementation for the creation of an Endpoint occasion

The identical holds true for the ClientEndpoint.Configurator, in that the configurator permits for personalisation of some algorithms throughout the connection initialization part. You’ll be able to customise the configuration utilizing these two strategies:

◉ beforeRequest(Map<String, Checklist<String>> headers): Permits for the modification of headers earlier than a request is distributed

◉ afterResponse(HandshakeResponse res): Permits for the customization of the processing for a handshake response

Supply: oracle.com

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments