6 Advanced Tasks

You can use REST API to perform advanced operations such as obtaining a count of resource items in a resource collection, executing custom actions, and executing batch requests.

Returning the Estimated Count of Business Object Items

REST APIs support retrieving the estimated item count in the resource collection.

The following sample estimates the total records and queries the first two items in the Employee collection. The query parameter totalResults ensures the response payload contains the totalResults attribute.

Request

  • URL

    <base_url>/Employee?totalResults=true&limit=2

  • HTTP Method

    GET

  • Query Parameter

    totalResults

    This parameter when set to true will include the estimated item count in the response for the resource collection. Otherwise the count is not included. The default value is false.

  • Content-Type

    none

  • Payload

    none

Response

  • HTTP Code

    200

  • Content-Type

    application/vnd.oracle.adf.resourceitem+json

  • Payload

    {
      "items" : [ {
        "EmployeeId" : 101,
        "FirstName" : "Neena",
        "LastName" : "Smith",
        "Email" : "NSMITH",
        "JobId" : "AD_VP",
        "DepartmentId" : 90,
        "Salary" : 2000,
        "links" : [ {
          "rel" : "self",
          "href" : "<base_url>/Employee/NSMITH",
          "name" : "Employee",
          "kind" : "item"
        } ]
      }, {
        "EmployeeId" : 102,
        "FirstName" : "Lex",
        "LastName" : "De Haan",
        "Email" : "LDEHAAN",
        "JobId" : "AD_VP",
        "DepartmentId" : 90,
        "Salary" : 3000,
        "links" : [ {
          "rel" : "self",
          "href" : "<base_url>/Employee/LDEHAAN",
          "name" : "Employee",
          "kind" : "item"
        } ]
      } ],
      "totalResults" : 5,
      "count" : 2,
      "hasMore" : true,
      "limit" : 2,
      "offset" : 0,
      "links" : [ {
        "rel" : "self",
        "href" : "<base_url>/Employee",
        "name" : "Employee",
        "kind" : "collection"
      } ]
    }
    

Making Batch Requests

REST APIs support executing multiple operations in a single roundtrip using a batch request. The data is committed at the end of the request. However, if one request part in a batch request fails, then all changes are rolled back and an error response is returned.

A batch request can consist of a combination of create, update, delete, upsert, and get requests. The path parameter and the payload needs to be the same as what you use to invoke the request directly. The get method supports the same URL parameters in the batch request as a separate HTTP request.

The request URL path must not use encoding of the URI parts, for example, to identify a multi-part key. Using an encoded path in the request will result in an exception error.

The following sample illustrates a successful batch operation that executes operations in four parts: 1) update employee 101, 2) update employee 102, 3) update employee 103, 4) query employee 104.

Request

  • URL

    <base_url>

  • HTTP Method

    POST

  • Content-Type

    application/vnd.oracle.adf.batch+json

  • Payload

    {
    	"parts": [{
    		"id": "part1",
    		"path": "/Employee/101",
    		"operation": "update",
    		"payload": {
    			"Salary": 10000
    		}
    	}, {
    		"id": "part2",
    		"path": "/Employee/102",
    		"operation": "update",
    		"payload": {
    			"Salary": 10000
    		}
    	}, {
    		"id": "part3",
    		"path": "/Employee/103",
    		"operation": "update",
    		"payload": {
    			"Salary": 10000
    		}
    	}, {
    		"id": "part4",
    		"path": "/Employee?q=EmployeeId%3D101",
    		"operation": "get"
    	}]
    }

