Blog

pastedImage_0

Hacking SAP HANA Web Sockets

Disclaimer: This is not a production or documented feature – its also more of a hijack than a hack 

 

I have been hoping for the inclusion of Websocket support on the HANA DB platform for a while now, and I was a little disappointed it was not packaged in the SPS08 release. My goal when building apps (or products) is to make use of the core platform its running on as much as possible, I firmly believe that when convincing an IT department, or company, to implement a product or app, the first question is: “How much infrastructure does this need?”. This can often be a deal breaker and why I am such a big proponent of the HANA’s DB + XS App Server integration – it consolidates the requirements into a single investment. Having a Websocket technology built directly in XS can be an additional selling point which developers are starting to expect these days.

A little while ago I wrote a blog post on building a dashboard using the awesome Node.js package from Holger Koser, however I have really been wanting to use Websockets in the metric² platform since the get go. Some comments here and here are prime examples of my long lasting hope of seeing the technology being included in the XS Engine platform sooner rather than later. I recently had a little nudge again from John Patterson to dig back into the topic and did manage to hack something together. The most interesting part of this was that once I had it working, I was left wanting just a little more …

Firstly a little bit about Websockets and why I feel they important to the app/web development world …

Real-time: In the age of having blazingly fast DB’s, we need a UI & server side (In our case XSJS files) integration layer which can display the data to user with as little over head as possible. Web Sockets supports this by providing a low-latency, near real-time connection between a client and the server.

Light Weight: Currently we need to do multiple AJAX calls to our backend server (to the XSJS files) to either perform some complex logic or DML against our database. This is slow and also fairly network intensive as each request (and response) requires additional handshakes and the packet size is considerably larger than just the intended content inside the package. In Web sockets, the requests and responses are really just the content themselves.

Duplexity: Web Sockets by nature are Full-duplex, implying that we can send and receive data at the same time for multiple requests.

Persistence: Web sockets provide a “open” connection between the server and client after the initial upgraded HTTP request handshake has been made. This lets us perform multiple server side requests using the same connection. This also lets the server initiate a response without needing a request from the client side.

The importance of these 4 factors to the web development world and to HANA XS specifically is that this is the missing link for us to take Web applications to the next level.

[Cross-domain support is another great feature!] In this example I was able to successfully have the HTML + JS file local to my PC and execute it against my HANA XSWS service (via a public URL).

– 07/25/2014 — Chris Paine made a good point on potential Cross-domain security issues (see below). Keep in mind that these files are secured just like any of the XS content files, e.g. as long as your folder has a authentication requirement it will persist to this XSWS file as well.

So onto the more interesting HANA specific parts …

 

I initially realized that HANA XS was using Web Sockets in SPS06, when for some reason the XS Engine debugger was not loading correctly due to my user missing some permissions. After searching through the XS code I came across the folder where the debugger was saved and it included a interesting file with the suffix of xsws i.e. XSWebService. After doing more digging I found that Websockets were being loaded in the WebDispatcher config file and I was confident I could find a way to start using it for app development.

After spending some time trying to create my own HANA package with these file extension types I realized that the name is somehow being filtered and only this file, and more specifically, in this location can be executed, otherwise the XS Engine passes back a 403 (forbidden) – I was a little disappointed but it didn’t discourage me … and I decided I would simply re-purpose my Debugger.xsws file for my own needs After a quick backup, I was ready to do some coding …

Essentially, a xsws file is just like any xsjs file, with the exception that it has some socket code returning the responses versus your regular xsjs file. You can do things like $.import for additional libraries as well as perform $.sql functions. Here is a small snippet from the code over on Github.

Debugger.xsws

  1. $.ws.onmessage = function (evt){
  2.     handleIncomingRequest(evt);
  3. }
  4. $.ws.onerror = function (evt) {
  5.     $.trace.debug(“error on connection: “ + evt.message);
  6.     throw new Error(evt.message);
  7. }
  8. $.ws.onclose = function (evt) {
  9.     $.trace.debug(“connection closed, disabling debugger”);
  10.     debugObject.enabled = false;
  11.     throw new Error(“Close status “ + evt.code + “:” + evt.reason);
  12. }

 

 

And this is some of our Client side code making calls the xsws service:

App.js

  1. // Create a new WebSocket. This works fine
  2.   var socket = new WebSocket(‘ws://<ENTER YOUR HANA SERVER HERE>/sap/hana/xs/debugger/api/Debugger.xsws’‘xsCrossfire’);
  3.   // Handle any errors that occur.
  4.   socket.onerror = function(error) {
  5.     console.log(‘WebSocket Error: ‘ + error);
  6.   };
  7. // Send the message through the WebSocket.
  8. socket.send(message);

As you can see – the code and requests are very simple and straight forward, in fact to me they are a little easier than jQuery + AJAX.

One caveat I did find was connection persistence in the event you have an error on the server side, the socket connection can break, in this case you would need a error handling state that attempted a reconnect before submitting any new requests.

A quick screenshot of the running test app i developed and how the server is sending persistence frames pings/pongs to validate the open connection along with the client request and server response.

If you are interested in trying this out on your test or dev instance I have posted the code on Github. Follow these simple instructions to get up and running …

1.) Using the Web IDE, open SAP -> HANA -> XS -> Debugger

2.) Make a backup of the Debugger.xsws file or simply comment out the contents.

3.) Paste the code into the file from Github

4.) Create the Websocket.html file and paste the contents of the Github file

4.) Create the app.js file and paste the contents of the Github file

5.) Open the Websocket.html file and enter any SQL statement

(Be sure you have the debugger security role)

As you can see from the files, the required methods for web sockets are really at a minimum and barely get in your way at all.

Conclusion

At the start of the article I mentioned I was left wanting a little more … this was mainly because since I have been wanting Web Sockets for such a long time, I realized that using it , alone its not really enough. In order for us to really take XS Engine to the next level, we also need to consider a “Publish/Subscribe” feature and a server side timer feature.

The Pub-Sub approach would essentially allow us to push data from the server side, on a specific occurrence of an event, much like a DB trigger. If a new row gets inserted, push the new inserted record to the registered subscriber.

The server side timer feature would allow us to create a server side timer (similar to a xsjob) which would persist and execute the server side function every x secs/mins/hours.

Overall I am pretty impressed with the opportunities Web sockets will bring to the XS Engine. I am hoping they will be included in the next release.