Posts Categorized: Source Code

compare-icon

Syscompare – a tool for comparing repos across HANA instances

compare-icon.png

A couple of weeks ago I was moving code from 1 hana instance to another trying to keep them in sync. However, I thought there might be a better alternative for comparing the contents of the repos across my systems to ensure that the files matched. After doing some digging and not finding a solution, I decided to write a small tool to do just this, called Syscompare. It is a open source HANA app which uses the new File API and compares the files on each system and displays the differences.

You can read more about the application here, and find the files for the HANA app in Github.

 

Features:

- Compare repos across HANA instances

- Display file differences in the application

- Highlights missing files on each instance

Usage:

- Setup the 2 XSHttpDest files

- Specify the source and target systems (using the xshttpdest file names)

- Specify the repo to compare

Once the processing is complete the app will show a summary of differences:

Screen Shot 2015-06-16 at 10.18.20 PM.png

Screen Shot 2015-06-16 at 10.20.12 PM.png

Screen Shot 2015-06-16 at 10.20.51 PM.png

You can checkout the Github/Source code here: paschmann/Syscompare · GitHub

If you prefer to download the Delivery Unit – please click here and provide your email address (this way I can keep you up to date with changes): metric² | Real-time operational intelligence for SAP HANA

Interested in contributing to the project? Please feel free to fork or submit a pull request.


bg_top

metric² for iPhone and SAP HANA

 

metric² for iPhone lets you monitor your SAP HANA instances from your phone showing you alerts, core resources and important metrics. Wherever you are.

As mentioned in my GitHANA article, developing on the metric² open source project has really provided some interesting use cases for me around SAP HANA. While it might not be as critical as ERP, BW or custom solution, the metric² demo system is used fairly regularly by people wanting to test drive the functionality. I recently had some server troubles and my HANA instances was down without me knowing. This promoted me to develop a small mobile app to monitor and ensure that my instance was available and running optimally. This is when metric² for iPhone was conceived and I started developing the free app.

 

 

The app is currently availble for iPhone, and I have a iPad version getting ready to be submitted to the App store. From a technical perspective the app uses a small XS file called mobileapi.xsjs which will need to be put in a package on your XSEngine instance to serve up the data to the app. You can specify how often you would like the data to be refreshed and specify multiple systems which you may need to monitor. (I have included my demo HANA instance as an example within the app so you can try it out.)

http://metric2.com/img/alerts2.png

 

The app is perfect for anyone running a HANA instance, be dev, test or production. It provides a really easy way to view the status of your system from anywhere using your iPhone. The app also downloads updates in the background and will notify you if any high alerts are experienced on the selected system, this is perfect for any sys admin/dba who will be to anticipate critical outages and be ready for the support calls.

A few features of the app

- View CPU, Disk, Memory consumption
- View open alerts
- Insights into your HANA instance quickly and from anywhere
- Add multiple HANA instances for monitoring
- Clean and simple UI for basic admin functions
- Push notifications for high alerts, when the app is in running background

Click here to find the GitHub project (of the mobileapi.xsjs file) and click here to check out the product page. This includes install instructions.

Technical Details

Building a native iOS (read Obj. C or Swift) which is integrated with SAP HANA is not terribly challenging and you really have 2 options for pulling or pushing data. Via a XSJS type file (like this app) or via a xsOData type of interface. Both have their pro’s and con’s but are fundamentally very similar. Below is a snippet of some of the code from my xsjs file and looks/acts very similar to what a regular AJAX call would use from a native XS app.

One of the biggest challenges for production users, like any intranet based resource, will probably be gaining access to the URL (mobileapi.xsjs) from outside the corporate net and will probably require a network admin to grant you access or configure (or reuse) a reverse proxy or firewall.

Screen Shot 2014-08-22 at 1.08.56 PM.png
Screen Shot 2014-08-22 at 1.12.40 PM.png
XCode iOS Pull Data Code
Screen Shot 2014-08-22 at 12.52.08 PM.png
SAP HANA XSJS Code serving data to the iOS app

Git-HANA-Screenshot

Git <> HANA – A free, open-source Github client for SAP HANA

Git-HANA-Screenshot.jpg

Over the last few months, working on the metric² open source project, I have been frequently updating the GitHub repo. As a heavy XS Web IDE user, this entailed exporting or copying the contents of the files from the package into my local GitHub repository for the project and subsequently committing the files from there. Since there is a small disconnect between the source (my HANA packages) and the destination (GitHub) I like to often see what changes which are due to be committed, the differences between the files, or just compare the files between the 2 systems.

Being over dedicated to building solutions to some of my workflow challenges (see here, here and here), I created yet another small HANA native app called Git <> HANA. The application allows you to compare files between your local HANA package and your (or any other) GitHub repo, and it also lets you commit files directly from the UI to GitHub, and vice-versa. If a file does not exists, it will create it for you (on either side). There are a couple other cool features which you can read about below, or watch the little video I created.

