Explore Spring 4 Features: WebSocket (Part II)
Now for the phase II to be in action, a asynchronous task needs to be scheduled, which at regular intervals, with the help of a Scheduler would post messages to MessageBroker.When the client would connect to the MessageBroker over WebSocket, it would start receiving the messages.
Now, here we cannot use Spring Scheduling features i.e. @EnableScheduling or @EnableAsync, as when we use @EnableWebSocketMessageBroker, then Spring automatically configures two schedulers by default,and Spring 4 does not allow more than two Schedulers at a time.
To overcome this limitation, we are using an implementation of SchedulingConfigurer.In its implementation,
we are injecting a service. We will be calling a method of the service at regular interval, which will send messages to the MessageBroker.
The code for SchedulingConfigurer implementation is:
Now, when the client connects to the message broker over Websocket, it starts receiving all the messages from message broker
The client code is:
The client code consists of 3 parts.
1) connect()
2) sendName()
3) disconnect()
1) connect()
In this method we create an object of SockJS and uses that Object to create a stompClient to make a connection to the server.
But the question arises why first SockJS and then Stomp?
Web browsers supports different versions of the WebSocket protocol. Some older browsers do not support WebSocket protocol.Therefore to build a WebSocket application today, fallback options are required to simulate the WebSocket API where necessary. SockJS is such a fallback option.
We are creating a SockJS object passing in the URL of the WebSocket Server side endpoint we want to connect to (as configured in the SpringWebSocketConfig class. The goal of SockJS is to let applications use a WebSocket API but fall back to non-WebSocket alternatives when necessary at runtime, i.e.without any change in the application code.
The URL passed to SockJS consists of http://<<server>>:<<port>>/<<Context Root>>/<<suffix url extn>>(OPTIONAL)/<<registered stomp endpoint>>
Here, suffix url extn is the config,as the Dispatcher Servlet is mapped to /config/* & registered stomp endpoint is /hello as present in SpringWebSocketConfig
We are using here is the SockJS client API.The SockJS client begins by sending "GET /info" to obtain basic information from the server.Then it decides the underlying transport mechanism to be used upon (if the browser supports WebSocket, then WebSocket).
An important point needs to be mentioned here is that, at first the basic HTTP "GET /info" is sent to the server, then protocol upgradation takes place.
The WebSocket protocol defines two main types of messages text and binary but leaves their content undefined.Instead it’s expected that client and server may agree on using a sub-protocol, i.e. a higher-level protocol that defines the message content as WebSocket protocol is too lower level. Using a sub-protocol is optional but either way client and server both need to understand how to interpret messages.
STOMP is a simple messaging protocol .STOMP is a frame based protocol with frames modelled on HTTP.
Then we create the stomp client,using the SockJS object created.
The second parameter is the callback function for successful connection. we can see the parameter frame which is being passed as a parameter to the callback function by the system. Within this callback function we subscribe to various endpoints. The third parameter is the error callback function. The error reason is the parameter to this function, being passed by the system.
2) sendName()
In this method, we are using stompClient, to send the desired Object in JSON format. The Stomp API constructs proper object instance out of this JSON String and passes it to the Controller Method.
The second parameter is a JSON string which will be mapped to a model of Type Hello Message .
3) disconnect()
In this method, we disconnect the StompClient from the server.
Now, here we cannot use Spring Scheduling features i.e. @EnableScheduling or @EnableAsync, as when we use @EnableWebSocketMessageBroker, then Spring automatically configures two schedulers by default,and Spring 4 does not allow more than two Schedulers at a time.
To overcome this limitation, we are using an implementation of SchedulingConfigurer.In its implementation,
we are injecting a service. We will be calling a method of the service at regular interval, which will send messages to the MessageBroker.
The code for SchedulingConfigurer implementation is:
@Configuration @EnableScheduling public class SpringWebSchedulingConfig implements SchedulingConfigurer { @Autowired IMessageService messageService; public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { // TODO Auto-generated method stub scheduledTaskRegistrar.setTaskScheduler(taskScheduler()); scheduledTaskRegistrar.addFixedDelayTask(new Runnable() { public void run() { // TODO Auto-generated method stub messageService.sendMessage(); } }, 10000); } @Bean() public ThreadPoolTaskScheduler taskScheduler() { return new ThreadPoolTaskScheduler(); } }It is the configured taskScheduler i.e. ThreadPoolTaskScheduler which calls the service method at regular intervals,with the help of a runnable implementation.
Now, when the client connects to the message broker over Websocket, it starts receiving all the messages from message broker
The client code is:
alert('Connected: '+frame); stompClient.subscribe('/queue/myQueue.Queue', function(greeting){ alert(JSON.parse(greeting.body).content); });Now, lets explore the client code a little.
The client code consists of 3 parts.
1) connect()
2) sendName()
3) disconnect()
1) connect()
In this method we create an object of SockJS and uses that Object to create a stompClient to make a connection to the server.
But the question arises why first SockJS and then Stomp?
Web browsers supports different versions of the WebSocket protocol. Some older browsers do not support WebSocket protocol.Therefore to build a WebSocket application today, fallback options are required to simulate the WebSocket API where necessary. SockJS is such a fallback option.
We are creating a SockJS object passing in the URL of the WebSocket Server side endpoint we want to connect to (as configured in the SpringWebSocketConfig class. The goal of SockJS is to let applications use a WebSocket API but fall back to non-WebSocket alternatives when necessary at runtime, i.e.without any change in the application code.
The URL passed to SockJS consists of http://<<server>>:<<port>>/<<Context Root>>/<<suffix url extn>>(OPTIONAL)/<<registered stomp endpoint>>
Here, suffix url extn is the config,as the Dispatcher Servlet is mapped to /config/* & registered stomp endpoint is /hello as present in SpringWebSocketConfig
We are using here is the SockJS client API.The SockJS client begins by sending "GET /info" to obtain basic information from the server.Then it decides the underlying transport mechanism to be used upon (if the browser supports WebSocket, then WebSocket).
An important point needs to be mentioned here is that, at first the basic HTTP "GET /info" is sent to the server, then protocol upgradation takes place.
The WebSocket protocol defines two main types of messages text and binary but leaves their content undefined.Instead it’s expected that client and server may agree on using a sub-protocol, i.e. a higher-level protocol that defines the message content as WebSocket protocol is too lower level. Using a sub-protocol is optional but either way client and server both need to understand how to interpret messages.
STOMP is a simple messaging protocol .STOMP is a frame based protocol with frames modelled on HTTP.
Then we create the stomp client,using the SockJS object created.
stompClient = Stomp.over(socket);Once a STOMP client is created, it must call its connect() method to effectively connect and authenticate to the STOMP server.If successfully connected, then a frame is being returned in the success callback function, and once the connection is established,then the client subscribes to various endpoints, to receive messages.If the connection fails, then the error callback() function is invoked.
stompClient.connect({}, function(frame) { alert('Connected: '+frame); stompClient.subscribe('/queue/myQueue.Queue', function(greeting){ alert(JSON.parse(greeting.body).content); }); stompClient.subscribe('/queue/myQueue.queue', function(greeting){ alert("Second client:"+JSON.parse(greeting.body).content); }); },function(error) { alert("The error is:---->"+error); });The first parameter to the connect() method is empty, it expects username and password.
The second parameter is the callback function for successful connection. we can see the parameter frame which is being passed as a parameter to the callback function by the system. Within this callback function we subscribe to various endpoints. The third parameter is the error callback function. The error reason is the parameter to this function, being passed by the system.
2) sendName()
In this method, we are using stompClient, to send the desired Object in JSON format. The Stomp API constructs proper object instance out of this JSON String and passes it to the Controller Method.
stompClient.send("/app/hello1", {}, JSON.stringify({ 'name': 'DISCO' }));The first parameter to the send() method is the url of the controller endpoint we want to send the message to. here /app/hello1. /app is the application destination prefix as mentioned in SpringWebSocketConfig. and /hello1 is the request mapping URL for the controller method.Any request to any resource on the server through WebSocket should prepended by this prefix.
The second parameter is a JSON string which will be mapped to a model of Type Hello Message .
3) disconnect()
In this method, we disconnect the StompClient from the server.
stompClient.disconnect();This is in short about what I have explored on WebSocket. Any suggestions are always welcome.Please share your views and opinions.
Comments
Post a Comment