Using Let’s Encrypt to create an SSL certificate for my Bluemix hosted web site

In this article I will demonstrate how to secure your custom domain IBM Bluemix web application by creating your own free SSL certificate using the https://letsencrypt.org/ certification authority.

Introduction

Let’s Encrypt is a new Certificate Authority: It’s free, automated, and open. In Public Beta” (Feb 2016). Under the covers uses openssl to create SSL certificates and as such there is no “Windows” interface for doing so. I used this opportunity to learn about VirtualBox, Unbuntu and other linux related technologies. I set up a Virtualbox VM for Unbuntu by following the instructions posted here. I then went through a torrid two days of learning how to make Unbuntu work in VirtualBox, changing the resolution of the VM, learning new Linux commands and other weird and wonderful things.

This brought me to the point of being able to create an SSL cert for my Bluemix site.

If you create a website in Bluemix you get a blah.mybluemix.net hosted site as default. http://xominosocket.mybluemix.net is my socket.io chat example I keep running. You can also create your own “route” by  clicking on the icon next to the domain at the top of your application dashboard.

I set an A record in my domain provider so that copper.xomino.com pointed at the bluemix IP address and the site appeared miraculously quickly within a few minutes. The site will work under SSL but the browser whines and complains about it.

l12

The instructions on how to upload your own SSL certificate are posted here – https://developer.ibm.com/bluemix/2014/09/28/ssl-certificates-bluemix-custom-domains/. I followed a similar path and won’t repeat too much as this post is really about Let’s Encrypt

Let’s Encrypt

As I was going through the documentation on how to use Let’s Encrypt the first problem I had was around the auto creation of a certificate. The code reaches out to the internet to check and see if you actually own the domain. When I did this the first time I got the following message telling me that it actually found my site has a certificate already for *.mybluemix.net. That is not surprising at this stage because I haven’t uploaded the correct certificate yet.

l1

So I went the manual route and performed the following:

letsencrypt certonly --manual --email myemailaddress -d copper.xomino.com

This presented me with the following information.

l2

For the manual process to work (to verify that I do in fact own the domain I am claiming to own) I have to make the very specific URL respond with a very specific answer.

To do this is set up a simple route manager in my node code

app.get('/.well-known/acme-challenge/kEEHfqWh8ur-rxYzIF0Ct8cnP_oGvqCXWZweMNDwbX4', function(req, res){
  res.send("kEEHfqWh8ur-rxYzIF0Ct8cnP_oGvqCXWZweMNDwbX4.PQf6X-2A2s213el2HHSOIMzTm2BLIBAtrEdXkFDPGIU");
});

Once checked into the repo and pushed to Bluemix, this then responded appropriately on the web site

l4

I hit Enter on the Unbuntu terminal prompt – et voila !!

l5

As you can see from the above picture I was able to navigate to the folder and find the files. (BTW I had to chmod 777 -R live the folder because permissions were not created correctly when the files were generated by Let’s Encrypt)

Back in Bluemix I am now able to upload the cert.pem and privkey.pem through the manage domains option. As you can see from the image below – there is an insecure icon next to copper.xomino.com

l6

Manage Domains

l7

Once the upload is complete I was able to view the certificate

l9l8

The route for the application now has a secure icon next to it


l10

Within a few minutes I was then able to access the application using my SSL certificate successfully

l11

Conclusion

Overall this was a relatively painless way of getting a free SSL certificate – and by painless I mean if you know what you are doing with an Unbuntu machine painless. If you don’t, expect a lot of googling. I think it is worth it to learn more about a new (to me) technology and I also have a nefarious docker based reason for learning Unbuntu for the future. This was just the start.

