Spring MVC 5 - Handling WebSocket message example

Posted on February 25, 2018


The WebSocket protocol is a computer communication protocol, standardized by the IETF as RFC 6455. It provides a full-duplex, two-way communication channel between client and server over a single TCP connection.

The Spring framework provides a WebSocket API that can be used to write client and server side applications that handle WebSocket messages.

This post shows you how to configure the WebSocket API to handler the WebSocket message in Spring MVC application. 

Tools and technologies used for this example are -

  • Spring MVC 5.0.3.RELEASE
  • Spring WebSocket 5.0.3.RELEASE
  • Servlet API 4.0.0
  • Java SE 9
  • Maven 3.5.2
  • Jetty Maven plugin 9.4.8
  • Eclipse Oxygen.2 Release (4.7.2)

Project structure

Final project structure of our application will look like as follows.

spring-mvc-websocket.png

Related - How to create a web project using maven build tool in eclipse IDE.

Jar dependencies

Edit pom.xml file of your maven project and add the following jars dependencies in your in it.

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>com.boraji.tutorial.spring</groupId>
   <artifactId>spring-mvc-websocket-example</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>Spring MVC - WebSocket example</name>
   <properties>
      <failOnMissingWebXml>false</failOnMissingWebXml>
      <maven.compiler.source>9</maven.compiler.source>
      <maven.compiler.target>9</maven.compiler.target>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>5.0.3.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-websocket</artifactId>
         <version>5.0.3.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>javax.servlet-api</artifactId>
         <version>4.0.0</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>javax.servlet.jsp</groupId>
         <artifactId>javax.servlet.jsp-api</artifactId>
         <version>2.3.2-b02</version>
         <scope>provided</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>9.4.8.v20171121</version>
         </plugin>
      </plugins>
   </build>
</project>

Creating WebSocket Handler

To handle the WebSocket message, first you need to create a WebSocket handler class (i.e. WebSocket server) by extending either TextWebSocketHandler or BinaryWebSocketHandler class.

MyWebSocketHandler.java

package com.boraji.tutorial.spring.websocket;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
public class MyWebSocketHandler extends TextWebSocketHandler {

   @Override
   protected void handleTextMessage(WebSocketSession session, TextMessage message)
         throws Exception {

      String clientMessage = message.getPayload();

      if (clientMessage.startsWith("Hello") || clientMessage.startsWith("Hi")) {
         session.sendMessage(new TextMessage("Hello! What can i do for you?"));
      } else {
         session.sendMessage(
               new TextMessage("This is a simple hello world example of using Spring WebSocket."));
      }
   }
}

 

WebSocket Configuration and Registering WebSocket Handler

After creating a WebSocket handler class, create a @Configuration class by implementing the WebSocketConfigurer interface.

Annotate WebSocket configuration class with @EnableWebSocket annotation to process the WebSocket requests.

Register your WebSocket handler class in overridden method registerWebSocketHandlers() of the WebSocketConfigurer interface as follows.

WebSocketConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import com.boraji.tutorial.spring.websocket.MyWebSocketHandler;

@Configuration
@EnableWebSocket
@ComponentScan("com.boraji.tutorial.spring.websocket")
public class WebSocketConfig implements WebSocketConfigurer {

   @Autowired
   private MyWebSocketHandler myWebSocketHandler;

   @Override
   public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
      registry.addHandler(myWebSocketHandler, "/socketHandler");
   }

}

Spring MVC Configuration

Create a web @Configuration class annotated with @EnableWebMvc annotation and and set appropriate prefix and suffix for JSP view resolver in configureViewResolvers() method as follows.

MvcWebConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
@ComponentScan("com.boraji.tutorial.spring.controller")
public class MvcWebConfig implements WebMvcConfigurer {

   @Override
   public void configureViewResolvers(ViewResolverRegistry registry) {
      registry.jsp("/WEB-INF/views/", ".jsp");
   }
}

Servlet Container Initialization and Configuration

Create a container initializer class by extending the AbstractAnnotationConfigDispatcherServletInitializer class and specify MvcWebConfig and WebSocketConfig classes as follows.

MvcWebApplicationInitializer.java

package com.boraji.tutorial.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class MvcWebApplicationInitializer
      extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return null;
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { MvcWebConfig.class, WebSocketConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }

}

In Spring MVC, The DispatcherServlet needs to be declared and mapped for processing all requests either using java or web.xmlconfiguration.

In a Servlet 3.0+ environment, you can use AbstractAnnotationConfigDispatcherServletInitializer class to register and initialize the DispatcherServlet programmatically.

Controller class

Create a simple @Controller class under com.boraji.tutorial.spring.controller package as follows. 

MyContoller.java

package com.boraji.tutorial.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MyController {

   @GetMapping("/")
   public String index() {
      return "index";
   }
}

JSP View

Create an index.jsp file under src\main\webapp\WEB-INF\views folder as follows.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>BORAJI.COM</title>
<script type="text/javascript">
	//Open the web socket connection to the server
	var socketConn = new WebSocket('ws://localhost:8080/socketHandler');

	//Send Message
	function send() {
		var clientMsg = document.getElementById('clientMsg');
		if (clientMsg.value) {
			socketConn.send(clientMsg.value);
			clientMsg.value = '';
		}
	}

	// Recive Message
	socketConn.onmessage = function(event) {
		var serverMsg = document.getElementById('serverMsg');
		serverMsg.value = event.data;
	}
</script>
</head>
<body>
   <h1>Spring MVC 5 + WebSocket + Hello World example</h1>
   <hr />
   <label>Message</label>
   <br>
   <textarea rows="8" cols="50" id="clientMsg"></textarea>
   <br>
   <button onclick="send()">Send</button>
   <br>
   <label>Response from Server</label>
   <br>
   <textarea rows="8" cols="50" id="serverMsg" readonly="readonly"></textarea>
</body>
</html>

 

Run application

Use the following maven command to run your application.

mvn jetty:run (This command deploy the webapp from its sources, instead of build war).

Enter the http://localhost:8080 URL in browser's address bar to test the WebSocket configuration.

spring-mvc-websocket_01.png

 

Download Sources