Wednesday, 4 April 2018

Java web socket client example using tyrus client

In this post, I am going to show you, how can we connect to a websocket end point using a websocket client written in Java.

Lets devide the steps.
a.   Build websocket server endpoint
b.   Implement a websocket client and connect to the websocket server endpoint

Finally, web socket clients send some message to websocket server endpoint, and server receive the message, convert the message to upper case and send it back to client.

Build websocket server endpoint
Follow below step-by-step procedure to build websocket server endpoint in eclipse.

I am going to use below maven dependencies to build server end point.

                  <dependency>
                           <groupId>javax.websocket</groupId>
                           <artifactId>javax.websocket-api</artifactId>
                           <version>1.1</version>
                           <scope>provided</scope>
                  </dependency>

                  <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
                  <dependency>
                           <groupId>com.google.code.gson</groupId>
                           <artifactId>gson</artifactId>
                           <version>2.8.2</version>
                  </dependency>

Step 1: Create new dynamic web project ‘websocketServerDemo’ in eclipse.

Step 2: Mavenize the project ‘websocketServerDemo’. Right click on the project -> Configure -> Convert To Maven project.


Step 2: Update dependencies in pom.xml
pom.xml
<project 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>websocketServerDemo</groupId>
 <artifactId>websocketServerDemo</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <build>
  <sourceDirectory>src</sourceDirectory>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.3</version>
    <configuration>
     <source>1.8</source>
     <target>1.8</target>
    </configuration>
   </plugin>
   <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
     <warSourceDirectory>WebContent</warSourceDirectory>
     <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
   </plugin>
  </plugins>
 </build>

 <dependencies>
  <dependency>
   <groupId>javax.websocket</groupId>
   <artifactId>javax.websocket-api</artifactId>
   <version>1.1</version>
   <scope>provided</scope>
  </dependency>

  <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
  <dependency>
   <groupId>com.google.code.gson</groupId>
   <artifactId>gson</artifactId>
   <version>2.8.2</version>
  </dependency>

 </dependencies>
</project>

Step 3: Define package com.sample.model. Create a class Message in the package com.sample.model.
Message.java
package com.sample.model;

public class Message {

 private String secretMessage;

 public String getSecretMessage() {
  return secretMessage;
 }

 public void setSecretMessage(String secretMessage) {
  this.secretMessage = secretMessage;
 }

}

Step 3: Define package ‘com.sample.util’. Create a class JSONUtil.java.

JSONUtil.java
package com.sample.util;

import com.google.gson.Gson;


public class JSONUtil {
 private static Gson gson = new Gson();
 
 /**
  * @param obj
  * @return json string of this object.
  */
 public static String getJson(Object obj) {
  return gson.toJson(obj);
 }

 /**
  * Convert given json string to object.
  * 
  * @param json
  * @param obj
  * @return an object by populating properties with json data.
  */
 public static <T> T getObject(String json, Class<T> clazz) {
  return gson.fromJson(json, clazz);
 }

}

Step 4: Define package com.sample.encoders. Create MessageEncoder and MessageDecoder classes.


MessageEncoder.java
package com.sample.encoders;

import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
import com.sample.model.Message;

public class MessageEncoder implements Encoder.Text<Message> {

 @Override
 public void init(EndpointConfig config) {
  // TODO Auto-generated method stub
  
 }

 @Override
 public void destroy() {
  // TODO Auto-generated method stub
  
 }

 @Override
 public String encode(Message object) throws EncodeException {
  return com.sample.util.JSONUtil.getJson(object);
  //return null;
 }


   
}


MessageDecoder.java
package com.sample.encoders;

import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;

import com.sample.model.Message;
import com.sample.util.JSONUtil;


public class MessageDecoder implements Decoder.Text<Message> {

 @Override
 public void init(EndpointConfig config) {

 }

 @Override
 public void destroy() {

 }

 @Override
 public Message decode(String s) throws DecodeException {
  Message message = JSONUtil.getObject(s, Message.class);
  return message;
 }

 @Override
 public boolean willDecode(String s) {
  return true;
 }

}

Step 5: Define package ‘com.sample.endpoint’. Create class WebSocketServer.java.


WebSocketServer.java
package com.sample.endpoint;

import java.io.IOException;

import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import com.sample.encoders.MessageDecoder;
import com.sample.encoders.MessageEncoder;
import com.sample.model.Message;
import com.sample.util.JSONUtil;

@ServerEndpoint(value = "/connectToMe", encoders = MessageEncoder.class, decoders = MessageDecoder.class)
public class WebSocketServer {
 @OnOpen
 public void onOpen(Session session) {
  System.out.println("Session Opened");
 }