If you are a web IDE user it’s quick and convenient to use, and I am convinced it will make your HANA + GitHub integration easier (I am also hoping we will also see more open source native HANA apps on GitHub as a result!!!!)

Features of Git <> HANA

- Compare files between HANA and Github
- Compare inline or side by side
- Commit files from HANA to GitHub
- Commit/activate files from GitHub to HANA
- Repo/branch selection
- Native HANA application
- Easy HANA package installation
- Open source
- handles .xs* (e.g. .xsaccess, .xsapp) files (which your file system probably does not like!)
- Image comparison
- File browsing can be done via the GitHub repo or your HANA package

You can download the app package here (newsletter sign up requested so I can keep you up to date with the app) or check out the source files here.

If you think this would be helpful or would like to see any other features, or would like to contribute to the source … EXCELLENT, please just let me know

Screenshots

  

Use the HANA Package Browser or GitHub repository as a reference.

Push files from HANA to GitHub or from GitHub to your local HANA package.

Compare Files side by side, or inline

Package Install Instructions

- Download the package
- Open Lifecycle manager (http://<HANA_SERVER>:PORT/sap/hana/xs/lm/)
- Click on Import/Export menu
- Click Import from File
- Browse to the downloaded file
- Edit the index.html file and specify your github username/password (or leave it blank and enter these details using the settings)


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.


pastedImage_15

Node.js dashboard for SAP HANA

This is what we will be developing in this blog …

Over the past few years Node.js has really caught my attention. The simplicity of Javascript with server side processing, Non-blocking-IO, Event Driven, and simple integration always intrigued me as a great combination for enterprise applications. (Somehow it sounds similar to HANA XS Engine)
A couple months ago I ran into a similar problem to Jon-Paul Boyd (HANA Forum Post) in which I wanted to use XS Engine for websocket/persistant connections to my HANA Instance, but due to the support not being included in SPS6, I decided to look elsewhere, and ended up using Node.js to fulfill this requirement.In the past, while developing HANA/Node apps, I resorted to creating a XSJS App which really just acted as a middleware layer to push and pull data from my HANA DB, until recently I noticed a great blog post from Ingo Sauerzapf which piqued my interest. The blog mentioned that Holger Koser had created a HANA DB Client for Node making life extremely easy to connect to HANA directly from Node. I thought it would be good share the small project I developed using Node.js and this new client with the community in the hopes that others will share their experiences with the technology.This blog is not necessarily an introduction to Node.js development as there are some nice tutorials and examples out there from Tobias Hoffman and Alessandro Spadoni. The blog is intended to cover a small app developed in Node.js and shows the development process behind it, taking it from conception through to reality. I encourage you to download a few of these components, and also the example out. This app, similar to another app I developed called Metric² (which you can read about here), it is a web based widget showing some friendly KPI’s on the performance of your HANA Instance. The app gets streaming data from our HANA backend displaying this in a friendly, simple dashboard. The dashboard is designed to be shown on a large format monitor in a Ops or IT center and can also very easily be modified to show any KPI’s relevant to your business or needs.

Requirements:

SAP HANA Instance (e.g. AWS Developer Image)

Node.js installed (this does not need to be on the HANA box but same network with access to the HANA port – normally 30015).

Node Dependencies

We will also use a couple of helpful dependencies from the node community including Socket.io, Express and obviously hdb. Installing these packages is as simple as running “npm install hdb”. Once you have the dependencies installed we can start creating our app.

https://nodei.co/npm/hdb.png?compact=true

App Design

For me, I always start mocking up in my favorite Image IDE (Photoshop), I used this image as inspiration for my app. I liked the simplicity, clean layout with focus on the numbers at the bottom. In our case, we will add a small chart in the center, giving us a basic visual representation of the numbers being displayed:

 

Photoshop HTML Mockup
Download the PSD

App Development

Index.html

In this case I decided to use Twitter Bootstrap to help with some of the layout/formatting of the page as well as some mundane tasks like Modal popups. From a coding perspective I started out developing the Single paged “index.html” file, doing my best to stick with my mockup which I previously created. I was sure to “id” all of my elements on this page as we will be updating these values from our node.js backend. This aspect of node development is strictly “traditional” web based development. No need to work with Node or any server for that matter. Once you have your page rendering the way you want, we can move on.

<html>

<head>

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

<meta charset="UTF-8"/>

<meta name="viewport" content="width=device-width, maximum-scale=1.0" />

<title>Metric&#178;</title>

<!-- jQuery -->

<script src="https://code.jquery.com/jquery.js"></script>

<!-- Socket.IO -->

<script src='/socket.io/socket.io.js'></script>

<!-- Peity - a lightweight sparkline package for jQuery -->

<script src='js/jquery.peity.min.js'></script>

<!-- Client side code needed -->

<script src='js/client.js'></script>

<!-- Bootstrap CSS -->

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">

<!-- Latest compiled and minified JavaScript -->

<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"></script>

<!-- CSS -->

<link rel="stylesheet" href="css/style.css">

</head>

<body>

<div id="top">

<div>

<div>

<div>

<table>

<tr>

<td rowspan="2" style="text-align: center; width: 10%;" >

<img id="statusicon" src="img/OKIcon.png"/>

</td>

<td style="vertical-align: top;">

<h1><span id="info-name">SAP HANA Instance</span>

<button data-toggle="modal" data-target="#myModal">

<span></span>

</button>

</h1>

</td>

</tr>

<tr>

<td style="padding-top: 20px;">

<span style="margin-left: 0px;" /></span><span id="info-alerts">0</span> Alerts

<span></span><span id="info-version">1.0</span>

<span></span><span id="info-detail">Server Location</span>

</td>

</tr>

</table>

</div>

<div>

<span>0</span>

</div>

<div>

<table>

<tr>

<td id="infoUSERS" onClick="setChart('USERS');">

<!-- The ID of each of our <SPAN> tags is important for updating the data being returned from the server -->

<span id="info-users">0</span><br />

<span>Users</span>

</td>

<td> </td>

<td id="infoDISK" onClick="setChart('DISK');">

<span id="info-disk">0</span> <sup>GB</sup><br />

<span>Free Disk</span>

</td>

<td id="infoMEM" onClick="setChart('MEM');">

<span id="info-mem">0</span> <sup>GB</sup><br />

<span>Free Memory</span>

</td>

<td id="infoCPU" onClick="setChart('CPU');">

<span id="info-cpu">0</span> <sup>%</sup><br />

<span>CPU</span>

</td>

</tr>

</table>

</div> <!-- /.containerfooter -->

</div> <!-- /.container -->

</div> <!-- /.centercontainer -->

</div> <!-- /.top -->

<!-- Modal -->

<div id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">

<div>

<div>

<div>

<button type="button" data-dismiss="modal" aria-hidden="true">&times;</button>

<h4 id="myModalLabel">Settings</h4>

</div>

<div>

<form id="modalbox" role="form">

<div>

<label for="servername">Name</label>

<input type="text" id="servername" placeholder="Enter a reference server name">

</div>

<div>

<label for="serverdetail">Location</label>

<input type="text" id="serverdetail" placeholder="Description, Location or Other Information">

</div>

<div>

<label for="bg">Background</label><br />

<label>

<input type="radio" name="bg" value="../img/bg1.jpg" checked> Background 1

</label>

<label>

<input type="radio" name="bg" value="../img/bg2.jpg"> Background 2

</label>

<label>

<input type="radio" name="bg" value="../img/bg3.jpg"> Background 3

</label>

<label>

<input type="radio" name="bg" value="none;"> None

</label>

</div>

<div>

<label for="colorscheme">Color Scheme</label><br />

<label>

<input type="radio" name="colorscheme" value="Dark" checked> Dark

</label>

<label>

<input type="radio" name="colorscheme" value="Light"> Light

</label>

<label>

<input type="radio" name="colorscheme" value="Fiori"> Fiori

</label>

</div>

<div>

<button type="button" data-dismiss="modal">Close</button>

<button type="button" id="modalSave" onClick="saveSettings();">Save changes</button>

</div>

</div><!-- /.modal-content -->

</div><!-- /.modal-dialog -->

</div><!-- /.modal -->

</body>

</html>

App.js

Next we develop the app.js file which is the brains of our operation. This file is firstly going to act as our web server for our web site, and secondly provide the data from our HANA server to the web page, pushing the data via web sockets.

Below is the app.js code, here you can see how we process each request based on the type and subsequently respond with the requested data. You can also see how simple it is to call the HANA DB and respond with the results.

 

var express = require('express'),

http = require('http'),

hdb = require('hdb');

try {

var app = express();

var server = http.createServer(app);

server.listen(3000);

var io = require('socket.io').listen(server);

app.use(express.static(__dirname + '/'));

// development only

if ('development' == app.get('env')) {

app.use(express.errorHandler());

}

var client = hdb.createClient({

host     : 'Your HANA IP Address or DNS Name',

port     : 30015,

user     : 'username',

password : 'password'

});

client.connect(function (err) {

if (err) {

console.error('Connect Error:', err);

} else {

console.log('Connected to server');

}

});

process.on('uncaughtException', function (err) {

console.log('Caught exception: ' + err);

});

strContent = '';

io.sockets.on('connection', function (socket) {

socket.on('request', function (data) {

// Handle Service Requests

switch (data.service) {

case 'CPU':

client.exec("SELECT ABS(SUM(PROCESS_CPU)) as CPU from SYS.M_SERVICE_STATISTICS", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: 'CPU', response: rows[0].CPU});

}

});

break;

case 'MEM':

client.exec("select TO_VARCHAR(ROUND((FREE_PHYSICAL_MEMORY) /1024/1024/1024, 2)) AS FREEMEM

from PUBLIC.M_HOST_RESOURCE_UTILIZATION", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].FREEMEM});

}

});

break;

case 'INFO':

client.exec("SELECT VALUE FROM SYS.M_SYSTEM_OVERVIEW WHERE NAME = 'Version'", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].VALUE});

}

});