Certificates are only available for 3 months at a time right now – you can read more about the why here (https://community.letsencrypt.org/t/pros-and-cons-of-90-day-certificate-lifetimes/4621).

Advertisements

Passing authentication information through the Bluemix Hybrid Secure Gateway

In this article I will demonstrate a couple of the things which can be passed through a Bluemix secure gateway, allowing us to create normal web based applications.

Introduction

In the previous article I demonstrated how to create a TLS secured hybrid Bluemix application. In this article we will look at some of the web properties/headers, cookies etc which we can pass through the gateway.

The Gateway

To demonstrate what can be passed through the gateway I am using a simple notes form to display the incoming information

The Cookie, Header and username fields are all hidden if the field value is blank

b1

 

Here is my application running on node, using the secure gateway and once again accessing the domino server hosted on my laptop.

b2

 

No username, no cookie, no header.

Changing the code back within the calling application we are going to add some additional information. In the following code snippet you can see that we have added some header “Marky” information.

app.get('/secureTunnel', function(req, res) {
    tunnel.create('8888', function(){
        var options = {
            headers: {"Cookie": "", "Marky": "Hi Marky"},
            port: '8888',
            path: '/xomino/ainx.nsf/testform?readform'
        };

        var callback = function(obj){
            res.writeHead(200, {"Content-Type": "text/html"});
            res.end(obj.body);
        }
        var obj = simpleHTTP.run(options, callback);

    });
});

When we refresh the application we can see that the header has been passed through the secure gateway to the application itself:


b3

b4

If we try and log into the application (directly on the domino server) we can generate a session authentication token. These screenshots are taken directly from the domino server.


b5

b6

At this point though just because the domino window is logged in, the node app still records anonymous.
b7

Adding the cookie to the node application code, which is passed through the gateway

app.get('/secureTunnel', function(req, res) {
    tunnel.create('8888', function(){
        var cookie = "DomAuthSessId=D2BF0063D62C9138E9F723BB88C046F5";
        var options = {
            headers: {"Cookie": cookie, "Marky": "Hi Marky"},
            port: '8888',
            path: '/xomino/ainx.nsf/testform?readform'
        };

        var callback = function(obj){
            res.writeHead(200, {"Content-Type": "text/html"});
            //res.write(JSON.stringify(obj.resHeaders)+"<hr/>")
            res.end(obj.body);
        }
        var obj = simpleHTTP.run(options, callback);
    });
});

We can now see that the user is authenticated within the bounds of the hybrid application

b8

Pushing all this code up into Bluemix you can truly appreciate the authenticated hybrid app

b9

Conclusion

In this article we have seen how we can push basic header information through the gateway and pseudo-demonstrate an authenticated application. There are of course multiple hurdles to overcome between this demo and a real world application, but I hope it has given you an idea for what’s possible.

 

 

BTE102: The Demonstration application – beyondtheeveryday.com

In the previous post  I described how Mark Leusink and I are going to be speaking about Angular.js in our presentation at ConnectED later this month.

We are very proud to announce the demonstration application upon which the presentation will be based

http://beyondtheeveryday.com

This application was created by Mark Leusink and is an amazing example of how simple an Angular application can be integrated with Domino data. The application is fully responsive and is particularly nice to use on a mobile device. All credit goes to Mark for this, I am very flattered to be talking with such an astute and talented developer. You can find out more about the application from Mark’s blog – http://linqed.eu/2015/01/14/marky-marks-mobile-first-connected-sessions-demo-app/

The application is running on a Domino server.

b1

IMG_0339

During the presentation we will demonstrate how we got the application to work on a node server hosted in Bluemix and also demonstrate the application running on SharePoint, IBM Connections and as a native Mobile application.

If you are still not sure, listen to Pete Janzen talk about his recommendations for the conference 😉

Write once – run anywhere………………. !

Websockets in XPages: Improving on the automated partialRefresh interface

In this article I will further discuss how tom improve the user experience of an automated partial Refresh on an user’s XPage. Although these posts were originally about using Bluemix to host the node.js server I kinda feel that the focus has drifted onto websockets more than Bluemix. So in an attempt to make it easier to find I am going to use the Websockets in XPages title moniker for a few posts and then go back to Bluemix 🙂

Introduction

In the last article we looked at how to push a automated partialRefresh to a XPage application using websockets. In that article it was noted that the user experience was not ideal because the whole panel refreshed without the user knowing about it. For some apps that is appropriate and for others it may not be. At this point in his career Dave Leedy is impressed he gave someone else and idea and I quote: “wow! that’s fricken awesome!!!”

So, that’s not a great user experience – what if they were doing something at the time?

Yes I was thinking that too! So I believe we can improve the user experience a little and take what Dave suggested and tweak it a little. Now where have a seen something which let’s the user know there is new data changes but doesn’t refresh the page without their action……….

b4

oh yeah that.

Instead of refreshing the control automatically, we will make the message create a “refresh” icon on the page which the user can then update at their leisure.

b5

The modified code is all in what happens when the page receives the refresh socket message. I added a jQuery rotate function just for some added “je ne sais quoi“. In the function we can see that when the refresh event is detected by the socket code the refreshControl function is called. This in turn makes the hidden refreshIcon visible, adds an onClick event and then rotates it. The onClick event performed the partialRefreshGet as we saw in the previous example turning the page briefly grey. We then hide the icon and remove the click event (to avoid piling on multiple events as the page gets continually refreshed)

 

 // Function to add a message to the page
  var refreshControl = function(data) {

	  $('.refreshIcon')
	  	.css({display: 'block'})
	  	.on('click', function(){
	  	   var temp = $('[id*='+data.refreshId+']').css({background: '#CCCCCC', color: 'white'}).attr('id')
		   XSP.partialRefreshGet(temp, {})
		   $(this).css({display: 'none'}).off('click')
	  	})
	  	.rotate({
	      angle:0,
	      animateTo:360,
	      easing: function (x,t,b,c,d){        // t: current time, b: begInnIng value, c: change In value, d: duration
	          return c*(t/d)+b;
	      }
	   })
  };

  // When a refresh message is received from the server
  // action it
  socket.on('refresh', function(data) { refreshControl(data); });

The following video quickly demonstrates the new capability.

Conclusion

In this brief article we concentrated on how to improve a user experience by notifying them that changes were pending and then allowing them to determine when the changes were made.

I still don’t think this is as optimal as I would like but you get the idea. As I said a long time ago – the more DOM you are reloading the worse the user experience. With a viewPanel we are kinda limited on what we can and cannot refresh. A better option may be to architect the application just the new data and update as appropriate……….

 

XPages and Bluemix: Sending a targeted Websockets message to specific XPages

In this article I will demonstrate how the use of socket.io “rooms” enables us to send message to users who are only accessing specific pages within our application, rather than blanket messages to all users.

Introduction

In the previous article I demonstrated how to use a message POST to the node.js server which could then be turned into a chat message and sent out to all users. While this is a nice example it only serves as such and does not have significant business value. In this article I will begin the peel back the potential for much greater application flexibility through the controlled use of targeted Websockets messages to users of an application.

Most applications have more than one “page” within it and we may wish to send a message to users of one page rather than all pages. Conversely we may want to only send messages to users who are viewing certain types of information wherever they are within the application.

In this article we are still going to use the chat example but this will be the last time we use “chat” as the use case. In future articles I will look into more practical applications of Websockets messaging within an application.

Using rooms within socket.io

Looking at the socket.io documentation for rooms and namespaces you can see that the API exposes the ability to create individual communication channels between the server and the application users.

How this translates to our application on the node.js server looks like this:

  socket.on('joinRoom', function(room, name){
    socket.join(room);
    io.sockets.in(room).emit('notice', name+" has joined");
    console.log(name+" has joined room "+room)
  })

When the “joinRoom” event is registered on the server then the socket is joined to the room name which is passed in. A message is the broadcast specifically out to all the existing room members that the new user has joined. Note that this message is room specific because of the io.sockets.in(room) rather than a blanket message to all users.

With this code in place on any page we can register our application page (chat room in this case) with the socket server. In my case I created a generic function to take the name of the “room” from the XPage URL. The following client side JavaScript sends the “joinRoom” request to the server.

  nickname=$('.username').text()
  // Send message to server that user has joined WinX.nsf/xRoom1.xsp?open&login
  var xpageName = location.href.split('.nsf/')[1] //xRoom1.xsp?open&login
  xpageName = xpageName.split('.xsp')[0] //xRoom1
  socket.emit('joinRoom', xpageName, nickname);

On the server we can then see the console.log as someone joins the room:

s1
We can then have multiple users in individual “rooms” which are in this case 3 separate xPages xRoom1.xsp, xRoom2.xsp, xRoom3.xsp From the original chat room I am able to sen all three rooms a blanket message because they are all “listening” for “msg” as in the previous articles

 socket.on('msg', function(data) {
    console.log('msg here')
    console.log(data)
    redisClient.lpush('messages', JSON.stringify(data));
    redisClient.ltrim('messages', 0, 99);
    socket.broadcast.emit('msg', data);        //broadcast to all users indiscriminately
  });

s2

Sending a message to a specific room

Modifying the original POST code which was shown in the previous article I was then able to create an XPage which will send a targetted message to a specific room. To do this, all I had to do was pass in an additional POST parameter of the room I wanted to send a message to.

I create a new Master XPage which had 3 fields on it – one for each room. Each of the individual fields had a “room” attribute which allows me to pick up a value to specify which room to send it to.

<div id="msgRoom1" class="msgCenter">
	<input placeholder="Send a message to Room1" room="xRoom1" autocomplete="off" autofocus="autofocus" />
	<button type="button">Send</button>
</div>
<br/><br/>
<div id="msgRoom2" class="msgCenter">
	<input placeholder="Send a message to Room2"  room="xRoom2" autocomplete="off"  />
	<button type="button">Send</button>
</div>
<br/><br/>
<div id="msgRoom3" class="msgCenter">
	<input placeholder="Send a message to Room3"  room="xRoom3" autocomplete="off" />
	<button type="button">Send</button>
</div>

s3

In the following code we bind to each of the buttons so that when the are clicked they:

  • set msgField to be the jQuery object representing the pertinent field
  • create the data object to send to the socket server
  • create the newMessage passing in data

The new message function then:

  • POSTs the data object at the “/roomPost” path on the server
  var socketServerURL = (location.href.indexOf('copper.xomino.com')>0) ? "http://copper.xomino.com:3000" : 'http://xominosocket.mybluemix.net'
  var socket = io.connect(socketServerURL)

$('.msgCenter Button').on('click', function(){
  	var msgField = $(this).prev('INPUT')
	var data = { text: msgField.val(), nickname: nickname, when: new Date(), room: msgField.attr("room") };
	sendMessageToRoom(data)
	newMessage(data);
	// Clear the message field
	msgField.val('');
})

var sendMessageToRoom = function(data){
	console.log(data)
	$.ajax({ url:
	        socketServerURL+"/roomPost",
		type: "POST",
		data: data
	}).done(function( msg ) {
		console.log( msg);
	});
}

We can see the message come through on the server

s4

You can also see from the log that I was able to join 3 rooms from the Message Center page – this is as simple as creating three requests to join:

  //client side JavaScript
  socket.emit('joinRoom', 'xRoom1', nickname);
  socket.emit('joinRoom', 'xRoom2', nickname);
  socket.emit('joinRoom', 'xRoom3', nickname);

Site in action
The best way to see all this is to see it in action – as you can see from the video below.

Moving the application to Bluemix

Working locally I used to following code to determine if I was on copper.xomino.com or another server (demo.xomino.com or different again)

  var socketServerURL = (location.href.indexOf('copper.xomino.com')>0) ? "http://copper.xomino.com:3000" : 'http://xominosocket.mybluemix.net'
  var socket = io.connect(socketServerURL)

I had to make a slight change to my cors code in the local node server setup. I looked at the cors npm site to see how to dynamically add cors support and found the answer and modified my code accordingly. So you need to make sure you

//Marky adding CORS from copper
//app.use(cors()); //not used for whitelists

var whitelist = ['http://copper.xomino.com', 'http://demo.xomino.com', 'http://marky.psclistens.com'];
var corsOptions = {
  origin: function(origin, callback){
    var originIsWhitelisted = whitelist.indexOf(origin) !== -1;
    callback(null, originIsWhitelisted);
  }
};

marky.psclistens.com is the same local server as copper.xomino.com (I use a hosts file to make them both look at localhost). But this allows me to play with cors and in this case talk to the local or bluemix node server without needing another “Domino” server.

s6

Because the site running locally is already connected to the Jazz Hub Git repository, as with the previous examples all I have to do is commit the changes locally, push to the Jazz Hub repository, the application will then be re-built and re-deployed to Bluemix.

It’s really about as simple as that. Because the code is already primed to check to see if we are looking locally or at Bluemix, a new URL for the application now looks at Bluemix.

s5

 

So why do we need Bluemix again?

While the development was performed locally, the intention is to be able to create a capability which does not require the user to have a locally running node.js server. That is where Bluemix comes in. In essence what we are creating is a cloud hosted Websockets service which can be integrated into existing applications.

 

Conclusion

In this article we have seen that with a little creativity we are able to register different chat rooms within the same application. There are other ways to do this of course but the point of this example was to demonstrate the ability to send a specific message to specific users looking at an individual XPage.

In the next article we will take a look at the practical implications of this within an XPages application.

 

Integrating the Bluemix Watson Translation service into an XPages application

In this article I will demonstrate how to integrate the Bluemix Watson Translation service into a functioning XPages application.

Bluemix Watson Translation Service

Following on from one from my previous posts on the subject I have been looking for a good workable example of using a Bluemix service within an XPages application. As I said before this is as much an exercise in me learning more about node.js and Bluemix as anything else – but I also love being able to share.

Based on the previous post about how to get the Watson Q and A service up and running it took me 12 minutes to get a working example of the Watson Translation service up and running on a Bluemix site. Just for disclaimers I have no idea how good the Watson service is and I am not advocating it – this is purely an exercise in being able to use a Bluemix service, more so that what it does.

So I followed the steps in my previous blog but applied them to the example post on the Watson Translation service. This was pretty simple and once again the only thing to change was the manifest.yml file to name the service and application correctly.

w2

http://xominowatsontranslate.mybluemix.net/

When you type into the TEXTAREA box (1) and then hit “Translate”(2) the result is displayed in the Output (3)

The page does a full refresh and the answer is displayed. The node.js code running behind the application is fairly self explanatory :

  • (looking at the code snippet below) we can see the values POST’d from the application are received on the node.js server in the app.POST
  • The posted field values are turned into a separate request to the Watson translation service
  • The Watson request (watson_req) is sent as a serversiude request to the Watson service
  • The results from that are sent back to the response object “watson_res”
  • The node.js response (res) back to the user is then set back to the browser using the jade template (index)
    • return res.render(‘index’,request_data);

// Handle the form POST containing the text and sid, reply with the language
app.post('/', function(req, res){

    var request_data = {
        'txt': req.body.text,
        'sid': req.body.sid,
        'rt':'text' // return type e.g. json, text or xml
    };

    var parts = url.parse(service_url);
    // create the request options to POST our question to Watson
    var options = { host: parts.hostname,
        port: parts.port,
        path: parts.pathname,
        method: 'POST',
        headers: {
            'Content-Type'  :'application/x-www-form-urlencoded', // only content type supported
            'X-synctimeout' : '30',
            'Authorization' :  auth }
    };

    // Create a request to POST to Watson
    var watson_req = https.request(options, function(result) {
        result.setEncoding('utf-8');
        var responseString = '';

        result.on("data", function(chunk) {
            responseString += chunk;
        });

        result.on('end', function() { //this is triggered when the response from Watson is completed
            // add the response to the request so we can show the text and the response in the template
            request_data.translation = responseString;
            console.log('request',request_data);
            return res.render('index',request_data); //<------response sent back to the web page
        })

    });

    watson_req.on('error', function(e) {
        return res.render('index', {'error': e.message})
    });

    // create the request to Watson
    watson_req.write(querystring.stringify(request_data));
    watson_req.end();

});

 

You can see that in action through firebug – here is the POST parameters

w3and here is the response – the new HTML containing the answer

w4

 

Modifying the service

Here is the thought process which occurred to me:

  • Well that is cool but if I want to integrate this into an XPage then I will need to return the result as JSON and not a whole HTML page
  • But I do not want to break the example so how can I do that ?
  • I can use a new route – so if I POST at a different URL, the node.js server can be made to be smart enough to do something different
  • Ah…….and then I will have CORS issues because my application will be running at xomino.com and the bluemix app is not

Replicating the POST as code

So the first thing I did was try and replicate the code in jQuery (as I know best) so that I could mimic a POST event in ajax without using a form. In the following example you can see I added jQuery to my page (jQuerify plugin for firebug). I then simulated an AJAX POST to the translation service (emulating the form post).

w5

 

The response is the HTML of the new page, so I know this is at least the right AJAX code.

w6

 

But when I am on the copper.xomino.com site and I try and repeat the same thing, as expected CORS issues.

w7

Ryan Baxter (who frankly has been a huge support and help in learning all this) said to me

“You are in luck, CORS is dead simple with Node  – https://www.npmjs.org/package/cors” and how right he was.

Adding the CORS package to my Bluemix application

The way you add a package to your Bluemix application is by updating the package.json file. This file contains all the npm modules that will be needed and what is even cooler is that these will be npm installed within your node server automagically on deployment

w8

So then I need to add the cors enabled page to my application. But I did not want to change the core example on the site. So what I did was create a new “route” within the node.js application and told it to do something different….

Originally we had this within the example


// Handle the form POST containing the text and sid, reply with the language
//the route in this case is "/" - so basically the root of the application
app.post('/', function(req, res){
	//stuff
}

and to create a new route we just add a different app.post


// Handle the form POST containing the text and sid, reply with the language
var cors = require('cors'); //add the cors module code to the application
app.use(cors());
var corsOptions = {
    origin: 'http://copper.xomino.com' //allow copper to be a site which can work with the watson site
};

//note the new cors(corsOptions) parameter in the app.post function
app.post('/xpages', cors(corsOptions), function(req, res){ //when a user posts to  site.com/xpages do this code instead of the default '/'
	//stuff
}

What I then changed was the response code – this was the original code responding with text and rendering using the jade index.jade template

	//......
        result.on('end', function() {
            // add the response to the request so we can show the text and the response in the template
            request_data.translation = responseString;
            console.log('request',request_data);
            return res.render('index',request_data); //render the response using the index,jade template and passing the request_data
        })

Instead of res.render I used res.json to send the request_data object back to the browser directly.

	//......
        result.on('end', function() {
            // add the response to the request so we can show the text and the response in the template
            request_data.translation = responseString;
            console.log('request',request_data);
            return res.json(request_data);
        })

So in this way I left the default page alone (“/” server root) – the example still works – but I added a new route (“/xpages”) so that my XPage application could POST at it.

I committed the code and pushed back up to Jazz Hub, restarting the service as we went…….and low and behold success…..

w9

As you can see from the above image, I am at the copper.xomino.com website. Using the slightly modified code to now post at

I get a response from the Bluemix website with the JSON from the Translation service. You can see from the headers the CORS header is added for copper.xomino.com

w10

Note – if you go to http://xominowatsontranslate.mybluemix.net/xpages you will GET an error. This is because my node application does not have an app.get for the /xpages route

So then XPages….

Integrating the Watson Transation service into an XPage application

Once I have the working ajax code it is very simple to add it to an XPage and just pick up the field values on the fly….. I cheated to some extent and copied and pasted the HTML from the original example into my XPage….hey why not this is an example after all…

I added a couple of classes to the example so that I could easily pick out the field values…

a1

And then the jQuery code to add to the application. In this code I

  • Select the .translate class (the translate button)
  • In the click event I get the data from the form
    • the .sid select box for the language translation
    • The text value from the textbox (.theOriginal) field
  • I then submit to the the translation service as before
  • In the .done() of the AJAX request, the incoming msg.translation is then added to the .theTranslation field

a2


 The demo

As you can see from the video – I am able to:

  • type in any value
  • send it to the bluemix service
  • receive the answer and display it on the screen
  • save the original and translated values as notes documents within my XPages application
  • Firebug shows the fact that the POSTS are going to http://xominowatsontranslate.mybluemix.net/xpages

Conclusion

I think this is a great example of using a “service” on another website to be able to enhance the functionality in your own XPages application. If IBM are successful in their investigation to put Domino inside of Bluemix, this capability will all happen behind the scenes and could be easily written as one true application……bring it on… 🙂

 

PS

This exercise was particularly gratifying because it feels like a culmination of all the work I have done in XPages over the last 3 years.

  • Without the jQuery and Firebug work I did at the start of XPages development, prototyping this would have been much more tedious.
  • Learning XPages has forced me to have a better understanding of AJAX and jQuery
  • If it were not for Angular and the “Write once run anywhere” I did for MWLUG, I would not have learned about CORS.
  • If it was not for the Angular work I would not understand “routes” within an application
  • …..and now I am learning about node.js and Bluemix PaaS

Keep learning !

 

 

Create your own Watson Q and A example with Bluemix, Webstorm and Jazz Hub

Introduction

In this article I will demonstrate how to get up and running with one of the Bluemix/Watson service examples. I will be using the example provided by IBM in their documentation as the basis for the article but the way in which I achieved the final goal was quite different from the way that they explained it in the example.

This example will use:

I could have added BS words as an attention seeking headline, and it would fit because there is so much I want to show in this one post (it is probably should be 5 separate posts). But I figured that it’s probably better to have a more description title about what this is really about (more googlable that way). So be warned this is a longer post than normal because of all the pictures. Going through this experience helped me better understand Git, Webstorm (and how it uses Git), Jazz Hub and Bluemix.

Creating an example of using the Bluemix Watson service.

Earlier this week IBM announced that they added the Watson API as a service to Bluemix. I honestly have no idea what I would ever use this for in my line of business but the coolness factor is huge!

In this post I am going to demonstrate how I was able to create the example service without using the same process as laid out in the IBM documented example. As this is a long post (lots of pictures) I will be discussing the separate parts in other posts.

There are also other ways of creating your App from scratch (for example Create an App, select node.js as a runtime and then bind the Watson service.) The reason I did the example this way was to highlight that you do not always have to start with a new service. I needed a node.js runtime, and it happened that one of my services already provided that (the DataCache starter service). That’s kinda cool and kinda the point of Bluemix!

1) Log into Bluemix

https://ace.ng.bluemix.net

Your should be presented with your dashboard.

2) Create an App 

 

 

a1

 

Select the Node.js runtime
w1

 

Name the App (in my case the App is called xominoWatsonQandA and the Host is xominoWatsonQ)

w2

3) Add a service – Watson Question and Answer 

