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.

 

XPages and Bluemix: How to create a Websockets message without being connected to the application

In this article I demonstrate how to create a Websocket message to be broadcast, from a website which is not connected to the Websocket directly. This will be achieved by using a http POST request of the message to a node.js server hosted on Bluemix and having that server then emit a Websocket message out to the application.

Introduction

In the previous article I demonstrated how to create an XPages chat client using a Bluemix hosted node.js server. I was able to do this by porting the node.js example to an XPage (xSocket.xsp). What I wanted to figure out (thank you Stack Overflow) was how to trigger a Websocket message to be sent out without using the Websocket socket.io JavaScript client.

Reference articles

This article is based on information already published on the following blog posts:

POSTing to a node route

In the Watson translation service example article I discussed how to create a new POST route within your node application using the simple express construct “app.post”.


var cors = require('cors');
app.use(cors());

var corsOptions = {
  origin: 'http://copper.xomino.com'
};

app.post('/xpages', cors(corsOptions), function(req, res){
  .....
});

In a similar fashion in this example I am going to POST data from the copper.xomino.com website and therefore I need to add the cors code to the application to allow this.

Looking at the message payload

If we look at the client.js file from the original node.js Bluemix example blog post we can see that the message which is sent to the websocket looks like this

    var msgField = $('#msg'),
    data = { msg: msgField.val(), nickname: nickname, when: new Date() };

So our target is to recreate that same data Object and send it through to the server socket emitter in the same format.

Creating the POST data

Once again learning from the previous Watson example the code for this is relatively simple. We create the data Object with a nickname and text value and then POST them to the xominosocket.mybluemix.net site. Logging the response from the server

var data = {
	nickname: 'marky ajax',
	text: 'Sample POST from AJAX'
}
console.log(data)
$.ajax({ url:
	"http://xominosocket.mybluemix.net/xpages",
	type: "POST",
	data: data
}).done(function( msg ) {
	console.log( msg);
});

Modifying the node.js code

The node.js code from the previous article needs to be updated in a number of ways.

The Watson Translation example used a version of express 3.x. Version 4 is more streamlined and does not contain a lot of middleware. When we attempt to POST data to the node server it cannot be understood because it is encoded by the web browser (by default). For his we need to add the npm module body-parser (not forgetting to include it in the package.json).

The new package.json looks like this

{
  "name": "xominosocket",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.10.1",
    "jade": "^1.7.0",
    "redis": "^0.10.3",
    "socket.io": "^1.2.0",
    "cors": "2.4.2",
    "body-parser": "1.9.2"
  }
}

The app.post also needs to be able to parse the incoming POST and then re-purpose this into a socket emit event. We do this as follows. I also added a check to make sure the req.body was coming through. This was failing before I realized I needed body-parser.

// Handle the form POST containing the text and nickname
app.post('/xpages', cors(corsOptions), function(req, res){
  var request_data = {};

  console.log(req.body)

  if (req.body){
    request_data = {
      'txt': req.body.text,
      'nickname': req.body.nickname
    };
  } else {
    request_data = {
      'txt': 'this failed',
      'nickname': 'Not this guy'
    };
  }

  var data = { msg: request_data.txt, nickname: request_data.nickname, when: new Date() };
  io.sockets.emit("msg", data);
  res.send(data);
});

Testing the new capability

For the purposes of this article I am only going to show the example in Firebug console. As you can see from the code on the right we are posting to the xominosocket site. On the left you can see the communication was successfully sent to the site, the response and the headers:

ws1

From the next screenshot you can see that the message is them broadcast out to the other client currently connected to the socket, in this case in Chrome.

ws2

Cors security

The cors security only allows POSTing from the copper.xomino.com site. This is a good thing 🙂

ws3

Conclusion

In this article we have seen how we can “create” a websockets emission event on the server by POSTing a message to a separate page within the application.

While this may seem pointless (“because why couldn’t I just create a normal websockets message from the page”), what we will see in a future article is the need to emit an event from the server which is not connected to the Websocket and doesn’t need to be.

 

Creating an XPages Websockets chat client using Bluemix

In this article I will demonstrate how I was able to take an example Bluemix, node.js based, websocket chat program and re-purpose it to be used in XPages.

Introduction

Earlier this year I was very excited to find the Websockets in XPages project on OpenNTF published by Mark Ambler. The concept behind that project is to be able to create a notes document in a queue which is processed and then send out to all users. As much as I promised to help out and use the project, life and a business need to learn and use Angular.js got in the way. My abject apologies to Mark for not following through on my promise to help move the project along.

With this article though, I want to start my exploration of using an external Websockets server to transmit messages to my XPages applications. One of the *nice* things about Websockets is that unlike JavaScript AJAX they are *not* restricted by CORS. This means that I can host my Websockets server anywhere. In this case it is a win win for me as I get to learn more about Bluemix, node.js, websockets and other NoSQL databases like Redis in this case.

Creating a Websockets chat example in Bluemix

I found this article on Create an HTML5 chat app on Bluemix with Node.js, Redis, and Socket.io and following it through I was able to get my own chat program up and running within an hour or so.

ws1

It is not an especially difficult example to follow but I did find that it helped to understand a little about Bluemix and how a node.js application is put together. You should be able to figure it out though just following through the example.

The code for the original example can be found here https://hub.jazz.net/project/joelennon/bluemixchat/overview?welcome= if you want to take a look at it.