break;

case 'DISK':

client.exec("select TO_VARCHAR((ROUND(d.total_size/1024/1024/1024, 2) - ROUND(d.used_size/1024/1024/1024,2))) as FREESPACE

from ( ( m_volumes as v1 join M_VOLUME_SIZES as v2 on v1.volume_id = v2.volume_id ) right outer join m_disks as d on d.disk_id = v2.disk_id )

where d.usage_type = 'DATA' group by v1.host, d.usage_type, d.total_size,    d.device_id, d.path, d.used_size", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].FREESPACE});

}

});

break;

case 'USERS':

client.exec("SELECT COUNT(CONNECTION_ID) as STATUS FROM SYS.M_CONNECTIONS

WHERE CONNECTION_STATUS = 'RUNNING'", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].STATUS});

}

});

break;

case 'ALERTS':

client.exec("SELECT COUNT(ALERT_DETAILS) as ALERTCOUNT FROM _SYS_STATISTICS.STATISTICS_CURRENT_ALERTS", function(err, rows) {

if (err) {

console.error('Error:', err);

} else {

socket.emit('response', {service: data.service, response: rows[0].ALERTCOUNT});

}

});

break;

}

});

});

} catch(err) {

console.log(err);

}

 

The App does have a couple of different themes which will hopefully make it fit with your office decor