w3

w3

4) Assign meta-data to the new service

  • Give the service a name – you will need this later so don’t over complicate this (qa-service)
  • The Watson service is currently in Bluemix as a Beta at time of writing

w4


5) Confirm you have an application

Now we have the pieces necessary to build the application on.

  1. A Node server
  2. The Watson service.

w5

6) Make sure you have a Jazz Hub account

If you do not already have a Jazz Hub account then go and create one here https://hub.jazz.net/

NOTE: The Jazz Hub site uses your IBM login userid and your Jazz Hub password – do yourself a HUGE favor and make the password the same as your IBM account and if you ever change the password on your IBM account you have been warned 🙂

Here is a shot of my Jazz Hub account before we start – note no “xominoWatsonQandA”

w1

7) Add your new application to Jazz Hub

Select the “Add GIT” option on the top right of your App dashboard

w6

8) Confirm existing service code?

The next prompt asks me if I want to create starter code in the new Git Source Control repository. In this case I do not – un-check it.

w9

9) Go to your new source control Git repository

Click on the Jazz Hub URL displayed on the right hand side.

The Add Git link will be replaced with a link to the repository. Click on the link to go to there. We will look at Edit Code in another post.

 

w7

 

10) Get the URL of the repository

In the picture below you can see over on the right there is a link for the Git URL – click on that and copy the URL.