Response

  • HTTP Code

    200

  • Content-Type

    application/vnd.oracle.adf.batch+json

  • Payload

    {
    	"parts": [{
    		"id": "part1",
    		"path": "<base_url>/Employee/101",
    		"operation": "update",
    		"payload": {
    			"EmployeeId": 101,
    			"FirstName": "Neena",
    			"LastName": "Smith",
    			"Email": "NSMITH",
    			"JobId": "AD_VP",
    			"DepartmentId": 90,
    			"Salary": 10000,
    			"links": [{
    				"rel": "self",
    				"href": "<base_url>/Employee/101",
    				"name": "Employee",
    				"kind": "item"
    			} ]
    		}
    	}, {
    		"id": "part2",
    		"path": "<base_url>/Employee/102",
    		"operation": "update",
    		"payload": {
    			"EmployeeId": 102,
    			"FirstName": "Lex",
    			"LastName": "De Haan",
    			"Email": "LDEHAAN",
    			"JobId": "AD_VP",
    			"DepartmentId": 90,
    			"Salary": 10000,
    			"links": [{
    				"rel": "self",
    				"href": "<base_url>/Employee/102",
    				"name": "Employee",
    				"kind": "item"
    			} ]
    		}
    	}, {
    		"id": "part3",
    		"path": "<base_url>/Employee/103",
    		"operation": "update",
    		"payload": {
    			"EmployeeId": 103,
    			"FirstName": "Alexander",
    			"LastName": "Hunold",
    			"Email": "AHUNOLD",
    			"JobId": "IT_PROG",
    			"DepartmentId": 60,
    			"Salary": 10000,
    			"links": [{
    				"rel": "self",
    				"href": "<base_url>/Employee/103",
    				"name": "Employee",
    				"kind": "item"
    			} ]
    		}
    	}, {
    		"id": "part4",
    		"path": "<base_url>/Employee",
    		"operation": "get",
    		"payload": {
    			"EmployeeId": 101,
    			"FirstName": "Neena",
    			"LastName": "Smith",
    			"Email": "NSMITH",
    			"JobId": "AD_VP",
    			"DepartmentId": 90,
    			"Salary": 10000,
    			"links": [{
    				"rel": "self",
    				"href": "<base_url>/Employee/101",
    				"name": "Employee",
    				"kind": "item"
    			} ]
    		}
    	}]
    }

Working with Error Responses

Error responses can be obtained in the form of a JSON payload in the form of HTTP status codes and error messages.

In addition to HTTP status codes and error messages, it is possible to obtain exception details in the response when your request is enabled to use REST API framework version 4 and the request is made for either application/vnd.oracle.adf.error+json or application/json media types. With framework version 4, the response will be in the form an exception detail payload which provides the following benefits to the web application:

  • If multiple errors occur in a single request, the details of each error are presented in a hierarchical structure.

  • An application-specific error code may be present that identifies the exception corresponding to each error.

  • An error path may be present that identifies the location of each error in the request payload structure.

Note:

The exception detail may or may not present certain details, such as the application-specific error code and the request payload’s error path.

For example, compare the error response for a POST submitted with a payload that contains the following incorrectly formatted date field when framework version 3 (or earlier) is enable and when framework version 4 (or later) is enabled.

{    "EmpNum" : 5027,
     "EmpName" : "John",
     "EmpHireDate" : "not a date"
}

Standard Error Response, Version 3 and earlier

Without framework version 4, no response payload is generated and instead only a single error message that does not reference the request payload will be returned in the response.

"An instance of type oracle.jbo.domain.Date cannot be created from string not a date. The string value must be in format YYYY-MM-DDTHH:MI:SS.sss+hh:mm."

Exception Payload Error Response, Version 4 and later

With framework version 4 enabled, the following exception detail payload is generated for the response. The payload includes the usual HTTP status code and formats the details of one or more exceptions in an array structure.

{    "title" : "Bad Request",
    "status" : "400",
    "o:errorDetails" : [ {
     "detail" : "An instance of type oracle.jbo.domain.Date cannot be created from string not a date. 
               The string value must be in format YYYY-MM-DDTHH:MI:SS.sss+hh:mm.",
       "o:errorCode" : "26099",
       "o:errorPath" : "/EmpHireDate"
    } ]
 }

Understanding the Exception Payload Error Response

The exception detail payload will be generated for a REST API error response when the following conditions exist:
  • REST API framework version is version 4.

  • Either application/vnd.oracle.adf.error+json or application/json is the media type for the response.

The exception detail payload is a JSON object with the following structure:

{   "title" : "Message as per HTTP status code",
    "status" : "HTTP error code",
    "o:errorDetails" : [
     ...
        {
            "detail" : "Message of detail error",
            "o:errorCode" : "error code"
            "o:errorPath" : "JSON pointer to the location of the error in the request payload"
        },
        ...
    ]
}

You opt into the exception payload as the error responses by using framework version 4 and making a request for either the application/vnd.oracle.adf.error+json media type or application/json media type.

Note that within the exception payload o:errorDetails can vary as per the number and the types of errors encountered. Additionally, the error code and error path are not guaranteed to be present in the response payload and should not be relied upon by web applications.

Obtaining an Exception Payload Error Response

REST APIs support obtaining exception details in the response when the request is made with an appropriate media type.