Below you can see a couple of images of the app running and showing the output. You can obviously very easily modify the code to show anything relevant to your business case as well. The Node-hdb package for node.js really makes developing HANA connected Node apps a breeze! Thanks Holger!

Fiori Styled
Light Theme
Image5.png
Dark Theme
Image6.png
As usual – please feel free to comment on your experience with Node.js and if you feel like this type of technology is a good fit in the enterprise? Do you have any suggestions on what I could have done differently?You can download the app here: Metric² for Node
Credits: The Bokeh backgrounds are from devientArt

Image1

Metric² for SAP HANA

Metric² is a web based, realtime dashboarding platform for SAP HANA, on SAP HANA.I recently gave a demo of the app at Demojam in Las Vegas (You can read my blog post about the event here). Metric² is a free app/download and this blog gives some insight into how it works, and how you can download and install it in your own HANA system:

Overview

Metric² is made up of 3 key areas:

Dashboards: Metric² can have multiple dashboards. Dashboards are designed as blank canvases, are quite flexible, and can contain widgets which are added can be simply dragged and dropped into their needed locations and also sized accordingly.

Widgets: Dashboards can have multiple widgets displayed. There are a variety of widgets including a range of predefined datasources (CPU, Memory, Disk etc.) but also include custom widgets (SQL, JSON, Yahoo) which can display a myriad of information to your team.

Alerts: Certain widgets can have alerts “attached” to them, when the value meets the conditions, the alert is logged and displayed.

  1. Why realtime? The intent is to be proactive about your systems or applications health, having the Metric² dashboards up on a large format monitor ensures that everyone is well aware of how your system is performing, and more importantly, when it is not.
  2. Why Web Based? While I personally prefer Native/Traditional/Window types apps, having Metric² run as a web app (using SAPUI5) means it can be used and displayed on a variety of devices and formats.
  3. Why do you call it a platform? Its more than just a bunch of metrics, everything is customizable, you can create your own widgets, your own dashboards and alerts, it also acts as a large data warehouse for any of the data you are monitoring/tracking, taking it past being an app, to a small platform which you can build, and extend upon.
Image1.png

Architecture:

This was an interesting dilemma for me, I wanted to keep the app as simple as possible by not requiring that admins install *any* additional components (thus deemed as a “Native” XS HANA app). It has a DB schema which Metric² needs to have present, and subsequently a set of files which get installed in the content repository via a package.

This lead to an interesting challenge, because the XS Engine did not support web sockets for “true” realtime app runtime, the app uses timers and HTTP polling to fetch the data from the backend system (read xsjs file). This is less than perfect. I have high hopes that SPS7 will include WebSocket support and we can start writing true realtime web apps directly on XS Engine. Another alternative is the recent availability of Node.js library for HANA, while its awesome, still requires additional components outside of the core HANA platform.

Image2.png

Design:

The app is based on a “Fiori” themed SAP UI5 foundation. I also used a variety of JQuery add-on’s to help (read: not reinvent the wheel) with the display of  the data. I also used the standard D3 visualization library of UI5 along with a helper class called NVD3 which is very useful in simplifying the D3 charting experience.

Image3.pngWhats Missing:

- Currently the app does not support multiple users.

- Browser support … currently its developed for Firefox only, but does not look too bad on Safari or Chrome (CSS Changes needed).

- The polling aspect, because the data is being fetched from your XSJS file and returned to the main page, I am constantly having to eval the returned code to update the chart widgets. Eval is Evil

- Widget history: Because widgets are being polled, if the screen is not open, it will not capture any historical data. Not very useful for troubleshooting.

Whats Next:

I am currently working on porting the app to support the realtime abilities. Planning on a new theme (not so much Fiori like) to make it a little more differentiated. Also planning on adding a few more predefined widgets (suggestions welcomed!!!).

Download:

Here

Install Guide:

  1. Import the Metric² Package to the content repository in XS Engine (This can be done via Web or Studio)
    1. Open http://YOURIP:8000/sap/hana/xs/ide/
    2. Click on the Delivery Unit Menu and then Import Delivery Unit From File System
    3. Select the downloaded/unzipped file (REPO_20131109-203950826-HDB–METRIC2.tgz)
  2. Run the Install script (InstallScript.sql) for the DB which is included in the download – This can be done in either HANA Studio or the Web IDE
  3. Optional: Run the Overview dashboard script (Overview Dashboard.sql) from here to give you a sample dashboard  – This can be done in either HANA Studio or the IDE
  4. Open your browser to http://YOURIP:8000/lilabs/metric2/Index.html

- Optional: Predictive Analytics: You may need to enable PAL on your server in order to use the libraries and forecasting feature under some of the widgets.

Known Issues:

- The ping response widget is not functional currently

- The Total CPU reported on the “System overview” widget should be converted to a legitimate percentage (0 – 100%) as SLES displays a summed percentage of all the CPU’s.

- The Map of the US Widget – coordinates are not accurate, they need an offset due to the images size and padding within the widget

- The dashboard itself is not fully responsive, when displaying on an iPad the view is often too small to display all the widgets

- There is no mail server functionality built into XS Engine, so alerts are only displayed on the monitor and in the notifications area on the right of the screen.

You can submit an issue log on my website making it easier to track, share, resolve: http://blog.li-labs.com/issue-log/

Disclaimer:

Vishal Sikka made a humorous reference at the Las Vegas Keynote to a certain “Pre-release” Beta product, so I am going to do the same This version of Metric² is a “Prerelease” beta please use and test it thoroughly in your development environment.

Stay up to date:

Please head over to http://www.metric2.com and signup for the newsletter, this way I can stay in touch with people interested in learning more.

License:

This software is provided as is, and with no warranty. You may copy, modify and share the code for personal purposes. You may not sell or include, any parts, or as a whole, the software. Please share the download via the URL provided – Thanks.

Favor:

If you install Metric² and build an interesting dashboard, please tweet or share it in the comments. Also if you find any errors or issues on the installation process, please let me know and I will gladly update this guide. Thanks


pastedImage_1

HANA Talk – A Simple helper class for SAP HANA Development

HANA Talk is a small Javascript class which help facilitate the communication between your front end html/js files and HANA database when using SAP
HANA XS Engine. This is intended to help people who are just starting out development on XS Engine and would like a easy place to get  their feet wet without having to go through too much trial and error. This is also a great starting point for people involved in events like InnoJam, Hackathons, etc. when POC’s and demos need to developed quickly, but not necessarily perfectly *cough* or securely *cough*

By providing this tutorial and the HANA Talk download, my hope is that it will encourage more people to consider using XS Engine as a app platform to drive their front end web apps and subsequently, encourage the use and innovation around HANA in general. Anne Hardy had a comment in her blog post regarding the Developer Advisory Board which was along the lines of “Developers want to get it in 5mins max; they want to build real stuff in less than an hour”.

I frequently get discouraged by the amount of learning and effort always needed to learn new technologies and products which companies “get into bed with”. Nearly every one of the apps I develop start out in a POC type phase, where my imagination and reality clash and inevitably produce the equivalent of a 3yr old’s self portrait, often resembling “Unconventional”. While going through these exercises I often wish it was simple to get somethings done, and understanding the cost and willing to accept the trade offs. This is why I developed HANA Talk – to make those unconventional portraits, easier to deliver

OK – so what does it do?

By adding a HANA Talk js and xsjs file to your project, you can simply write SQL statements in your HTML file and have the results returned synchronously.

e.g.  Index.html

  1. <script type=”text/javascript”>
  2. var resp = hana.executeScalar(‘SELECT 1 FROM DUMMY’);
  3. console.log(resp); //Outputs 1
  4. </script>

Super simple and easy. See below for further details.

Prerequisites

1. Download/fork these 2 files – client.js & server.xsjs from Github and add them to your package. The filenames/structure can be changed if you are feeling adventurous. In your HTML file, you will need to reference client.js, this is as simple as adding a tag to you header. For reference, if you are not using SAP UI5 or jQuery – you will need to add this to your HTML header as well.

A Basic Example

2. In your javascript code, instantiate a new HanaTalk object. We will use this to “pass” our SQL commands to our HANA DB.

  1. var hana = new HanaTalk(‘SYS’); //The ‘SYS’ reference is in relation to the Schema. It can be specified here or within your TSQL Statement

3. Call your HanaTalk object with the operation type and SQL you would like execute (see below for additional operations).

  1. var result = hana.executeRecordSet(“SELECT 1 FROM DUMMY”);

