This workshop presents a scenario for extending your web application with Cognitive service integration on Bluemix. The service chosen for this scenario is IBM Watson Question and Answer (Watson QA) service. Arch-Ref-Diagram-Etherpad-Lab4 Contents:

Before you begin

This workshop is written for Ubuntu 14 and Mac OSX development workstations because it’s easy to set up the required tools on those platforms. If your development workstation is running another operating system (such as Windows), you should either obtain an additional server running Ubuntu or run Ubuntu in a virtual machine on your development workstation. This workshop was completed using Ubuntu 14 Desktop following the same set up and configuration procedures described in the previous workshops. Important: Before proceeding with this workshop, you will need to have completed Workshop 1 in this series.

Task 1. Extend Etherpad-lite capabilities using the defined plug-in model

This workshop utilized the defined Etherpad-lite plug-in framework to add capabilities that integrate with services provided by Bluemix. In this case we leveraged the IBM Watson Question and Answer (Watson QA) service. For further details and exploration on your own, the Etherpad Lite plug-in framework is described here. The plug-in we developed allows for users of the Etherpad-lite application to send questions to the Watson QA service and receive a response in the working pad.

Task 2. Create the Watson Question and Answer service

Perform the following steps to create the Watson Question and Answer service:
  1. Log in to Bluemix. The dashboard opens, as shown:
    Bluemix Dashboard
    Bluemix Dashboard
    The dashboard shows an overview of the active Bluemix space for your organization.
  2. Go to your DASHBOARD and click CF APPS in the left navigation menu.
  3. Click the app etherpad-container. This app was created in the previous Workshop (Web application hosting with Database Services), so your app title may be different. Select the app created from the previous Workshop if the titles differ.
  4. Click ADD A SERVICE OR API. When the service catalog opens, scroll down to Cognitive and look for Question Answer.
  5. Click the Question Answer icon to create the new cognitive service. Accept the default settings and click CREATE. You may be asked to restage your application. If so, click RESTAGE and wait the few seconds for your app to restage. Once your page has refreshed and your app has restaged, you now have a managed Watson QA service ready for your use.

Task 3. Understand the Bluemix Environment Variables (VCAP_SERVICES) and how they are accessed in the application

The Bluemix application environment provides a set of environment variables that define the names and details of services bound to the application (e.g. ClearDB MySQL, Question and Answer) called VCAP_SERVICES. In order for the Etherpad-lite app to interact with Watson QA, the plug-in code leveraged and adapted the IBM provided NodeJS demonstration application, located here. You will not need to edit any of the plug-in code; it is only presented here for insight into how different applications can interact with bound Bluemix services.
  1. First, from application dashboard select the Environment Variables link. This will show you the details of the services that have been bound to your application.
    Service Details
    Service Details
  2. Next, copy the contents of your VCAP_SERVICES variables by clicking on the Copy icon in the upper right corner. Paste this content into a file and save it as VCAP_Services.json (case-sensitive) in the /etherpad-lite directory. This is the same directory which contains the Dockerfile and settings.json that was extracted from GIT in Workshop 1.
  3. The Etherpad application will automatically use the URL, username and password property names of the question_and_answer binding in the server side JavaScript that will invoke the Watson Q&A service. The screen below shows how the NodeJS application loads VCAP_SERVICES variables in order to access the Watson QA service. NodeJS application loads VCAP_SERVICES variables in order to access the Watson QA service loadVCAP
  4. Next, the screen below shows how the NodeJS script uses the VCAP_SERVICES variables to set up the REST API to invoke the Watson QA service. One item to note is that the Watson QA service is a beta version that provides two corpora, healthcare and travel. For this example, we set the default data set to healthcare. Details of the service can be found here. Invoke the Watson QA service invokeWatson
  5. Finally, the next code example shows how the question is sent and the correlating response is received and sent to the Etherpad-lite pad object that invoked the request. watsonQA

Task 4. Update the Dockerfile

Next you will need to update the Dockerfile to include the NPM command to install the plug-in when the container is built and copy over the VCAP_SERVICES information so you can test your Watson Q&A Service integration locally. Open the Dockerfile located in the /etherpad-lite directory and add the following command to the Dockerfile (around line 20 before the run /src/etherpad-lite/bin/ command):
run npm install --prefix /src/etherpad-lite ep_talk_to_watson
add ./VCAP_Services.json /src/etherpad-lite/node_modules/ep_talk_to_watson/VCAP_Services.json
Save this file after inserting the above line.

Task 5. Build the image for the application