 @OnMessage
 public void onMessage(Message message, Session session) throws IOException, EncodeException {

  String secretMessage = message.getSecretMessage();
  String result = secretMessage.toUpperCase();
  
  Message resultMsg = new Message();
  resultMsg.setSecretMessage(result);
  
  session.getBasicRemote().sendText(JSONUtil.getJson(resultMsg));
 }

 @OnClose
 public void onClose(Session session) throws IOException, EncodeException {
  
 }

 @OnError
 public void onError(Throwable t) {
 }


}


Total project structure looks like below.
Implement websocket client
Step 1: Create new java maven project.

Right click on project explorer -> New -> other.

Search for maven.

Select ‘maven project’ and press Next button.

Select the check box ‘Create a simple project (skip archetype selection).

Give group id and artifact id as 'websocketClientDemo'

Click on Finish button.

Step 2: Update maven dependencies.
pom.xml
<project 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>websocketClientDemp</groupId>
 <artifactId>websocketClientDemo</artifactId>
 <version>0.0.1-SNAPSHOT</version>

 <dependencies>
  <!-- https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api -->
  <dependency>
   <groupId>javax.websocket</groupId>
   <artifactId>javax.websocket-api</artifactId>
   <version>1.1</version>
   <scope>provided</scope>
  </dependency>

  <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
  <dependency>
   <groupId>com.google.code.gson</groupId>
   <artifactId>gson</artifactId>
   <version>2.8.2</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/org.glassfish.tyrus.bundles/tyrus-standalone-client -->
  <dependency>
   <groupId>org.glassfish.tyrus.bundles</groupId>
   <artifactId>tyrus-standalone-client</artifactId>
   <version>1.9</version>
  </dependency>
 </dependencies>
</project>


Step 3: Define the classes JSONUtil, Message, MessageEncoder and MessageDecoder classes. Source code is same like the source code defined in Websocket server application.

Step 4: Define the package ‘com.sample.client’.  Create class WebSocketClient.

WebSocketClient.java
package com.sample.client;

import javax.websocket.ClientEndpoint;
import javax.websocket.OnMessage;

import com.sample.encoders.MessageDecoder;
import com.sample.encoders.MessageEncoder;
import com.sample.model.Message;

@ClientEndpoint(encoders = MessageEncoder.class, decoders = MessageDecoder.class)
public class WebSocketClient {


 @OnMessage
 public void onMessage(Message message) {

  String secretMsg = message.getSecretMessage();
  System.out.println("Message received is : " + secretMsg);

 }

}

Step 5: Define package com.sample.test, create class TestClient.java.


TestClient.java
package com.sample.test;

import org.glassfish.tyrus.client.ClientManager;

import java.io.IOException;
import java.net.*;

import javax.websocket.DeploymentException;

import com.sample.client.WebSocketClient;
import com.sample.model.Message;
import com.sample.util.JSONUtil;

public class TestClient {
 public static void main(String args[]) throws DeploymentException, IOException, URISyntaxException, InterruptedException{
  String server = "ws://localhost:8080/websocketServerDemo-0.0.1-SNAPSHOT/connectToMe";
  String secretMessage = "good morning";
  
  ClientManager client = ClientManager.createClient();
  // client.getProperties().put(ClientProperties.PROXY_URI, "http://proxy:8083/");

  javax.websocket.Session websocketSession = client.connectToServer(WebSocketClient.class, new URI(server));
  websocketSession.setMaxIdleTimeout(0);
  Message message = new Message();
  message.setSecretMessage(secretMessage);
  websocketSession.getBasicRemote().sendText(JSONUtil.getJson(message));
  
  while(true){
   Thread.sleep(2000);
  }

 }
}

Project structure looks like below.


Deploy the war file
Generate the war file.

Right click on the project -> Run As-> Maven Install.
Above step generates the war file. Deploy the war file to server. If you are using tomcat, copy the war file to webapps directory and start the server.

Once the application is deployed, run TestClient.java application, you can able to see the message ‘good morning’ in capital letters.




Prevoius                                                 Next                                                 Home

1 comment:

  1. Exception in thread "main" javax.websocket.DeploymentException: Handshake response not received.
    at org.glassfish.tyrus.client.ClientManager$3$1.run(ClientManager.java:655)
    at org.glassfish.tyrus.client.ClientManager$3.run(ClientManager.java:673)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.glassfish.tyrus.client.ClientManager$SameThreadExecutorService.execute(ClientManager.java:826)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:496)
    at org.glassfish.tyrus.client.ClientManager.connectToServer(ClientManager.java:312)
    at com.renault.rpSimulator.RPsimulator.webSocketEndPoint.TestClient.main(TestClient.java:24)

    Process finished with exit code 1

    any idea ?

    ReplyDelete