w11

11) Open Webstorm IDE

As I was working my way through this example I wanted to learn more about how Webstorm functions as a Git client. You can use Source Tree or the Git command line if you prefer.

You need to ensure that Git is enabled in Webstorm before you proceed. it is not configured out of the box. The instructions for enabling git are found here https://www.jetbrains.com/webstorm/webhelp/using-git-integration.html. You will need to have Git installed before hand. Follow the ssh key instructions and it will show you how.

12) Checkout the new repository

Select Checkout from Version Control > Git form the Webstorm VCS menu option

w12

 

Paste the URL from the Jazz Hub site into the Vcs Repository URL

w13

Select Clone and a new project is created within Webstorm and as you can see, the files downloaded are those from the repository on Jazz Hub

w14

12) Download the example code and add to the local repository

Following the example site, download the sample file qa-nodejs-sample.zip. Unzip it locally and drag the files into the repository directory created by Webstorm in the previous step.

w15

Clicking back into Webstorm you will see the files refresh in the project – they all appear “red” because although the files are in the repository directory they are not current added to the Git configuration, it does not know they exist.

w16

13) Add the files to the local Git repository

Right click on the project and add the directory as follows.

w17

The files will all turn green

14) Edit the manifest.yml file

Within Bluemix the manifest,yml file is the key to holding everything together. It contains the “services” and the application they are used in. In my case the service name for Watson was qa-service and the application is xominoWatsonQandA.

