Enterprise Java

Websockets with Spring 4

I am throwing the entire kitchen sink into a small web application that I am developing as part of this post – Spring Boot, Spring Integration, RabbitMQ and finally the topic of the post, the Websocket support in Spring MVC with Spring 4.

Real-time quake listing application

The final app will list the earthquake occurrences around the world and is updated in realtime(if a minute can be considered realtime enough), along these lines:
 
 
 
 
 
Screen Shot 2014-03-08 at 12.13.08 AM

Storing the Quake Information

The first part of the application is polling the data from USGS Earthquake hazards program every minute and storing it. I have chosen to store it directly into a RabbitMQ topic, which will be later used for the Websockets integration. Spring Integration is a great fit for the requirements of such a feature – using just configuration I can poll the USGS service providing a json feed of this information and write it to a RabbitMQ topic. This is how this flow looks:

quakepolling

and a raw complete Spring integration flow for the same is the following, the only code missing here is the configuration for rabbitmq which is part of another configuration file:

<import resource="rabbit-context.xml"/>
 <int:inbound-channel-adapter channel="quakeinfotrigger" expression="''">
  <int:poller fixed-delay="60000"></int:poller>
 </int:inbound-channel-adapter>

 <int:channel id="quakeinfo"/>

 <int:channel id="quakeinfotrigger"></int:channel>

 <int-http:outbound-gateway id="quakerHttpGateway"
     request-channel="quakeinfotrigger"
     url="http://earthquake.usgs.gov/earthquakes/feed/geojson/all/hour"
     http-method="GET"
     expected-response-type="java.lang.String"
     charset="UTF-8"
     reply-channel="quakeinfo">
 </int-http:outbound-gateway>

 <int-amqp:outbound-channel-adapter amqp-template="amqpTemplate" channel="quakeinfo" />

So, now that I have a flow which collects the Earthquake information and stores it into a RabbitMQ topic called “amq.topic” and internally plugs in a routing key of “quakes.all” to each of the quake information message, the next step is to figure out how to show this information dynamically on the browser application.

Presenting the Quake information

Spring Framework 4.0+ makes it easy to develop the web part of the application with the Websocket based messaging support now built into the framework. Spring 4.0 uses the STOMP as higher level protocol over raw websockets – I have included references which provide much more clarity on the details of the Websocket support.

In essence, Spring will act as a intermediary for the browser to subscribe to the RabbitMQ quakes topic and display realtime information as new quake information flows in, this diagram from the references sums this up well:

Full-Featured-Message-Broker

Spring 4 Websockets support with an external broker requires the broker to support STOMP protocol, which is easy to enable with RabbitMQ. With the STOMP support in RabbitMQ in place, the Spring MVC configuration looks like this:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

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

 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
  registry.addEndpoint("/quakesep").withSockJS();
 }
}
  • “/topic” is being registered as a endpoint where Spring acts as a gateway to the RabbitMQ STOMP support
  • “/app” is the application prefix where Spring MVC will listen for browser requests encoded within the STOMP message frame, in this specific instance I am not getting any requests from the UI and so this endpoint is not really used
  • “/quakesep” is the websocket endpoint

This is all that is required on the server side!

Now for the client to subscribe to the message in the RabbitMQ topic, I have implemented it along the lines of the sample in one of the reference articles. The sample uses sockjs client, a javascript library for websocket emulation in browsers.

This is how the javascript code to connect to the websocket endpoint “/quakesep” and subscribing to the “/topic/quakes.all” endpoint looks like. This internally registers a temporary queue with RabbitMQ for this websocket session and maps a AMQP routing key of “quakes.all” to this temporary queue, in essence sending all the quake messages to the temporary queue for the session.

function connect() {
      var socket = new SockJS('/quakesep');
      stompClient = Stomp.over(socket);
      stompClient.connect({}, function(frame) {
          console.log('Connected: ' + frame);
          stompClient.subscribe('/topic/quakes.all', function(message){
              showQuakeInfo(message.body);
          });
      });
  }

the showQuakeInfo function above simply displays fresh quake information when available from RabbitMQ.

springwebsockets

The entire sample was put together with Spring Boot, this has ensured that the dependencies declared in the pom file is kept to a bare minimum, the amount of configuration to start up the application is surprisingly small – essentially the WebSocketConfig code that I displayed above!

Resources

  1. Websocket architecture in Spring Framework
  2. Webinar on building Websocket based applications using Spring Framework

 

Reference: Websockets with Spring 4 from our JCG partner Biju Kunjummen at the all and sundry blog.
Subscribe
Notify of
guest

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

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
user23
user23
10 years ago

Hi. I’m newbie in Spring 4 websockets and trying to learn your post. I’m trying to run the sample code, but I’m having error. Connection refused. ? What should I do to run it properly?. Btw nice post. Thank you so much.

Ken dG
Ken dG
10 years ago

Hi!. Thanks for this. Great post. I just have one question, Is it efficient to use this technology for creating multiplayer games?

Back to top button