This section is similar to Build the image for the application, however we will be using different image names, since we are leveraging the Watson Question and Answer service. Tip: On Linux you will normally need to start the IBM Containers Extension (ICE) commands below with sudo ice. On Mac OSX, you should not use the sudo command.
  1. Log in to the ICE command line tool:
    ice login
  2. Build your container using the following commands in succession, from the etherpad-lite directory. You will need to use the value of your own Registry URL in the following commands, found in the container launch page that opens after clicking CREATE A CONTAINER button on the Bluemix dashboard. The first command issued will pull the latest official IBM Node.js container from the global IBM repository.
    ice --local pull
    The second command issued will build our application container, against that pulled latest image and with our Dockerfile and settings.json that were extracted from the Workshops GIT repository. The -t parameter provides a tag that will automatically be applied to the built image, so you can reference it locally. The trailing period (.) is important to make sure we specify the current directory (the cloned etherpad-lite directory) is the working directory for Docker to build our image from.
    • Format:
      ice --local build -t YOUR_LOCAL_IMAGE_NAME .
    • Example:
      ice --local build -t etherpad_bluemix_watson .
  3. Finally, we will tag our image into a repository with a format that will allow us to publish our built image to Bluemix and run it on the IBM Containers service. This command takes your local image that was tagged previously during the build command and applies a repository-specific tag to it, so it can be correctly placed in the IBM Containers service shared repository. This format is required and you will not be able to successfully push an image to Bluemix if you use another image name format that does not match.
    • Format:
    • Example:
      ice --local tag -f etherpad_bluemix_watson
    Your local and remote image names do not have to be the same, but it does help for clarity when comparing local and remote image lists. Also, you can tag your initial image with the full repository tag during the build step instead, but it helps to use shorter tags when running locally to save time and apply the Bluemix-required format before pushing your image to Bluemix. In order, these commands would appear as follows, replacing the necessary formatted parts with your organization and images information:
    ice --local pull
    ice --local build -t etherpad_bluemix_watson .
    ice --local tag -f etherpad_bluemix_watson

Task 6. Test the application on your workstation

