Spring Reactive WebSocket Hot Publisher

2 minute read Published:

Web-Socket that utilizes the Reactive Hot-Publisher pattern.
Table of Contents

This Demo

This is the multi-casting Flux variation of the standard WebSocket Service seen here

WebSocket Server

Spring’s reactive [WebSocket] API is a part of Spring 5’s WebFlux API which bring reactive flow control to our projects via project reactor. We will introduce a single WebSocket handler, and show whats needed to get started using Spring’s WebSocketServer support.

You’ll want to start a new Spring project using start.spring.io[this link] to autogenerate a maven based POM. If you go with a different approach, just make sure to have webflux, and lombok projects.

First, wire in a WebSocketHandlerAdapter to handle our web socket handshake, upgrade, and other connection details.

socket_handler_adapter.

    @Bean
    WebSocketHandlerAdapter socketHandlerAdapter() {
        return new WebSocketHandlerAdapter();
    }

Next, create the WebSocket session handler. The simplest way to do this to use the functional interface for WebSocketHandler and implement it’s handle method to manage our stream response. In this, we will use the Flux.interval operator and push it’s output back to the session.

socket_session_handler.

    WebSocketHandler webSocketHandler(ConnectableFlux<String> publisher) {
        return session ->
                session.send(publisher.map(session::textMessage))
                        .doOnSubscribe(sub -> log.info(session.getId() + ".CONNECT"))
                        .doFinally(sig -> log.info(session.getId() + ".DISCONNECT"));
    }

We utilize the ConnectableFlux<String> to hot publish our tick data to websocket clients. That is, in contrast to the last demonstration which produced a cold published flow.

Finally, to map URI’s to our handler we wire in a reactive SimpleUrlHandlerMapping to delegate socket connections on URL /ws/feed.

uri_handler_mapping.

    @Bean
    HandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        RequestMappingHandlerMapping foo = new RequestMappingHandlerMapping();
        simpleUrlHandlerMapping.setUrlMap(Collections.singletonMap("/ws/feed",
                webSocketHandler()));
        simpleUrlHandlerMapping.setOrder(10);
        return simpleUrlHandlerMapping;
    }

Finally, we will execute this server app:

server_app_main.

    public static void main(String[] args) {
        SpringApplication.run(WebSocketConfiguration.class, args);
    }

Start the application:

$ mvn clean spring-boot:run
...
INFO 10671 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080

Now we are ready to implement the client, and demonstrate the new server we just stood up!

References/Readling List