Oracle Application Container Cloud Service: Building a RESTful API with Node.js and Express

 

Before You Begin

Purpose

This tutorial shows you how to develop a RESTful API in Node.js using the Express framework and an Oracle Database Cloud Service instance to deploy it in Oracle Application Container Cloud Service.

Time to Complete

45 minutes

Background

Express is a Node.js web application framework that provides a robust set of features to develop web and mobile applications. It facilitates a rapid development of Node based Web applications.

Scenario

In this tutorial, you build a basic RESTful API that implements the CRUD (Create, Read, Update, and Delete) operations on an employee table in a Oracle Database Cloud Service instance using plain Node.js and the Express framework.

Database diagram:

Database model
Description of this image

The Node.js RESTful application responds to the following endpoints:

Path Description
GET: /employees Gets all the employees.
GET: /employees/{searchType}/{searchValue} Gets the employees that match the search criteria.
POST: /employees Adds an employee.
PUT: /employees/{id} Updates an employee.
DELETE: /employees/{id} Removes an employee.

The HTML client to test the RESful API is provided in the next section (What do you need?) The zip file contains an index.html file and seven .png images. This client is developed using JQuery, Ajax and CSS.

What Do You Need?

  • Node.js 4.x
  • A text editor
  • A web browser
  • Oracle SQL Developer
  • An active Oracle Cloud account
  • An instance of Oracle Database Cloud Service
  • A user and password to connect Oracle SQL Developer to your instance (If you don't have an instance, you can create one by following this tutorial.)
  • cURL 7.0+ (cURL is installed by default on most UNIX and Linux distributions. For the steps to install cURL on a Windows 64-bit machine, click here).
  • employee-client.zip
  • node-employees-service.zip (The complete project with the source code ready to deploy in Oracle Application Container Cloud Service)
 

Setting Up the Database and the Objects

In this section, you create a connection to your Oracle Database Cloud Service instance from Oracle SQL Developer and execute the scripts to create the employee table and sequence and to insert a couple of employee rows.

 

Connecting Oracle SQL Developer to Your Database

  1. Open Oracle SQL Developer.
  2. Click the View menu and select SSH.
  3. Right-click SSH Hosts and click New SSH Host.
  4. In the New SSH Host dialog box, enter or select the following values and click OK:
    • Name: DBCS
    • Host: The public IP address of your Oracle Database Cloud Service instance
    • Username: opc
    • Use key file (After you select this check box, click Browse, and select the private key file.)
    • Add a Local Port Forward (Select this check box.)
    • Name: Local
    • Host: localhost
    • Port: 1521
    • Use specific local port: 1523
    New SSH host window
    Description of this image
  5. Right-click the DBCS host connection and select Connect.
  6. If it's required, enter the passphrase.
  7. Right-click Connections and select New Connection.
  8. In the New / Select Database Connection dialog box, enter or select the following values and click Test:
    • Connection Name: Your connection name
    • Username: Your database user name
    • Password: Your database password
    • Connection Type: SSH
    • Role: default
    • Port forward: Local (DBCS)
    • Service name: PDB1.<your-identity-domain>.oraclecloud.internal

      Note: Keep the default values for the rest of the fields.

  9. Click Save and then Connect.
 

Creating the Database Objects

  1. Right-click the connection and select Open SQL worksheet.

    Connection context menu
    Description of this image
  2. Copy the following script into the SQL worksheet to create the EMPLOYEE table and the sequence named EMPLOYEE_SEQ:

    CREATE TABLE EMPLOYEE (
          ID INTEGER NOT NULL,
          FIRSTNAME VARCHAR(255),
          LASTNAME VARCHAR(255),
          EMAIL VARCHAR(255),
          PHONE VARCHAR(255),
          BIRTHDATE VARCHAR(10),
          TITLE VARCHAR(255),
          DEPARTMENT VARCHAR(255),
          PRIMARY KEY (ID)
    	  ); 
    
    
    CREATE SEQUENCE EMPLOYEE_SEQ
     START WITH     100
     INCREMENT BY   1; 
     
  3. Click Run Script Run Script button and then click Commit Commit button.
  4. Copy the following script into the SQL worksheet to insert five employees, click Run Run button, and then click Commit Commit button.

    INSERT INTO EMPLOYEE (ID, FIRSTNAME, LASTNAME, EMAIL, PHONE, BIRTHDATE, TITLE, DEPARTMENT) VALUES (EMPLOYEE_SEQ.nextVal, 'Hugh', 'Jast', 'Hugh.Jast@example.com', '730-715-4446', '1970-11-28' , 'National Data Strategist', 'Mobility'); 
    INSERT INTO EMPLOYEE (ID, FIRSTNAME, LASTNAME, EMAIL, PHONE, BIRTHDATE, TITLE, DEPARTMENT) VALUES (EMPLOYEE_SEQ.nextVal, 'Toy', 'Herzog', 'Toy.Herzog@example.com', '769-569-1789','1961-08-08', 'Dynamic Operations Manager', 'Paradigm'); 
    INSERT INTO EMPLOYEE (ID, FIRSTNAME, LASTNAME, EMAIL, PHONE, BIRTHDATE, TITLE, DEPARTMENT) VALUES (EMPLOYEE_SEQ.nextVal, 'Reed', 'Hahn', 'Reed.Hahn@example.com', '429-071-2018', '1977-02-05', 'Future Directives Facilitator', 'Quality'); 
    INSERT INTO EMPLOYEE (ID, FIRSTNAME, LASTNAME, EMAIL, PHONE, BIRTHDATE, TITLE, DEPARTMENT) VALUES (EMPLOYEE_SEQ.nextVal, 'Novella', 'Bahringer', 'Novella.Bahringer@example.com', '293-596-3547', '1961-07-25' , 'Principal Factors Architect', 'Division'); 
    INSERT INTO EMPLOYEE (ID, FIRSTNAME, LASTNAME, EMAIL, PHONE, BIRTHDATE, TITLE, DEPARTMENT) VALUES (EMPLOYEE_SEQ.nextVal, 'Zora', 'Sawayn', 'Zora.Sawayn@example.com', '923-814-0502', '1978-03-18' , 'Dynamic Marketing Designer', 'Security'); 
 

Developing the REST Server

In this section, you create the REST Service and you use the NPM utility to download and build dependencies for your Node.js project.

  1. Open a console window and go to the folder where you want to store the Node.js application server.

    Console window - open folder
    Description of this image
  2. Run npm init to create the package.json file. At the prompt, enter the following values, confirm the values, and then press Enter:

    • Name: node-server
    • Version: 1.0.0 (or press Enter.)
    • Description: Employee RESTful application
    • Entry point: server.js
    • Test command (Press Enter.)
    • Git repository (Press Enter.)
    • Keywords (Press Enter.)
    • Author (Enter your name or email address.)
    • License (Press Enter.)
    Console window – create package.json
    Description of this image

    The package.json file is created and stored in the current folder. You can open it and modify it, if needed.

  3. In the console window, download, build, and add the Express framework dependency:

    npm install --save express
    Console window - add Express framework dependency
    Description of this image
  4. In the console window, install the body-parser dependency:

    npm install --save body-parser

    The body-parser dependency is a Node.js middleware for handling JSON, Raw, Text and URL encoded form data.

    Console window - install body-parse dependency
    Description of this image

    Note: If the console displays optional, dep failed or continuing output, ignore it. The output pertains to warnings or errors caused by dependencies on native binaries that couldn't be built. The libraries being used often have a JavaScript fallback node library, and native binaries are used only to optimize performance.

  5. Open the generated package.json file in a text editor, and verify its contents. It should look like this:

    View package.json
  6. Create a server.js file, open it in a text editor, and add the following require statements to use the node dependencies and the oracledb server component:

    var express = require('express');
    var bodyParser = require('body-parser');
    var oracledb = require('oracledb');
  7. Add a PORT variable equal either to the process.env.PORT environment variable or to 8089, if the environment variable isn't set:

    The PORT environment variable is set automatically by Oracle Application Container Cloud Service.

    var PORT = process.env.PORT || 8089;
  8. Create an app variable to use the express method:

    var app = express();
  9. Store the database connection properties that are equal to environment variables or defaults:

    The environment variables listed are set in Oracle Application Container Cloud Service automatically when you add the Database Cloud Service binding.

    var connectionProperties = {
    user: process.env.DBAAS_USER_NAME || "oracle",
    password: process.env.DBAAS_USER_PASSWORD || "oracle",
    connectString: process.env.DBAAS_DEFAULT_CONNECT_DESCRIPTOR || "localhost/xe"
    };
  10. Create the doRelease method to release the database connection:

    function doRelease(connection) {
    connection.release(function (err) {
    if (err) {
    console.error(err.message);
    }
    });
    }
  11. Configure your application to use bodyParser(), so that you can get the data from a POST request:

    // configure app to use bodyParser()
    // this will let us get the data from a POST
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json({ type: '*/*' }));
  12. Create a router object and assign it to the router variable:

    var router = express.Router();
  13. Add the following response headers to support calls from external clients:

    Note: Browsers and applications usually prevent calling REST services from different sources. If you run the client on Server A and the REST services on Server B, then you must provide a list of known clients in Server B by using the Access-Control headers. Clients check these headers to allow invocation of a service and prevent cross-site scripting attacks (XSS).

    router.use(function (request, response, next) {
    console.log("REQUEST:" + request.method + " " + request.url);
    console.log("BODY:" + JSON.stringify(request.body));
    response.setHeader('Access-Control-Allow-Origin', '*');
    response.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    response.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    response.setHeader('Access-Control-Allow-Credentials', true);
    next();
    });
  14. Create the GET method to get the list of employees:

    View code
  15. Create the GET method to return the list of employees that match the criteria.

    /**
     * GET /searchType/searchValue 
     * Returns a list of employees that match the criteria 
     */
    router.route('/employees/:searchType/:searchValue').get(function (request, response) {
      console.log("GET EMPLOYEES BY CRITERIA");
      oracledb.getConnection(connectionProperties, function (err, connection) {
        if (err) {
          console.error(err.message);
          response.status(500).send("Error connecting to DB");
          return;
        }
    	console.log("After connection");
    	var searchType = request.params.searchType;
    	var searchValue = request.params.searchValue;
    	  
        connection.execute("SELECT * FROM employee WHERE "+searchType+" = :searchValue",[searchValue],
          { outFormat: oracledb.OBJECT },
          function (err, result) {
            if (err) {
              console.error(err.message);
              response.status(500).send("Error getting data from DB");
              doRelease(connection);
              return;
            }
            console.log("RESULTSET:" + JSON.stringify(result));
            var employees = [];
            result.rows.forEach(function (element) {
              employees.push({ id: element.ID, firstName: element.FIRSTNAME, 
    		                   lastName: element.LASTNAME, email: element.EMAIL, 
    		                   phone: element.PHONE, birthDate: element.BIRTHDATE, 
    						   title: element.TITLE, dept: element.DEPARTMENT });
            }, this);
            response.json(employees);
            doRelease(connection);
          });
      });
    }); 
  16. Create the POST method to add employees:

    View code
  17. Create the PUT method to update the employee by ID:

    View code
  18. Create the DELETE method to remove employees by ID:

    View code
  19. Set up and start the server:

    app.use(express.static('static'));
    app.use('/', router);
    app.listen(PORT);

