WebSocket with Spring boot and Angular

Angular featured image

1. Overview

WebSocket makes it possible to open an interactive communication between a browser (front-end) and a server (back-end).

It’s a two-way communication protocol that allows not only communication from the front-end to the back-end, but also from the back-end to the front-end as well.

In this article, I will show you how to use WebSockets in both Angular and Spring boot using SockJS, StompJS and Spring WebSocket.

This is an overview of how the final project will look like :

Web socket Spring boot Angular demo

  • A Spring boot application as the back-end that use Spring WebSocket to push notifications to a topic.
  • An Angular application as the front-end that use SockJS and StompJS to subscribe to the topic, consume notifications from it and displaying them in a simple html page.

2. Create back-end

2.1. Create Spring boot app

Generate a Spring boot project using Spring intializr, with Web and Websocket dependencies selected or add them manually to your pom.xml.

<!-- pom.xml -->
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-websocket</artifactId>
	</dependency>
</dependencies>

2.2. Implement WebSocket

1. Create a configuration Java class annotated with @EnableWebSocketMessageBroker to enable WebSockets.

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {
	
	@Override
	public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
		stompEndpointRegistry.addEndpoint("/socket")
				.setAllowedOrigins("*")
				.withSockJS();
	}

	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		registry.enableSimpleBroker("/topic");
		registry.setApplicationDestinationPrefixes("/app");
	}
}

2. Create a POJO class to hold the message to be shared between the back-end and the front-end.

public class Notifications {

    private int count;

    public Notifications(int count) {
        this.count = count;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public void increment() {
        this.count++;
    }
}

3. Create a web Controller and inject SimpMessagingTemplate bean in it.

Every time the Controller is called, the Notifications.count will be incremented by one and sent to the topic using SimpMessagingTemplate.convertAndSend() method.

@RestController
public class NotificationController {

    @Autowired
    private SimpMessagingTemplate template;

    // Initialize Notifications
    private Notifications notifications = new Notifications(0);

    @GetMapping("/notify")
    public String getNotification() {

        // Increment Notification by one
        notifications.increment();

        // Push notifications to front-end
        template.convertAndSend("/topic/notification", notifications);

        return "Notifications successfully sent to Angular !";
    }
}

3. Create front-end

3.1. Prepare Angular app

1. Create an Angular project using ng new command.

ng new websocket-front-end

2. Install StomJS and SockJS-client using npm install command.

npm install --save sockjs-client stompjs

3.2. Implement WebSocket

1. Create a service with name WebSocketService, using ng generate service command.

import {Injectable} from "@angular/core";

var SockJs = require("sockjs-client");
var Stomp = require("stompjs");

@Injectable()
export class WebSocketService {

    // Open connection with the back-end socket
    public connect() {
        let socket = new SockJs(`http://localhost:8080/socket`);

        let stompClient = Stomp.over(socket);

        return stompClient;
    }
}

Register the WebSocketService as a provider.

import {WebSocketService} from "./services/websocket.service";

@NgModule({
	...
	
	providers: [WebSocketService],
	
	....
})
export class AppModule { }

2. Inside the app.component.ts, open a connection with the back-end socket and subscribe to the notification topic.

import {Component} from '@angular/core';
import {WebSocketService} from "./services/websocket.service";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {

    public notifications = 0;

    constructor(private webSocketService: WebSocketService) {
	
		// Open connection with server socket
        let stompClient = this.webSocketService.connect();
        stompClient.connect({}, frame => {
			
			// Subscribe to notification topic
            stompClient.subscribe('/topic/notification', notifications => {
			
				// Update notifications attribute with the recent messsage sent from the server
                this.notifications = JSON.parse(notifications.body).count;
            })
        });
    }
}

3. Display the notifications attribute inside the app.component.html.

<div style="text-align:center; margin-top: 150px;">

    <h1 style="font-size: 4em;">

        Notifications : <span style="color: red;">+{{ notifications }}</span>

    </h1>

</div>

Find the source code of this example in GitHub.

4. Conclusion

Combining the power of WebSockets and Angular can allow you to create a very interactive web applications.

 

4.7 9 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

16 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
waqas_kamran
waqas_kamran
6 years ago

nice article . can i change port for web socket . means i want to use different ports for web socket and http rest

azza
azza
6 years ago

Hi i’m stuck with this error did you get the same error or do you have a clue on how to fix it please ?
“Failed to load http://localhost:8090/websocket-backend/socket/info?t=1528067934321: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. Origin ‘http://localhost:4200’ is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.”

Eric
Eric
6 years ago

Followed step by step and got this error:

ERROR in ../node_modules/stompjs/lib/stomp-node.js
Module not found: Error: Can’t resolve ‘net’ in ‘C:\…\node_modules\stompjs\lib’
i 「wdm」: Failed to compile.

I’m stuck with this messages. Any ideas for solving this?

Thanks.

Girish
Girish
Reply to  Eric
5 years ago

Im facing the same issue on angular 7 please help

JLASSI adnan
JLASSI adnan
Reply to  Girish
4 years ago

You can try this command : npm i net -S

Nag
Nag
6 years ago

Nice Article!! Thanks for putting together. Did you implement this in Hybris extensions?

Som
Som
5 years ago

ERROR in ./node_modules/stompjs/lib/stomp-node.js
Module not found

Kshitij
Kshitij
5 years ago

Very nice article. The demo works perfectly as well. Any ideas on how to send the notification to only a specific user though?

Girish
Girish
5 years ago

Seems like the over() method on stompjs s not supported anymore. Could you please verify

Girish Kumar Muniraju
Girish Kumar Muniraju
5 years ago

Thankyou ” Mouad EL Fakir “, for a great starter kit for StompJs, websocket with SpringBoot. It really helped me start on my project.I was able to get it running 🙂

RogerHeeby
RogerHeeby
4 years ago

I treasure the content on your web sites. Thanks a lot.

Dennisknons
Dennisknons
4 years ago

I simply want to say I am beginner to weblog and in fact savored you’re site . Most likely I’m want to bookmark your website. You definitely include great posts. Thanks a lot for revealing your blog site.

Omar Salem
Omar Salem
4 years ago

Thank you!

Zakaria Ahmmed
Zakaria Ahmmed
2 years ago

test

khaled noussari
khaled noussari
2 years ago

comment je peut décrémenter le nombre des notification par exemple si c’est déjà j’ai vue la notification

16
0
Would love your thoughts, please comment.x
()
x