Save the Manifest file

w8

You can also see from the manifest file command “node app.js“. If you look into the other files currently in the example you will find app.js. This tells Bluemix how to start the application.

15) Commit the files to the local repository

Right click on the project name – select Git > Commit Directory

In this case I chose to Commit and Push back to the repository

 

w20

w21

Webstorm then does a stupidity check on your files (we all need that)

w22

And then Webstorm tells you that you are stupid!!

w23

On dear……….well actually if you look into this, Webstorm is reporting issues in the example app css files and missing semi-colons in the JavaScript. Without going into correcting all of them, the application works despite these errors. So we Commit and continue.

w24

My commit comments are “Modified manifest and all files”

Pushing…

w25

We get confirmation that the files were committed and pushed up to the Jazz Hub repository

16) Confirm Jazz Hub

You can now see by refreshing your Jazz Hub page that all the files are now in the server repository. You can also see next to my picture in the middle “Manifest change and all files” as the last commit comment.

w26

Then comes the really cool and completely not Command Line experience. In the top right of the page you can see Build and Deploy….

17) Build and Deploy

w27

18) Confirm

You will be taken to a page where you can see the results of the build and deploy. Jazz Hub is very smart and self aware. If you have un-committed changes within your repository it will not let you Deploy. That is for another day though.