The completed server.js should look like this:

View server.js
 

Adding the HTML Client

In this section, you add the client files to your project and you update the index.html file to connect the client to your RESTful application.

  1. Create a folder named static in the root directory of your project.

  2. Unzip the employee-client.zip file in the static directory.

    Note: Make sure the index.html is in the static directory and not in a subfolder.

  3. Open the index.html in a text editor.

  4. Edit the server variable, set the URL of your application, and save the file.

    Note: Replace identity-domain with the entity domain of your cloud account.

    https://employees-service-identity-domain.apaas.us2.oraclecloud.com 
 

Preparing the Node.js Server Application for Cloud Deployment

To ensure that your server application runs correctly in the cloud, you must:

  • Bundle the application in a .zip file that includes all dependencies.
    Note: Don't bundle database drivers for Oracle Enterprise Cloud Service.
  • Include a manifest.json file that specifies the command which Oracle Application Container Cloud Service should run.
  • Ensure your application listens to requests on a port provided by the PORT environment variable. Oracle Application Container Cloud Service uses this port to redirect requests made to your application.
 

Creating the manifest.json File

When you upload your application to Oracle Application Container Cloud Service using the user interface, you must include a file called manifest.json in the application archive (.zip, .tgz, .tar.gz file). If you use the REST API to upload the application, this file is still required but doesn’t have to be in the archive.

  1. Create a manifest.json file.

  2. Open the manifest.json file in a text editor and add the following content:

    {
    "runtime":{
    "majorVersion":"4"
    },
    "command": "node server.js",
    "release": {},
    "notes": ""
    }

    The manifest.json file contains the target platform and the command to be run.

  3. Compress all the project files including the manifest.json file, the static folder, the server.js, and the node_modules folder in a file named node-employees-service.zip. Make sure that the node_modules folder doesn't have an OracleDB subfolder.

 