4. We can populate that response into our html (DOM)

  1. document.getElementById(“SomeElementID”).innerHTML = result;

A few more examples

a.) Insert/Update/Delete a record – use .executeChange, this will execute your code and respond with the records which have been updated

  1. document.getElementById(“resp4″).innerHTML = /*hana.executeChange(“UPDATE/INSERT/DELETE …. “) + */ ‘ Record Changed’;

b.) Return a Table – using .executeRecordSet will return a html formatted table, displaying the select’s record set

  1. document.getElementById(“resp2″).innerHTML = hana.executeRecordSet(“SELECT TOP 5 * FROM M_HOST_INFORMATION”);

c.) Return a Object – .executeRecordSetObj allows us to loop through records, and have quite a lot of control of the display of each record and its column name.

  1. document.getElementById(“resp3″).innerHTML = hana.executeRecordSetObj(“SELECT TOP 5 * FROM M_HOST_INFORMATION”);

Here are the results of the calls above:

As you can see, making these types of calls is fairly simple and since your files reside directly on the DB app server, responsiveness is not too bad. So what’s so bad about this method?

Security: Because you are passing your SQL text directly from your browser to the backend server, you open yourself up to all kinds of SQL Injection hacks. Technically, we are not parsing URL arguments/parameters into the server side DB request but rather entire statements. In order for us to hack this, we could simply change the URL request to include some devious SQL.

Speed: For simplicity and to avoid AJAX Callbacks, the execution is performed Synchronously (i.e. We wait for the server to completely respond before we continue processing). The good: Code is “inline” and easy to manipulate the response/results from the server. The Bad: if we do a Select * on a massive (read billion) row table, the entire window is locked/hung until it either times out or completes. Not a particularly nice behaving UI.

The usual disclaimer: As mentioned, the intent of this post/download is to encourage simplicity, this comes at a cost, both performance and security are less than perfect – in this case, we will do our best to mitigate some of these. In fact, I expect a snarling comment from Thomas Jung, like a high school math teacher, disappointed that one of his protege openSAP students would even suggest these obscenities

I encourage you to test this out and provide some feedback or makes some changes and share this with the community.


Screen+Shot+2013-05-10+at+8.25.14+AM

Simple Sample: Writing an entry to SAP Netweaver Gateway using JSON

Skill Level: Beginner
Time Needed: 20 minutes

I recently assisted someone on the forums when they were having trouble creating records in their SAP ECC instance while using Gateway. I thought I would share some very simple code showing what it takes to write an entry into a service via JSON from iOS (Objective C). The reason the title of the document is “Simple Sample” – there are no frills. Whenever I develop a new app, I start small, get the basic functionality working, and proof out the process before getting too creative.

*** If you do not have your own gateway server, you might be able to connect this to the SAP Gateway System which can be found here. Create an account and utilize this service *** DISCLAIMER: Untested as the signup form does not work

The small application sample below uses this document as a starting point. It describes setting up CRUD (Create, Read, Update and Delete) operations for the Bank account list in your back-end, based on the Bank BAPI. For our example, we will be using the Read and Create functionality of the service. Our example will use a open source repository called AFNetworking. The download can be found here, is ARC compatible and is very easy to add and reference in your project. I will skip the basics of creating a iOS project and adding the reference to AFNetworking (but for reference I am using a “Single View” app template in XCode).

Read Operation from your iOS App

Reading from a OData service using JSON can be done in as little as 7 lines of code in objective C (When using the AFNetworking classes). Here is my example code which can be used to read from your service. In my case, I am returning a list of Banks. Below is the code and the output.

Screen Shot 2013-05-10 at 8.20.25 AM.png Screen Shot 2013-05-10 at 8.23.55 AM.png

Create Operation from your iOS App

Creating a new record adds a small requirement, in that a CSRF (Cross Site Request Forgery) Token needs to be added to the POST request header. If you notice above, I have added this “fetch” header to my GET request, thus returning the key we need along with our data. (2 birds, 1 stone). Here is the create request. Pending it is successful, it will return the record which have been added to your back-end system. Below is the code and output.

Screen Shot 2013-05-10 at 8.19.28 AM.png Screen Shot 2013-05-10 at 8.25.14 AM.png

Here is a link to the GitHub project to avoid you writing all of this out. Once again – download and follow this useful guide from Gateway team to create the Bank service in your Gateway system, download the project from GitHub, update your gateway server name and details and this will be a useful starting point for creating your next enterprise app.

Disclaimer: Keep in mind the code purposely simplifies the code needed. If you feeling more adventurous:

  1. Ensure your gateway server is using HTTPS.
  2. Instead of using a NSString *dataset, use NSDictionary object/Class to the Request using JSONRepresentation
  3. Add your username and password to the header request, Base64 encoding them.
  4. Instead of writing the JSON response out to a UITextView, add some UITextBoxes and parse the values out.

Can anyone spot the field I forgot to post?


Image2

A peek inside xSync and the HANA XS Engine

icon_128x128.png

