0

This is my requirement

  1. In my application Spring-mvc is internally hitting the rest api and fetching data from the dependent system(time consuming operation). I would like to monitor this server side event from JSP page
  2. I would like to have timer/progress bar for the rest-api search triggered by spring.
İsmail Y.
  • 3,579
  • 5
  • 21
  • 29

1 Answers1

0

in this case you can use the WebSocket and STOMP protocol for fulfill your requirement.

WebSocket

WebSocket is a bi-directional connection between user's browser and server. for more info about WebSocket.

STOMP Protocol

STOMP is a simple (or streaming) text orientated messaging protocol for working with message-oriented middleware. for more info about STOMP

difference between WebSocket and STOMP protocol, please refer Nitin Kamate answer.

in this answer, used the SockJS and stopmjs to create a WebSocket and communication protocol in spring application.

SockJS

SockJS is a java script library for use to create WebSocket. for more info about SockJS and you can download sockjs.min.js file from here.

stompjs

stompjs is a java script library for provides a STOMP over WebSocket client for web browser. for more info about stompjs and you can download stomp.min.js file from here.

you should download the sockjs.min.js and stomp.min.js files and add these java script files into your project and need to add WebSocket library dependancy.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>x.x.x</version>
</dependency>

firstly config the WebSocket in servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:websocket="http://www.springframework.org/schema/websocket"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/websocket
    https://www.springframework.org/schema/websocket/spring-websocket.xsd">

    <websocket:message-broker application-destination-prefix="/app">
        <websocket:stomp-endpoint path="/portfolio"/>
            <websocket:sockjs/>
        </websocket:stomp-endpoint>
        <websocket:stomp-broker-relay prefix="/topic"/>
    </websocket:message-broker>

</beans>
  • application-destination-prefix is used as prefix to massage mapping
  • path - use the http://localhost:8080/portfolio url connect to WebSocket
  • prefix is used as prefix to STOMP destination

then build the WebSocket client as follows,

in this example, we send the some value to destination from server side controller

AppController.java

@Controller
public class AppController {

    @Autowired
    private SimpMessagingTemplate template; //provide methods for sending messages to a user

    @RequestMapping(value = "/event")
    public void getValue() throws InterruptedException{
        for (int i = 0; i < 100; i++) { //in this example, used for loop to generate a value in iteration
            this.template.convertAndSend("/topic/number", i); //send the value of i to destination through WebSocket
            Thread.sleep(1000); //added a delay to every round in for loop
        }
    }
}

JavaScript (SockJS) client for receiving value send by server side (java) event. (additionally used the angular library for handle the frontend. tutorial for angular js)

app.js

var mainApp = angular.module("mainApp", []);
     
mainApp.controller('appController', function($scope, $http) {

    $scope.progress = 0; // variable declared by angular for store the value return by java
    var socket = new SockJS('/Your_Application_Name/portfolio'); //create a new SockJS WebSocket
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        stompClient.subscribe('/topic/number', function (value) {
        $scope.progress=value.body; //assigned value to progress variable
        $scope.$apply();
    });

    $scope.startEvent = function() { // this function call the getValue() function in controller
        $http.post('event').then(function(value) {

        }, function(reason) {
        
        }, function(value) {
        
        })
    }
}
});

following jsp file included with button and progress bar. use the button for start the server side event (in this example, button called getValue() function in AppController.java through angular js. additionally used bootstrap framework for create the frontend. tutorial for bootstrap)

index.jsp

<html>
   <head>
      <link rel="stylesheet" href="resources/css/bootstrap.min.css">
      <script type="text/javascript" src="resources/js/jquery.min.js"></script>
      <script type="text/javascript" src="resources/js/sockjs.min.js"></script>
      <script type="text/javascript" src="resources/js/stomp.min.js"></script>
      <script type="text/javascript" src="resources/js/bootstrap.min.js"></script>
      <script type="text/javascript" src="resources/js/angular.min.js"></script>
      <script type="text/javascript" src="resources/js/app.js"></script>
   </head>
   
   <body ng-app="mainApp" ng-controller="appController">
      <div class="container">
         <div class="progress  mb-3">
            <div class="progress-bar" role="progressbar" ng-style="{width: progress + '%'}" aria-valuenow="{{progress}}" aria-valuemin="0" aria-valuemax="100">{{progress}}%</div>
            <!--progress variable used for set value to progress bar-->
         </div>
         <button type="button" class="btn btn-outline-secondary btn-sm" ng-click="startEvent()">Start Event</button>
         <!--click event of above button call to startEvent() function in app.js file-->
      </div>
   </body>
</html>

please refer spring documentation for more details about WebSocket, Spring WebSocket from here.

Lakshan
  • 1,404
  • 3
  • 10
  • 23