w28

 

Note: what’s interesting is that the Deploy to URL which I cannot change is xominoWatsonQandA.mybluemix.net not what I would expect as xominoWatsonQ.mybluemix.net which is the route I gave the application in the first place. Turns out I not have two routes to the same App. I can see this back on my bluemix dashboard as there is now a (+1) next to my routes options!

So note to self, name your route the same as the application name!

w10

19) You now own Watson

Click on the route link back on your Bluemix dashboard and you now have a running example of the Watson Heathcare service

w9

In review

In this example we saw a LOT of cool new features, concepts and ideas for Domino developers and you know that we have barely scratched the Bluemix, Webstorm, Jazz Hub surface. I learned a significant amount of new and cool things from going through this process. The first time from scratch it took about 90 minutes to figure out what I was doing. The second time I went through it, even taking all the screenshots for the blog it took 25 minutes.

We only changed two lines in one file to make this work – anyone can do this !!

Like I said at the top of the article, I have no idea how I would use Watson in the day job but that was not the purpose for doing this example. These “services” are componentized capabilities which we can take advantage of. Imagine the growth possibilities as more and more services are added to Bluemix. This has got to be fun to watch and follow along. Remember IBM are investigating putting Domino into Bluemix.

The Watson Cloud REST API information is available here http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/#!/Question_Answer

This is so cool 🙂