X

An Oracle blog about Web Services and Security in the Fusion Cloud

  • March 10, 2017

Invoking HCM REST Services using JavaScript

Terence Munday
Application Architect

Overview

The Fusion HCM Cloud exposes REST services to interact with key business objects.  This article describes how to invoke these services using JavaScript and HTML.  The example focuses on the HCM Employee REST service and provides examples on how to query, filter response data and limit the number of records returned.  



System Requirements

Fusion HCM Rel 11+
Fusion user with privileges to invoke REST services
A Browser with JavaScript enabled

This example was developed using Mozilla Firefox (45.8.0)



JavaScript

I created several JavaScript functions that work in concert with one another to invoke HCM REST Services.  I've also created a simple HTML page that calls these functions and displays the output.  When I say simple, I mean simple...  When the page loads, JavaScript is executed to call the employee REST service and display the results.  I've also included several examples showing how to apply queries, set filters and limit the number of records retrieved.  For a complete reference, please see the official documentation: REST API for Oracle Global Human Resources Cloud.

The contents of rest-blog.js:

/*
invokeService

Parameters
----------
server      - The server/host name
endpoint    - The rest endpoint
querystring - The HTML query string.  This string can include query
              parameters and a variety of filters that control the
response
from the service.
username    - The fusion user with privileges to invoke REST APIs
password    - The user's password
requestDiv  - DOM element to display the request URI
responseDiv - DOM element to display the formatted response

Returns
-------
This function does not return anything.


Description
-----------

This is the main function that is called to invoke HCM REST Services.  The function builds the request URI (Universal Resource Identifier) using the server, endpoint and query string and displays the formatted URI string in the browser console and in the requestDiv element. 

A handler is created that will be called when the complete response from the service is received.  The response handler calls the JSON parse function to convert the response text to a JavaScript object.  The code uses this object to retrieve the number of records returned in the response.  The handler also calls the JSON stringify function to convert the response to a more readable string.  The string is then formatted so that it can be properly displayed in HTML.  The number of records retrieved and the formatted response are logged to the browser console and displayed in the responseDiv element.

Finally, the function calls the sendGetRequest() function, passing the request URI, credentials and response handler.

*/
function invokeService(server, endpoint, querystring, username, password,
requestDiv, responseDiv) {

    var uri = server + endpoint,
    handler = function() {
        return function (data) {
            var nRecs = '', obj, str;
            if (data) {
                obj = JSON.parse(data);
                str = JSON.stringify(data);
                str = str.substring(1, str.length - 1)
                           .replace(/\\n/g, '<br/>')
                           .replace(/\\"/g, '"');

                if (obj && obj.count) {
                    nRecs = 'Number of records returned: ' + obj.count;
                    console.log(nRecs);

                    nRecs = nRecs +
'<p>More records available? ' + (obj.hasMore ? 'Yes' : 'No') + '</p>';
                }

                str = (nRecs ? '<p>' + nRecs + '</p>' + str : str);
            }
            else {
                str = 'An error occurred.  Ensure the Request URI, username and password are correct';
            }

            console.log(data ? data : str);

            responseDiv.innerHTML = str;
        };
    }();

    if (querystring) {
        uri = uri + querystring;
    }

    requestDiv.innerHTML = uri;

    sendGetRequest(uri, username, password, handler);
}

/*
sendGetRequest

Parameters
----------
uri         - The request URI
username    - The fusion user with privileges to invoke REST APIs
password    - The user's password
handler     - the response handler function

Returns
-------
This function does not return anything.

Description
-----------
This function does the work of sending an HTTP GET request to the the rest endpoint on the server (the URI).  First, we call a function to create an XMLHttpRequest object.  The XMLHttpRequest object is used to send an asynchronous request to the server. 

The onreadystatechange function is created and assigned to the request object.  This function will be called asynchronously as response data is returned.  We pass our handler as a parameter to this function, creating whats known as a closure in JavaScript.  The Mozilla Development Network defines closures as:

"Closures are functions that refer to independent (free) variables (variables that are used locally, but defined in an enclosing scope). In other words, these functions 'remember' the environment in which they were created."

What this means is that the response handler function we created in the invokeService function and passed to this function will remember the variables referenced (e.g. responseDiv) when the handler was created.  

The onreadystatechange function is called progressively each time state changes.  The meaning of each state is as follows:

0 - UNSENT
1 - OPENED
2 - HEADERS_RECEIVED
3 - LOADING
4 - DONE

When the state changes to 4, communication with the server is complete.  The HTTP status is also returned along with each state change.  If the request is complete (state = 4 or  XMLHttpRequest.DONE) and the HTTP status is 200 (Success), then we call the handler method passing the responseText as a parameter to us to display the response in our HTML page. 

Note: Since the content type is set to application/json the response is returned in XMLHttpRequest.responseText NOT XMLHttpRequest.responseXML.

Next, we call the XMLHttpRequest open method to initialize the request with the HTTP GET method and the URI.  The last parameter to the this method indicates how the request should be processed.  Passing null indicates we want to process the response asynchronously.

Once the request is initialized, we can set the credentials in the Authentication HTTP header.  We call our setCredentials function to accomplish this. 

Note: There is a variation of the XMLHttpRequest open method that accepts a username and password.  The HCM REST services expect these values to be concatenated and base64 encoded, so we must set them explicitly.

Finally, we send the request to the server.  We pass null to the XMLHttpRequest send method because we are sending a GET request.  If this were a POST request, we would send the POST data as a parameter.

*/
function sendGetRequest(uri, username, password, handler) {
    var req = getXmlRequest()
    if (req == null) {
        console.log('Failed to get XMLHttpRequest object');
        return;
    }

    req.onreadystatechange = function(fn) {
        return function () {
            var status = ('readyState: ' + req.readyState + ', ' +
                          'status: ' + req.status + ' ' + req.statusText);
            console.log(status);

            if (req.readyState === XMLHttpRequest.DONE) {
                if (req.status === 200) {
                    fn(req.responseText);
                }
                else {
                    fn('');
                }            
            }
        };
    }(handler);

    req.open('GET', uri, true);

    if (username && password) {
        setCredentials(req, username, password);
    }

    req.send(null);
}

/*
setCredentials

Parameters
----------
req         - The initialized XMLHttpRequest object
username    - The fusion user with privileges to invoke REST APIs
password    - The user's password

Returns
-------
This function does not return anything.

Description
-----------
This function base64 encodes the username and password and sets the resulting string in the HTTP Basic Authentication header.

*/
function setCredentials(req, username, password) {
    var creds = window.btoa(username + ':' + password);
    req.setRequestHeader('Authorization', 'Basic ' + creds);
}    

/*
getXmlRequest

Parameters
----------
none

Returns
-------
XMLHttpRequest object

Description
-----------
This function creates and returns an XMLHttpRequest object that is compatible with the user's browser.

*/
function getXmlRequest() {
    var e1, e2;

    if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    }
    else if (window.ActiveXObject) {
        try {
            return new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e1) {
            try {
                return new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch (e2) {
                // fall through
            }                    
        }
    }
    return null;
}




HTML

This is a simple HTML document that demonstrates how to invoke the HCM Employee REST service.  It is only for demonstration purposes.  In a real application, you would never want to hardcode the username and password in the file...

To run the example, replace the server/host, endpoint, query string, username and password in the HTML.  

Below are several examples of query strings that demonstrate how to filter results and limit the amount of data returned.  Experiment with them to get a feel for how things work.

Example 1: No query string specified

querystring = ''

Since there are no query parameters or filters specified, all employees will be returned.  Actually, the service will only retrieve the first 25 records.  All data and links associated with the employee object will also be retrieved.

Example 2: retrieve selected fields and no links

querystring = '?fields=LastName,FirstName,PersonId&onlyData=true'

This example sets filters to identify the fields you want returned in the response.  It also specifies that only data, not links, should be returned.  Multiple filters are separated by the & symbol.  This request will return the LastName, FirstName and PersonId for the first 25 employees.  No links will be returned in the response.

Example 3: limit the number of records returned

querystring = '?fields=LastName,FirstName,PersonId&onlyData=true&limit=5'

This example does the same thing as the previous example, but sets a filter to limit the number of records returned to 5.

Example 4: paging - retrieve the second 5 employee records

querystring = '?fields=LastName,FirstName,PersonId&onlyData=true&offset=5&limit=5'

This example does the same thing as the previous example, but sets the offset filter to retrieve the second 5 employee records.  This is you page data from the service.

Example 5: query for spefic records

querystring ='?q=LastName=Miller'

This example sets a query parameter to retrieve employee records where the LastName is Miller.  All data and links will be returned.        

Example 6: query for specific records and filter the results

querystring = '?q=LastName=Miller&fields=LastName,FirstName,PersonId&onlyData=true'

This example adds filters to the to the previous example.  Only the LastName, FirstName and PersonId will be returned for records where the LastName is Miller.  No links are returned.

The HTML source in all of it's beauty ;)

<!DOCTYPE html>
<html>
<head>
<title>Invoking the HCM REST Employee Service</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type='text/javascript' src='rest-blog.js'></script>
<style type="text/css">
    body {
        font-family: Arial, Helvetica, sans-serif;
    }
</style>
</head>
<body>
    <h2>Invoking the HCM REST Employee Service</h2>

    <hr/>

    <h3>Overview</h3>
    <div>This is an example of how to invoke the HCM Employee REST Service.</div>

    <h3>Request</h3>
    <div id="rest-request"></div>

    <h3>Response</h3>
    <div id="rest-response"></div>

    <script>
        var

        // set this to your server/host
        server = '
<host>:<port>/',

        // set this to the rest service endpoint you want to invoke
        endpoint = 'hcmCoreApi/resources/11.1.11/emps/',

        // The query string
        querystring = '',

        // Fusion user with privileges to call HCM REST services
        username = '<fusion username>',

        // the user's password
        password = '<password>',

        // These are the div elements used to display the request and response
        requestDiv = document.getElementById('rest-request'),
        responseDiv = document.getElementById('rest-response');            

        // invoke the service using the variables defined above
        invokeService(
            server,
            endpoint,
            querystring,
            username,
            password,
            requestDiv,
            responseDiv
          );              

    </script>    

</body>
</html>




That's it!

You now have some JavaScript and HTML allowing you to invoke HCM REST services.  I hope you found the article informative and useful.



References

REST API for Oracle Global Human Resources Cloud Release 11
http://docs.oracle.com/cloud/farel11/globalcs_gs/FARWS/Data_Integration_Tools_and_REST_Services.html

REST API for Oracle Global Human Resources Cloud Release 12
http://docs.oracle.com/cloud/latest/globalcs_gs/FARWS/

Mozilla Development Network, Closures
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

Mozilla Development Network, XMLHttpRequest.readyState
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.