Starting with version 4 of the REST API framework, web applications may obtain an error response with a detailed exception payload.

The following sample attempts to create the department object with a new department item. However, for this example the request fails because the item for the department already exists.

Notice in the exception payload the o:errorDetails array provides the error path for where the error occurred in the request object; however, these particular details may not always be available to web applications.

Request Example 1

  • URL

    <base_url>/Department

  • HTTP Method

    POST

  • Accept Header

    application/vnd.oracle.adf.resourceitem+json,application/json

  • Payload

    {
    	"DeptNum" : 50,	
    	"DeptName" : "SALES",
    }

Response Example 1

  • HTTP Code

    400

  • Content-Type

    application/json

  • Payload

    {
       "title" : "Bad Request",
       "status" : "400",
       "o:errorDetails" : [ {
          "detail" : "A department with the same name already exists. Please provide a different name.",
          "o:errorCode" : "Dept_Rule_0"
      } ]
    }

The following sample attempts to create the department object with a new department item. However, for this example the request fails because the employee names entered exceed the number of characters allowed by the validation rule defined for the EmpName field.

Request Example 2

  • URL

    <base_url>/Department

  • HTTP Method

    POST

  • Accept Header

    application/vnd.oracle.adf.resourceitem+json,application/vnd.oracle.adf.error+json

  • Payload

    {
       "DeptNum" : 52,       
       "DeptName" : "newDept522",
       "Employee" : [ {
            "EmpNum" : 501,
            "EmpName" : "MILLERSxxxxxxxxxxxxxxxxx"
        }, {
            "EmpNum" : 502,
            "EmpName" : "JONESPxxxxxxxxxxxxxxxxx"
          } ]
    }

Response Example 2

  • HTTP Code

    400

  • Content-Type

    application/vnd.oracle.adf.error+json

  • Payload

    {
       "title" : "Bad Request",
       "status" : "400",
       "o:errorDetails" : [ {
          "detail" : "Value MILLERSxxxxxxxxxxxxxxxxx for field EmpName exceeds the maximum length allowed.",
          "o:errorCode" : "27040",
          "o:errorPath" : "/Employee/0/EmpName"
       }, {
          "detail" : "Value JONESPxxxxxxxxxxxxxxxxx for field EmpName exceeds the maximum length allowed.",
          "o:errorCode" : "27040",
          "o:errorPath" : "/Employee/1/EmpName"
       } ]
    }

The following sample attempts to perform a batch operation. However, for this example the batch operation fails for the reasons shown in the exception detail payload of the error response.

Request Example 3

  • URL

    <base_url>

  • HTTP Method

    POST

  • Content-Type Header

    application/vnd.oracle.adf.batch+json

  • Payload

    {
        "parts": [
            {
                "id": "part1",
                "path": "/Employee",
                "operation": "create",
    	    "payload" : {
    		"EmpNum" : 1299,
    		"EmpJob" : "CLERK",
    		"EmpMgr" : 7566,
    		"EmpHireDate" : null,
    		"EmpSal" : 245,
    		"EmpComm" : 0,
    		"EmpDeptNum" : 30
    	    }
            },
            {
                "id": "part2",
                "path": "/Employee",
                "operation": "create",
                "payload": {
                    "EmpNum" : 7589,
    		"EmpName" : "SampleEmpxxxxxxxxxxxxxxxxxx",
    		"EmpJob" : "CLERK",
    		"EmpMgr" : 7566,
    		"EmpHireDate" : null,
    		"EmpSal" : 245,
    		"EmpComm" : 0,
    		"EmpDeptNum" : 30
                }
            },
            {
                "id": "part3",
                "path": "/Department",
                "operation": "create",
                "payload": {
                   "DeptNum" : 52,       
                   "DeptName" : "newDept522",
                   "Employee" : [
                       {
                           "EmpNum" : 7588,
                           "EmpName" : "SampleEmpxxxxxxxxxxxxxxxxxx",
                           "EmpJob" : "CLERK",
                           "EmpMgr" : 7566,
                           "EmpHireDate" : null,
                           "EmpSal" : 245,
                           "EmpComm" : 0,
                           "EmpDeptNum" : 30
                       }
                   ]
               }
           },
    	{
                "id": "part4",
                "path": "/Department/10/child/Loc",
                "operation": "get"
            },
    	{
                "id": "part5",
                "path": "/Department?invQP=invVal",
                "operation": "get"
            },
    	{
                "id": "part6",
                "path": "/Department/54",
                "operation": "delete"
            },
    	{
                "id": "part7",
                "path": "/Department/54",
                "operation": "get"
            }
        ]
    }