Creating the deployment.json file

In the deployment.json file you can specify how much memory to allocate to your application, how many application instances to create initially, additional environment variables, and service bindings to other Oracle Cloud services. For this tutorial you create the deployment.json file to add the Oracle Database Cloud Service binding.

Note: If you don't specify the values or the file is omitted, memory and instance defaults are used.

  1. Create a deployment.json file.

  2. Open the deployment.json file in a text editor and add the following content. Replace the values of name, username, and password with the credentials of your Oracle Database Cloud Service instance.

    {
      "services": [
        {
          "name": "service-name",
          "type": "DBAAS",
          "username": "your-username",
          "password": "your-password"
        }
      ]}
 

Deploying Your Application Using the REST API

 

Uploading Your Application to the Storage Service

Before you can deploy your application, you must copy it to the storage service. You need your Oracle Cloud service credentials (username, password, identity domain) to use the REST API. With your credentials, you create cURL scripts to upload your application to the storage service.

  1. Open a command-line window (or Terminal in Linux).

  2. Create a storage container using the following cURL command:

    Note: Replace the words in bold with your storage credentials.

    curl -i -X PUT \
      -u Username:Password \
      https://hostname/v1/Storage-Identity-Domain/employees-service
    
  3. Upload your application archive (node-employees-service.zip) in the storage container:

    curl -i -X PUT \
    -u Username:Password \
    https://hostname/v1/Storage-Identity-Domain/employees-service/node-employees-service.zip -T <Path-to-local-file>/node-employees-service.zip
    
 