Porting the “client” to an XPage

Within the original example, the interface makes a connection to a Redis database to store the last 99 entries of the chat. Within the XPages example I could do that but I am not going to at this time. So the XPages interface will lose chat history when you refresh the page. I am not really concerned about that in the big picture.

Because I had all the files locally I was able to create a new IBM Domino database and drag the files into the WebContent directory. Within node.js the “Public” directory is assigned to the root of the server, but in this case I removed the public folder as it is unnecessary.

w2s2

 

The original example uses the jade templating engine to create the web page. But in this case I felt lazy and just viewed the source of the example once it was working and then extracted all the HTML I needed.

Moving socket.io to the HEAD

Because this is XPages and because we have dojo and I am sure I have pointed out before – we have to move the files to the HTML HEAD in such a manner as they come before Dojo within the application. Socket.io is apparently one such JavaScript library.

The HTML of the XPage is relatively simple. As you can see below we a using the xp:resources tag to insert the same HTML references to the local files as they were in the original example.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">

	<link rel="stylesheet" href="//cdn.jsdelivr.net/normalize/3.0.1/normalize.min.css"/>
	<link rel="stylesheet" href="stylesheets/style.css"/>

	<xp:this.resources>
		<xp:headTag tagName="script">
			<xp:this.attributes>
				<xp:parameter name="type" value="text/javascript" />
				<xp:parameter name="src" value="//cdn.jsdelivr.net/jquery/2.1.1/jquery.min.js" />
			</xp:this.attributes>
		</xp:headTag>
		<xp:headTag tagName="script">
			<xp:this.attributes>
				<xp:parameter name="type" value="text/javascript" />
				<xp:parameter name="src" value="socket.io/socket.io.js" />
			</xp:this.attributes>
		</xp:headTag>
		<xp:headTag tagName="script">
			<xp:this.attributes>
				<xp:parameter name="type" value="text/javascript" />
				<xp:parameter name="src" value="javascripts/client.js" />
			</xp:this.attributes>
		</xp:headTag>
	</xp:this.resources>

	<h1>XPages Websocket Chat using Bluemix</h1>

	<input id="msg" autocomplete="off" autofocus="autofocus"/>
	<button type="submit">Send</button>

	<ul id="messages">
	</ul>

</xp:view>

 The critical difference – the server connection

Within the original example the socket code was on the same server as the client creating the messages. In this case they are not as my XPages server is wholly independent of Bluemix.

So I had to change the initial connection to the websocket server. Within the client.js file I changed the first line from

$(document).ready(function() {
  var socket = io(), nickname, msgList = $('#messages');
  ...

to the following

$(document).ready(function() {
  var socket = io.connect('http://xominosocket.mybluemix.net') //connect to the Bluemix server
  var nickname, msgList = $('#messages');
  ...

With these changes and a couple of stupid spelling mistake corrections I was able to bring my application up within my xSocket XPage.

ws3

You can see from the Firebug console that the copper.xomino.com application is talking to the xominosocket.bluemix.net application

Mobile Compatible

Yes you have to be connected to the website (rather than OS Push notification) but websockets works on iOS7+ and Android 4.4+

(http://caniuse.com/#feat=websockets)

Screenshot_2014-11-08-11-47-45

Conclusion

There is a lot more detail which we can go into as to how this example works but in the mean time if you want to play with it.

Here is the Bluemix Page: http://xominosocket.mybluemix.net/ (with chat history)

Here is an XPage: http://demo.xomino.com/xomino/WSinX.nsf/xSocket.xsp (no history)

For the full effect – open each link in a different browser and you can talk to yourself 😉

You can find my Bluemix code on Jazz Hub – https://hub.jazz.net/project/mdroden/xominosocket/overview.

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 !

 

 

Oh duh, that is why Node Package Manager (npm) is so cool

I am in the process of playing with Bluemix and part of the reason or this is to learn more about node.js. It is really cool to learn something new and also to broaden the mind. But I digress – Node Package Manager (npm) makes using node.js so simple it is mind boggling…

Without going into masses of detail on node.js (which I might at some point) here is the simple example of what I am trying to do and why npm is so cool. Node Package Manager (npm) allows you to install any node “module” or code component library, very easily and with the minimum of effort.

I run node.js on my windows machine within a certain directory. I am looking into CORS enable one of my Bluemix applications so I am messing with the cors module in node.

Here is my directory structure to start with. It is only a simple hello world app but for the sake of this demonstration it is all I need.

n1

Within node_modules we have the following packages which are the modules I used as I was learning the hello world example.

n2

Adding a new module using npm could not be simpler

To add “cors” to my application I open the hello-world directory in a command prompt (Shift right click)

n3

I install cors with the simple “npm install cors” (yes Ryan I used a Command Line Interface)

n4

The files are downloaded from the npm website and they are added to my directory structure

n5

and it is as simple as that. I now have all the cors code which can be accessed by my application.

It only struck me this morning as to the sheer brilliance of this as I “muscle memory” did this to install a new module because it occurred to me I needed it. Simplicity is a thing of beauty to me.

In summary

  • I wanted to install a new module
  • The npm architecture with node centralizes all the code modules you need
  • I did not need to know where to look for the cors package existed
  • I found my example of how to use CORS online
  • I added the code module I needed to my application with 3 words
  • so cool 🙂

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 🙂