Home  >  Spring 4

Spring 4 WebSocket + SockJS + STOMP + Tomcat Example

By Arvind Rai, September 20, 2014
This page provides the description and example of Spring 4 WebSocket. Spring 4 has introduced the WebSocket API using which a browser and web server can communicate over WebSocket protocol. In this way, we can create a highly interactive UI and Online Games which needs quick response from the server. Higher version of browser supports WebSocket protocol. To describe WebSocket, I am creating a simple calculation application. SockJS provides the WebSocket like object on UI. STOMP client is being used to communicate over WebSocket protocol. I am using tomcat server to deploy the project. Find the diagram which displays the WebSocket Communication.
Spring 4 WebSocket  + SockJS + STOMP + Tomcat Example

WebSocket Protocol

WebSocket is a protocol which communicates between browser and web server. WebSocket works over TCP protocol. It opens a socket connection between browser and web server and start communication. WebSocket embeds sub protocol easily. In our example we are using STOMP over WebSocket .

SockJS

SockJS is a java script library which provides websocket like object for browsers. SockJS provides cross browser compatibility and supports STOMP protocol to communicate with any message broker. SockJS works in the way that we need to provide URL to connect with message broker and then get the stomp client to communicate.

STOMP Protocol

STOMP is Streaming Text Oriented Messaging Protocol. A STOMP client communicates to a message broker which supports STOMP protocol. STOMP uses different commands like connect, send, subscribe, disconnect etc to communicate.

Software Used for the Example

Below software are being used to run the Spring 4 WebSocket Example.
1. JDK 8
2. Spring 4 WebSocket
3. sockjs-0.3.4.js
4. stomp.js
5. Tomcat 8
6. Eclipse
7. Firefox 46.0.1
8. Gradle

Project Configuration in Eclipse

Find the eclipse screen shot which shows the project configuration of our calculation application example.
Spring 4 WebSocket  + SockJS + STOMP + Tomcat Example

Java Configuration to Support Spring 4 WebSocket

We are using two configuration class one for WebSocket configuration and another for Spring MVC. Find the WebSocket configuration.
AppWebSocketConfig.java
package com.concretepage.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
public class AppWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		config.enableSimpleBroker("/topic");
		config.setApplicationDestinationPrefixes("/calcApp");
	}
	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/add").withSockJS();
	}
} 
Now check the Spring MVC configuration. We have imported WebSocket Configuration here.
AppWebConfig.java
package com.concretepage.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
@Configuration 
@ComponentScan("com.concretepage") 
@EnableWebMvc
@Import({ AppWebSocketConfig.class })
public class AppWebConfig extends WebMvcConfigurerAdapter {
    @Bean  
    public UrlBasedViewResolver setupViewResolver() {  
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();  
        resolver.setPrefix("/jsp/");  
        resolver.setSuffix(".jsp");  
        resolver.setViewClass(JstlView.class);  
        return resolver;  
    }
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
	registry.addResourceHandler("/resources/**").addResourceLocations("/js/");
    }
} 

@EnableWebSocketMessageBroker Annottaion

EnableWebSocketMessageBroker has been introduced in Spring 4. EnableWebSocketMessageBroker annotation enables a configuration class to support WebSocket. This annotation supports message broker.

AbstractWebSocketMessageBrokerConfigurer

AbstractWebSocketMessageBrokerConfigurer has been introduced in Spring 4. This class is extended by WebSocket Configuration class. We need to implement two methods of this class configureMessageBroker() and registerStompEndpoints().

MessageBrokerRegistry

MessageBrokerRegistry has been introduced in Spring 4. This class helps to register message broker. We can enable simple broker for topic and queue conventionally.
topic : Use topic when there are more than one subscribers for a message.
queue : Use queue for peer to peer communication.
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/calcApp"); 
In our Calculation application, we have enabled topic broker. And we need to define an application destination name using which browser and server will communicate over WebSocket. Here we have defined calcApp

StompEndpointRegistry

StompEndpointRegistry has been introduced in Spring 4. StompEndpointRegistry register an end point for the STOMP over WebSocket. Check the below code snippet.
registry.addEndpoint("/add").withSockJS(); 
StompEndpointRegistry adds end point for STOMP communication. And enables SockJS. In this way STOMP client will send the message via the URL /calcApp/add

Controller class for WebSocket Comunication

In our Spring MVC controller class, there is two method. One is used to connect using HTTP protocol i.e start() and another method is addNum() which will run over WebSocket protocol. Their URL pattern is like ws: for regular and wss: for secure connection
WebSocketController.java
package com.concretepage.controller;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.concretepage.vo.CalcInput;
import com.concretepage.vo.Result;
@Controller
public class WebSocketController {
    @MessageMapping("/add" )
    @SendTo("/topic/showResult")
    public Result addNum(CalcInput input) throws Exception {
        Thread.sleep(2000);
        Result result = new Result(input.getNum1()+"+"+input.getNum2()+"="+(input.getNum1()+input.getNum2())); 
        return result;
    }
    @RequestMapping("/start")
    public String start() {
        return "start";
    }
} 

