5 minutes with – WebSocket

Build interactive Web Application by using relative new technologies as WebSocket can improve the user experience in the 2.0 Web World.

Let’s have a look at how to get it by adopting Browser WebSocket using Spring Framework.

Finally I got a little time to write this article that I think it’s quite easy and can be inspiration for a lot of different applications.

Interactive Web Application is the “standard” in Web 2.0. We’ve already got Ajax, Jquery, backbones and a lot of others client frameworks that help us to achieve the aim of provide a better interaction between the client and the server.

Why WebSokect? The answer is, especially, due to the interaction between the client and the server. It’s not a common pooling process made by the client but, rather, a subscription process.

The protocol which made it available is named STOMP (Simple or Streaming Text Oriented Message Protocol from Wikipedia definition).

It’s a protocol built over Http protocol and it’s supported by these browsers (https://en.wikipedia.org/wiki/WebSocket#Browser_implementation)

Now; introducing the example, I’m going to replicate the Jmx Monitor for a Tomcat Web Server (not very original idea but useful for my aim).

I’m going to use Spring WebSocket that’s available here. The main actors are endpoints and brokers. It’s very close to Jms dispatcher concept, so, if you’re habit to this you’ll have no problem to get these concepts.

The main project file is the spring configuration file; nowadays a lot of Spring samples have a configuration properties inside the class file. I keep on preferring to use xml file to define the Spring configuration, at least, for the sample.

<websocket:message-broker application-destination-prefix="/monitor">
  <websocket:stomp-endpoint path="/jvm">
    <websocket:sockjs/>
  </websocket:stomp-endpoint>
  <websocket:simple-broker prefix="/topic"/>
</websocket:message-broker>

A broker named “/topic” with an endpoint named “/jvm” is configured in order to send the message.

The message will be sent by a trigger defined as task scheduled

<task:scheduled-tasks scheduler="myScheduler">
<task:scheduled ref="monitorController" method="fireHeapMemoryUsage" fixed-delay="5000" />
</task:scheduled-tasks>

<task:scheduler id="myScheduler"/>

And the method fireHeapMemoryUsage is defined in this Spring @Controller


@Controller("monitorController")
public class MonitorController {

@Autowired
private SimpMessagingTemplate template;

@Autowired
private JmxProxy proxy;

public void fireHeapMemoryUsage() throws MessagingException,
AttributeNotFoundException, InstanceNotFoundException,
MalformedObjectNameException, MBeanException, ReflectionException,
IOException {

System.out.println("Fire!");

this.template.convertAndSend("/topic/HeapMemoryUsage",
new JvmAttribute(proxy.getHeapMemoryUsage()));
}
}

A message is sent at the endpoint /topic/HeapMemoryUsage containing the Jvm Heap Memory used.

The component to access the Jmx attributes is the following


public class JmxProxy {

private JMXConnector jmxc;

public JmxProxy(String url) throws IOException, AttributeNotFoundException, InstanceNotFoundException, MalformedObjectNameException, MBeanException, ReflectionException
{
JMXServiceURL jmxUrl = new JMXServiceURL(url);
jmxc = JMXConnectorFactory.connect(jmxUrl);
}

public String getHeapMemoryUsage() throws AttributeNotFoundException, InstanceNotFoundException, MalformedObjectNameException, MBeanException, ReflectionException, IOException
{
Object o = jmxc.getMBeanServerConnection().getAttribute(
new ObjectName("java.lang:type=Memory"), "HeapMemoryUsage");
CompositeData cd = (CompositeData) o;

return cd.get("used").toString();
}
}

The list of Jmv attributes available over Jmx is here.

The client side is built by using sockjs library.

</pre>

<html>
<head>
<title>Jvm Monitor</title>
<script src="sockjs-0.3.4.js"></script>
<script src="stomp.js"></script>
<script src="//www.chartjs.org/assets/Chart.min.js"></script>

<script type="text/javascript">
var stompClient = null;

var currentdate = new Date();
var datetime = currentdate.getDate() + "/"
+ (currentdate.getMonth()+1)  + "/"
+ currentdate.getFullYear() + " "
+ currentdate.getHours() + ":"
+ currentdate.getMinutes() + ":"
+ currentdate.getSeconds();

function connect() {
var canvas = document.getElementById('updating-chart'),
ctx = canvas.getContext('2d'),
startingData = {
labels: [datetime, datetime],
datasets: [
{
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
data: [0, 0]
}
]
},
latestLabel = startingData.labels[6];

// Reduce the animation steps for demo clarity.
var myLiveChart = new Chart(ctx).Line(startingData, {animationSteps: 15});
var socket = new SockJS('/SpringWebSocket/jvm');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/HeapMemoryUsage', function(jvmValue){

var div = Math.floor(JSON.parse(jvmValue.body).value/1000000);

var currentdate = new Date();
var datetime = currentdate.getDate() + "/"
+ (currentdate.getMonth()+1)  + "/"
+ currentdate.getFullYear() + " "
+ currentdate.getHours() + ":"
+ currentdate.getMinutes() + ":"
+ currentdate.getSeconds();

// Add two random numbers for each dataset
myLiveChart.addData([div], datetime);

console.log('Lenght: ' + myLiveChart.datasets[0].points.length);

// Remove the first point so we dont just add values forever
if (myLiveChart.datasets[0].points.length>6)
myLiveChart.removeData();

});
});
}

</script>
</head>
<body onload="connect()">
<div>
<div>
<canvas id="updating-chart" width="500" height="300"></canvas>
</div>
</div>

</body>
</html>

ChartJs gives a better look & feel at the page, it’s not a dependency of sockjs library.

Summarizing, the sequence diagram that illustrates the interaction between the client and the server.

Web Socket

And the web page

websocketpage

That’s all.

I hope you can get some inspiration from this sample, I think it’s worth spend some hours to look inside this technology. I don’t have a lot of experience on this topic but I think it could be a valid choice among the client/server interaction framework.

I’ve posted the solution source code on github https://github.com/MarcoGhise/SpringWebSocketMonitor. I’m quite a newbie, please report me any problem

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s