Now that our container is built, we can try testing our Etherpad web application locally.
  1. The following command will start a Docker container and run Etherpad in it. It will also print out a container ID (CID) that you will need for the next step:
    docker run -d -p 9080:9080 etherpad_bluemix_watson
  2. The next step is to find the URL to type into your browser to see the running Etherpad web application. On Linux operating systems, you’ll need to get the IP address of the Docker container itself if you are running in a Linux Desktop environment. In the command below, replace CID with the container ID from the docker run command above:
    docker inspect --format '{{ .NetworkSettings.IPAddress }}' CID
    On Mac OSX, boot2docker is running Docker in a virtual machine, so you need the IP address of boot2docker (usually Run this command to get the IP address of boot2docker:
  3. If you are running a Linux Server environment inside a virtual machine, you will need to configure port-forwarding for your virtualization platform to access Etherpad running on the container from your host machine. This will vary from platform to platform, but forwarding port 9080 on your host machine to the internal virtual machine guest is usually all that is needed. An example of a VirtualBox Port Forwarding configuration is shown here:
    Port Forwarding Rules
    Port Forwarding Rules
    Similarly, a virtual machine running on VMWare would require a port forwarding rule as well, but the Guest IP value would be the IP Address associate the VMWare 8 network.
  4. We’re hosting Etherpad on port 9080, so to test your running Etherpad application you can open a URL like this in your browser (replacing with your container’s IP address): If everything is running correctly, you’ll see a welcome screen like the one below.
    New Pad window
    New Pad window
    Go ahead and create a new Pad and play around with it. When you access the pad you now have the ability to submit a question to the Watson QA service. On a new line in the pad type (without quotes) “@aw “, which stands for “Ask Watson”. Make sure to add a space after the “w”. The presents a response of “@watson Ask Me: “. At this point, type a question on the pad making sure to add a question mark (?) to the end of the question. The plug-in takes this question and submits it to the Watson QA service and places the text of the response into pad. A few things to note:
    • The default corpus used for answers is a healthcare domain.
    • This is a beta service and the corpus does not contain the depth or breadth of information that you would expect from a full Watson service.
    The following screen shots show the interaction:
    Watson Q/A service interaction (1 of 4)
    Watson Q/A service interaction (1 of 4)
    Watson Q/A service interaction (2 of 4)
    Watson Q/A service interaction (2 of 4)
    Watson Q/A service interaction (3 of 4)
    Watson Q/A service interaction (3 of 4)
    Watson Q/A service interaction (4 of 4)
    Watson Q/A service interaction (4 of 4)

Task 7. Run the application in Bluemix

Once we have the application running locally, we can publish it to a container running in Bluemix and run it on the Internet. Here are the commands to run the container in Bluemix. You will need to replace some values with your environment specific values, so read the formatting of each command before executing them below, in order:
ice --local push
ice images
ice run --bind etherpad-container --name etherpad_01
The ice --local push command publishes the container image to Bluemix and places it in your organization’s registry, scoped by the Registry URL you configured when you created your IBM Containers service instance.
  • Format:
    ice --local push
  • Example:
    ice --local push
The ice images command will print out the published image URL for you, along with some other data associated with the rest of the images you have pushed up to Bluemix. The output of the ice images command will be similar to below, with the fields being actual unique IDs generated for each image pushed to Bluemix, as shown here:
Output of the ice images command
Output of the ice images command
Note the etherpad_bluemix image that we pushed up to Bluemix with the previous command and the difference between its image name and the other two images provided by IBM. Now we will create a running container instance on Bluemix by issuing the run command below:
ice run -p 9080 --bind etherpad-container --name etherpad_01
You will need to change a few of the parameters in the command above to match your environment:
  1. Update the application name used in the --bind parameter. This allows Bluemix to inject your application’s VCAP_SERVICES information into the running container instance. This is the same application that was used in Task 2 above.
  2. Change the container name parameter (--name) from etherpad_01 or whatever you choose each time you create a new container. This container name does not have to be scoped with a complete URL like the image name does, as it is only for ease of identification of running containers. It can be a simple string and just has to be unique across the containers you have running inside your IBM Containers service instance.
  3. Replace with your own image URL. The :latest tag at the end of the URL specifies to run the latest version of that image, if multiple exist.
  4. Specifying the -p parameter will expose the desired port on the running container inside the Container Service. This parameter needs to be specified for each port you wish to be accessible on your container.
  • Format:
  • Example:
    ice run -p 9080 --bind etherpad-container --name etherpad_01
The ice run command will return a unique container ID (CID); use that CID in commands run for that container. In the following examples, the CID is dd489740-ffff-4c8f-9117-d94cd147f122, so replace that with your own CID. Before you can connect to your web application, you will need to assign it a floating public IP address. The ice ip request command will assign one to you. Replace in the example below with the IP address returned from the ice ip request command, and replace dd489740-ffff-4c8f-9117-d94cd147f122 with your own CID:
ice ip request
ice ip bind dd489740-ffff-4c8f-9117-d94cd147f122
We're hosting Etherpad on port 9080, so to test your running Etherpad application you can open a URL like this in your browser (replacing with the IP address returned from the ice ip request command): Your account only gets two of these public IP addresses at no charge, so unbind the IP addresses when you're not using them. Replace in the example below with the IP address returned from the ice ip request command, and replace dd489740-ffff-4c8f-9117-d94cd147f122 with your own CID:
ice ip unbind dd489740-ffff-4c8f-9117-d94cd147f122
If you want to look up the CIDs for your running containers, and your published image names, you can click the Containers and Images tabs in the container view of the Bluemix dashboard, or you can use the following ICE commands to view running containers and published images respectively:
ice ps
ice images
To stop or remove a running container instance on Bluemix, you can issue the following commands respectively, providing the necessary CID of the container you want work on:
sudo ice stop CID
sudo ice rm CID
Note that a container does not have to be stopped before it can be removed from the IBM Containers service, which is a requirement when running containers locally using Docker.

5 comments on"Actionable Architecture: Web application hosting with Cognitive Services (Etherpad Workshop 4)"

  1. It seems that the service instance used by pluginep_talk_to_watson by default may be down and what is unexpected that will lead to node.js shutdown – etherpad is killed and browser no longer can connect (“You have been disconnected.
    The connection to the server was lost
    The server may be unavailable. Please notify the service administrator if this continues to happen.”)
    as exception is uncaught – seems to be line 144 in

    form docker logs

    [2015-02-22 19:56:21.454] [INFO] console – At line 127…creating Watson request…
    [2015-02-22 19:56:21.463] [INFO] console – At line 171…creating question object for Watson…
    [2015-02-22 19:56:21.463] [INFO] console – At line 182…this is the question being sent to Watson <<>>
    [2015-02-22 19:56:21.905] [INFO] console – At line 134…gathering results from Watson…
    [2015-02-22 19:56:21.906] [INFO] console – At line 141…answers received…
    [2015-02-22 19:56:21.908] [ERROR] console – TypeError: Cannot read property ‘question’ of undefined
    at IncomingMessage. (/src/etherpad-lite/node_modules/ep_talk_to_watson/watsonapi.js:144:29)
    at IncomingMessage.emit (events.js:117:20)
    at _stream_readable.js:943:16
    at process._tickDomainCallback (node.js:463:13)
    [2015-02-22 19:56:21.909] [INFO] console – graceful shutdown…
    [2015-02-22 19:56:21.909] [INFO] console – db sucessfully closed.

    • Rick Osowski February 24, 2015

      This was an oversight in Task 7 and running the container. I am updating that section and some previous ones to include the right steps for dynamically accessing the created Watson Q&A service. I should have the updates shortly.

  2. I followed the tutorials, created and removed containers as per instructions. I also unbound the public IPs from my containers via ice, but when I look in Bluemix, my space still has 2/2 Public IPs bound and it won’t let me bind another container.
    Is there a way to wipe that clean? Any ice command or Bluemix UI option to do that?

    • Rick Osowski June 01, 2015

      Thanks for following up. In a recent service update, the need to unbind a Public IP address from a container instance before deleting the container is no longer a required step. It can still be done for reusing Public IPs in a build pipeline manner, but otherwise the system will take care of deallocating the Public IP and returning it to your pool of requested Public IPs, once a container with a bound Public IP is destroyed.

      • Thanks for clarifying it.

        I noticed that running “ice ip request” on a space that has reached the number of external IP addresses will tell you can’t request any more IPs.
        However, you can unbind the existing IPs and bind them to other containers in that space as needed (within the current limit of 2 external IP addresses per space).

Join The Discussion

Your email address will not be published. Required fields are marked *