@MessageMapping Annotation

@MessageMapping annotation has been introduced in Spring 4. The method annotated with @MessageMapping works for WebSocket protocol communication. This defines the URL mapping. In our example add is URL pattern for WebSocket Comunication.

@SendTo Annotation

@SendTo has been introduced in Spring 4. Once the request has reached to server over WebSocket, a calculation or any business logic is performed on the data and result is prepared. Now we need the URL pattern where the result will be sent and for this task @SendTo comes into picture. @SendTo defines a URL pattern to send result. In our example we have URL pattern as /topic/showResult .

Web Application Initializer Class

Find the web application initializer class that supports servlet web.xml configuration and no need to use web.xml.
WebAppInitializer.java
package com.concretepage.initializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import com.concretepage.config.AppWebConfig;
public class WebAppInitializer implements WebApplicationInitializer {
   public void onStartup(ServletContext servletContext) throws ServletException {  
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        ctx.register(AppWebConfig.class);  
        ctx.setServletContext(servletContext);    
        Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
        dynamic.addMapping("/");  
        dynamic.setLoadOnStartup(1);  
   }  
}  

Value Object to Communicate with JSON Data

We have two value object, one for request data and second for response data. Find the class to get JSON data from request.
CalcInput.java
package com.concretepage.vo;
public class CalcInput {
    private int num1;
    private int num2;
	public int getNum1() {
		return num1;
	}
	public void setNum1(int num1) {
		this.num1 = num1;
	}
	public int getNum2() {
		return num2;
	}
	public void setNum2(int num2) {
		this.num2 = num2;
	}    
} 
Find the class to send JSON data as an response.
Result.java
package com.concretepage.vo;
public class Result {
    private String result;
    public Result(String result) {
        this.result = result;
    }
    public String getResult() {
	return result;
    }
} 

An Interactive UI using WebSocket Communication

We have a UI that has button to connect and disconnect and two input text to get number. Result is also displayed here getting from server. UI is using two JS library sockjs-0.3.4.js and stomp.js.
start.jsp
<!DOCTYPE html>
<html>
<head>
    <title>Calculator App Using Spring 4 WebSocket</title>
    <script src="resources/sockjs-0.3.4.js"></script>
    <script src="resources/stomp.js"></script>
    <script type="text/javascript">
        var stompClient = null; 
        function setConnected(connected) {
            document.getElementById('connect').disabled = connected;
            document.getElementById('disconnect').disabled = !connected;
            document.getElementById('calculationDiv').style.visibility = connected ? 'visible' : 'hidden';
            document.getElementById('calResponse').innerHTML = '';
        }
        function connect() {
            var socket = new SockJS('/Spring4WebSocket/add');
			stompClient = Stomp.over(socket);
            stompClient.connect({}, function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/showResult', function(calResult){
                	showResult(JSON.parse(calResult.body).result);
                });
            });
        }
        function disconnect() {
            stompClient.disconnect();
            setConnected(false);
            console.log("Disconnected");
        }
        function sendNum() {
            var num1 = document.getElementById('num1').value;
            var num2 = document.getElementById('num2').value;
            stompClient.send("/calcApp/add", {}, JSON.stringify({ 'num1': num1, 'num2': num2 }));
        }
        function showResult(message) {
            var response = document.getElementById('calResponse');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            p.appendChild(document.createTextNode(message));
            response.appendChild(p);
        }
    </script>
</head>
<body>
<noscript><h2>Enable Java script and reload this page to run Websocket Demo</h2></noscript>
<h1>Calculator App Using Spring 4 WebSocket</h1>
<div>
    <div>
        <button id="connect" onclick="connect();">Connect</button>
        <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button><br/><br/>
    </div>
    <div id="calculationDiv">
        <label>Number One:</label><input type="text" id="num1" /><br/>
        <label>Number Two:</label><input type="text" id="num2" /><br/><br/>
        <button id="sendNum" onclick="sendNum();">Send to Add</button>
        <p id="calResponse"></p>
    </div>
</div>
</body>
</html> 

Gradle for Spring 4 WebSocket Application

Find the gradle script for JAR dependency.
build.gradle
buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-release" }
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
apply plugin: 'war'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenLocal()
    mavenCentral()
    maven { url "http://repo.spring.io/libs-release" }
}
bootRepackage {
    enabled false
}
dependencies {
    compile("org.springframework.boot:spring-boot-starter-websocket")
    compile("org.springframework:spring-messaging")
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
    compile 'jstl:jstl:1.2'
} 

Run Application

Find the steps to run the calculation application.
1. Download source code and go to root project using command prompt.
2. Run gradle clean build
3. Deploy WAR in tomcat.
4. Access URL http://localhost:8080/Spring4WebSocket/start
5. Click on connect.
6. Enter number in text fields to add.
7. Click on Send Button.
8. After some time result is displayed.
Spring 4 WebSocket  + SockJS + STOMP + Tomcat Example

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS
comments powered by Disqus


Copyright ©2017 concretepage.com, all rights reserved |Privacy Policy | Contact Us