On saturday I published a blog about a small app I wrote called xSync – basically a XS Engine app for Mac developers where you can sync a local development folder with your HANA repository. This is for rapid development and to encourage the “bring your own IDE” approach to application development on HANA. Here is a look behind the scenes on how the app works and some of the challenges of the project.

Image.png

As mentioned in my previous blog – I started using the IDE Lightweight editor after doing the upgrade of my AWS HANA box last weekend. I enjoyed the experience but after working with it for nearly a full day was wanting a little more. Syntax highlighting, easy commenting, easy indentation, CSS autocomplete and hints, etc. etc. so I started doing some peaking around the editor itself and came to find the editor is something called ACE, a pretty nice little open source IDE (written in JS). This got me thinking … maybe I could insert text directly into the Lightweight IDE browser text box, and submit the form as a save …. hmmm …. not a terrible idea …. just need to scrape the page, find the elements and submit the form via some injected JS. Pretty simple …  I did some digging and found the HTML objects I needed by using Firebug when a lightbulb went off … instead of populating the form via a HTML page, why not rather check the HTTP methods it is calling when doing the actual save, since there must be some integration with HANA directly … which is when I came across the mother load … a small file called reposervice.xsjs It seemed that every time I was saving or modifying my objects through the IDE, it was calling this file. After checking out the parameters it was `, it was very clear that the methods and text were easy to simulate. I fired up REST Client and within a couple minutes the concept was POC’ed. Pass your file contents as your body with a path param and a POST and you were off to the races

Screen Shot 2013-06-09 at 4.39.png

Using Firefox Rest Client to monitor system calls showed each save, create, delete operation was using a small file called reposervice.xsjs, which references the libraries needed for the repository modifications.

Image2.png

The diagram above displays the HTTP call made when saving/creating a file, and how the IDE initially does a HEAD request for the XSRF token, followed by the HTTP PUT.

The initial HEAD request is to fetch the CSRF Token, secondly the token along with the parameter of mode, path and activate are passed to the URL. Pending you are successful, a JSON message is returned with the status. For those of you are not familiar with Cross-Site-Request-Forgery, you can read about it here: http://en.wikipedia.org/wiki/Cross-site_request_forgery

Once I had this done, I was wondering what the best integration option would be and weighed up a couple options of a simple check in type procedure, but wanted something faster, easier and “click free”. Being a bit of a highly iterative developer myself, I find it easier to develop “online”, which is why I decided it would be best to do a File System watch of a particular folder and save any changes automatically to my HANA instance. Similar to a dropbox type approach.

I had my POC working nicely, a integration goal defined and set out to start developing the UI/Application in Objective-C (Xcode). I had a template type of app from one of my little SAP Note Viewer applications which could act as a foundation. I threw some code out and pulled some very useful little open source packages in as helpers. Within a couple hours in my evenings each night the app was running nicely and doing what I had expected, modify a file or two in a predefined location and sync up to XS. easy.

Thats generally where development grinds to halt for me, as I envision feature after feature to build a Mac clone of HANA Studio Luckily my senses got the better of me, and I worked on doing a recursive package downloader, the ability to create, rename and delete files and folders and not a HANA Studio rewrite Once this was all done, ironing out the bugs was painful. The cocoa FSEvents stream (File System Events) Class on the mac is not easy to work with and a bear at best. Having to monitor a folder for any modifications, deletes and creates turned into a bit of a logic nightmare. One of the interesting challenges is that if you “delete” a file on the mac file system, it does not get a “delete” FS Event but rather a rename! (Since it goes to the trash/recycle bin!). This leads to having to do multiple … if exists then …. type statements around each file and folder event

UI is another interesting one, I like apps to look somewhat decent … and I spent a good amount of time working on each of the elements in Adobe Photoshop as usual … (Whenever I do a mobile app development talk I mention that I spend close to 40% of entire project time in apps like Photoshop with design work! Most are surprised!)

If you are interested in incorporating some these types of features into your own app, I will be posting a copy of the integration classes on GitHub shortly.

PLEASE KEEP IN MIND: This is exploratory type work with undocumented API’s, I would not recommend using this in production, or any important production work (or your important opensap homework!). The reason I shared this was to encourage people to look under the hood and understand the how’s and why’s of how some of these great new tools work.

I would be interested to hear if anyone has any interesting use-cases for being able to manipulate both HANA repository and DB artifacts from outside of the Studio? Does anyone have any challenges with the HANA Studio today they would like to see changed?


Screen+Shot+2012-07-20+at+5.12.03+PM

Connecting SAP Netweaver Gateway Trial to ES Workplace ERP

After following John Moy’s blog series on setting up the Netweaver Gateway trial on Amazon EC2, I thought it would be helpful to share how to connect your shiny new gateway trial to the ES Workplace ERP. Since using the ES Workplace systems a couple years ago for a CRM Mobile app, I have always praised the ES team for putting together a great set of resources for encouraging and enabling a service oriented architecture (SOA). The systems (ECC, CRM and PI) are great for doing testing against and developing POC’s or demo apps. In this case we will be using the ERP instance to connect our Gateway system for data consumption.

In this example we will be initially connecting our systems together and then going through setting up a very basic example of consuming data from the ES Workplace ERP system via the Netweaver Gateway system sitting in the AWS cloud.

Please note that the Prepackaged Netweaver Gateway Trials already have this configured and ready for your username/password.

In order to connect and consume data from the ES Workplace ERP system, you will need an account. You can create one here and it only takes a couple of minutes: http://www.sdn.sap.com/irj/sdn/soareg
Once you have created your account, I suggest logging in and changing the initial password you received through registration. Its also just a good idea to check you are able to gain access to avoid any issues down the road.
Next up head over to your Netweaver Gateway Trial system and open up SPRO

-> SAP Netweaver

-> Gateway

-> OData Channel

-> Configuration

-> Connection Settings

->SAP Netweaver Gateway to SAP System

-> Manage RFC Destinations

Screen Shot 2012-07-20 at 4.47.32 PM.png
Click on ABAP Connections and select the “New” icon. Screen Shot 2012-07-20 at 8.08.35 PM.png
Name your RFC Destination and make sure that Connection Type is configured to be 3 – ABAP Connection.

Under Technical Settings enter the following values:

Target Host: iwdfvm3989

System Number: 00

Save As: IP Address

Gateway Host: /H/155.56.56.170/S/3299/W/e$workp1ace/H/iwdfvm3989.dmzwdf.sap.corp

Gateway Service: 3300

Screen Shot 2012-07-20 at 5.11.42 PM.png
next click the “Logon & Security” Tab and enter your ES Gateway Credentials and save the connection. Screen Shot 2012-07-20 at 5.11.52 PM.png
After saving, select “Manage SAP System Aliases” and enter the details which will create a system alias for the ES Workplace ERP system. Screen Shot 2012-07-20 at 8.29.31 PM.png
SAP System Alias: Any name e.g. ESW

RFC Connection: Should be the name of your RFC connection you specified above

Software Version: Default

Screen Shot 2012-07-20 at 8.31.19 PM.png
Click the connection test button and you should receive a screen looking like this. Screen Shot 2012-07-20 at 5.12.03 PM.png
Once this is done, we are ready to create our webservice.

For our consumption example we will be pulling out a simple list of all users. If you would like to see a complete and detailed guide of CRUD (Create, Read, Update and Delete) operations – I would suggest checking out this document: https://www.sdn.sap.com/irj/scn/index?rid=/library/uuid/30aee2cc-c474-2e10-ac93-d163ee3b9576

Open up SE80 and create your Gateway Data Model. Screen Shot 2012-07-20 at 8.25.27 PM.png
Be sure to specify your System Alias when creating the Model. Screen Shot 2012-07-20 at 8.40.47 PM.png
Per the documentation, search for a BAPI you would like to use. Because we defined the System Alias in the previous step, the BAPIs being displayed are coming from the target system, in this case the ES Workplace machine. Screen Shot 2012-07-20 at 8.51.23 PM.png
Continue through the process by mapping the query operation.Also be sure to set a primary key by highlighting your unique property and clicking the “Key” button. Once done, click “generate”. Screen Shot 2012-07-20 at 9.01.33 PM.png
Next up we will create a consumption model for our data model. Open up SE80 again and attach the gateway data model to consumption model. Screen Shot 2012-07-20 at 9.39.01 PM.png
Now we should be done, you can open up the browser and point to your URL listed in SE80 under the consumption model to see the definition and available collections. Screen Shot 2012-07-20 at 9.40.35 PM.png

This is directly on the AWS machine, but I can also call this from my local machine:

Troubleshooting:

In the event you try to view a collection and receive the error: No System Alias found for Service, open up SPRO and assign a System Alias to the Service.

Screen Shot 2012-07-20 at 9.32.23 PM.png
Here you can see where the ESWORKPLACE alias has been defined. Screen Shot 2012-07-20 at 9.35.36 PM.png
Having additional problems?

Check that the service has been defined in SICF

Screen Shot 2012-07-20 at 9.37.49 PM.png
If you queries are taking a long time to load or your dataset is large, don’t forget to limit it/add parameters to restrict the returned records. This can be done when defining the data model. Screen Shot 2012-07-20 at 9.46.04 PM.png
If your service will display locally on AWS but not from another machine, check that the AWS Security Rules include the port gateway is running on (in my case 8000).
If you try to view the detail of the  you will get an error, this is because I did not map the operation of GetDetail or Read – we only did the Query. Follow the guide to easily add this.

If you have a elastic IP associated with you EC2 instance you should be able to call the REST service from any machine connected to internet. (You could also use your public DNS name, its just not all the short!).

Here are a couple of useful TCodes for working with Gateway:

/IWFND/ERROR_LOG Gateway Error Log
/IWFND/APPS_LOG Gateway Application Log Viewer
/IWFND/MAINT_SERVICE Maintain Service