Response Example 3

  • HTTP Code

    400

  • Content-Type

    application/vnd.oracle.adf.error+json

  • Payload

    {
    	"title" : "Bad Request",
    	"status" : "400",
    	"o:errorDetails" : [ {
    		"detail" : "URL request parameter invQP cannot be used in this context.",
    		"o:errorCode" : "27520"
    	}, {
    		"detail" : "Attribute EmpName in Emp is required.",
    		"o:errorCode" : "27014",
    		"o:errorPath" : "/parts/0"
    	}, {
    		"detail" : "Value SampleEmpxxxxxxxxxxxxxxxxxx for field EmpName exceeds the maximum length allowed.",
    		"o:errorCode" : "27040",
    		"o:errorPath" : "/parts/1/payload/EmpName"
    	}, {
    		"detail" : "Attribute EmpName in Emp is required.",
    		"o:errorCode" : "27014",
    		"o:errorPath" : "/parts/1"
    	}, {
    		"detail" : "Value SampleEmpxxxxxxxxxxxxxxxxxx for field EmpName exceeds the maximum length allowed.",
    		"o:errorCode" : "27040",
    		"o:errorPath" : "/parts/2/payload/Employee/0/EmpName"
    	}, {
    		"detail" : "Attribute EmpName in AM.Dept_empWorksIn_deptToEmpQA_EmpViewDef is required.",
    		"o:errorCode" : "27014",
    		"o:errorPath" : "/parts/2"
    	}, {
    		"detail" : "Not Found",
    		"o:errorCode" : "11404",
    		"o:errorPath" : "/parts/3"
    	} ]
    }

Obtaining the Standard Error Message Response

REST APIs support generating an error message that describes the validation or system error when the request is made with REST API framework versions 1 through 3 enabled.

Before version 4 of the REST API framework, the error response returns a single error message and HTTP status code. Version 4 and later allows web applications to obtain an error response with a detailed exception payload.

The following sample attempts to update the Departments resource with a new department resource item. However, for this example the update fails because the item for the department already exists. The response is an error message because REST API framework version 4 (or later) is not enabled.

Request Example Made With Framework Version 3

  • URL

    http://server/demo/rest/11.2/Departments

  • HTTP Method

    POST

  • Content-Type

    application/vnd.oracle.adf.resourceitem+json

  • Accept Header

    application/vnd.oracle.adf.resourceitem+json,application/json

  • Payload

    {
    	"DeptNum" : 50,	
    	"DeptName" : "SALES",
    }

Response Example From Framework Version 3

  • HTTP Code

    400

  • Error Response

    A department with the same name already exists. Please provide a different name.

Enable Polling for Endpoint Requests

If you run into timeout issues when working with business objects, you might want to enable polling for long-running endpoint requests.

Polling is useful in many contexts involving long-running processes, where you run the risk of breaking the client/server connection because of gateway or browser timeouts. A process can be long running, say, when your application integrates with external services, perhaps through a trigger that makes API calls to an external service. It can also involve endpoint requests that import a large volume of data from a file or from one database (development, staging, or live) to another during your application's lifecycle. Most data-related endpoint requests, including those to create, query, update, and delete business object data, are long-running processes that can benefit from polling.

You can enable polling by adding the vb-poll=true query parameter to an endpoint request URL. Now when the client makes an endpoint request, the server—instead of waiting for the request to complete and then return an HTTP response (status 200 or otherwise)—returns an HTTP response (status 202) with details of a new URL for the client to poll. This allows the server to continue processing the request in the background and the client to poll the new URL as and when it wants to find out if the request is complete and get the response (or error).

To enable polling for long-running endpoint requests:

  1. Add the vb-poll=true query parameter to your endpoint request URL, for example:

    POST https://server.example.com/ic/builder/rt/hrapp/1.0/resources/data/Employee?vb-poll=true

  2. When you receive the HTTP response with status 202, look for the Polling-Location header whose value will be the polling URL.

    The client can poll this URL and check the response, which will either contain the Polling-Location header to indicate that the process is still running, or will be the final response.

    When the long-running process completes, the response remains available for a limited time period, after which it is removed. The process itself is not affected by this, but the result is not available beyond this period—two minutes by default. The client should take this setting into account when determining the frequency of polling requests.