Deploying Your Application to Oracle Application Container Cloud Service

To deploy your application, you need to include standard information in your script. The following example script shows placeholders for the required information:

url -i -X POST  \
  -u Username:Password \
  -H "X-ID-TENANT-NAME:Identity-Domain" \
  -H "Content-Type: multipart/form-data" \
  -F "name=employees-service" \
  -F "runtime=node" \
  -F "subscription=Monthly" \
  -F "deployment=Path-to-local-file/deployment.json" \
  -F "archiveURL=employees-service/node-employees-service.zip" \
  -F "notes=Node employees REST service application" \
  https://hostname/paas/service/apaas/api/v1.1/apps/Identity-Domain

Here are a few key points about this example:

  • -H specifies headers that are added to the HTTP request.
  • -F allows cURL to submit data like it's coming from a form (so, POST as the HTTP method).
  • archiveURL specifies where your archive file is located. The URL consists of your application's name, a slash, and the archive's file name.
  • region (Optional) If your account has access to Oracle Cloud Infrastructure regions, specify in this parameter the same region than the region where your Oracle Database Cloud Service instance was created.

 

Testing the REST service

  1. Open a web browser and enter the URL of the employee REST service.

    Note: Replace identity-domain with the entity domain of your cloud account.

    URL:

    https://employees-service-identity-domain.apaas.us2.oraclecloud.com/employees
    Firefox window - Employees Service
    Description of this image
  2. Remove the /employees part of the URL to execute the index.html.

    Employees client - Search page
    Description of this image
  3. Click Add New.

    Employees client - Search page
    Description of this image
  4. Fill the form and click Add.

    Employees client - Add new form
    Description of this image
  5. Select the card of the new employee.

    Employees client - Search page
    Description of this image
  6. Click Edit.

    Employees client - Details page
    Description of this image
  7. Change the value of the Department field and click Update.

    Employees client - Edit page
    Description of this image

    The employee card is updated.

    Employees client - Search page
    Description of this image
  8. Click the card of the employee and click Delete.

    Employees client - Details page
    Description of this image
  9. Click Delete and then click Ok to confirm.

    Delete confirmation
    Description of this image
    Deployments dialog box
    Description of this image
 

Want to Learn More?