Use REST API with Order Management Extensions

Apply these guidelines when your extension calls REST API.

Create Connector

  1. Go to Home > My Enterprise > Setup and Maintenance > Manage External Interface Web Service Details.

    You must use this task.

  2. Set these values:

    Attribute

    Value

    Connector Name

    QUERYPARAM

    Connector URL

    https://host:port/fscmRestApi/resources/latest/itemsV2

    User Name

    Enter the user name that you use to access REST API.

    Password

    Enter the password that you use to access REST API.

    Invocation Mode

    Synchronous Service

    Send Attachments No
    Response Processing Option Use the default value.

    For details, see Manage Connector Details Between Order Management and Your Fulfillment System.

  3. Use the invokeRestService method in your extension to call REST API.

    For details and examples, go to REST API for Oracle Supply Chain Management Cloud, expand Order Management, then click Sales Orders for Order Hub.

Use invokeRestService to Call REST API

Order Management will automatically select the correct version according to the arguments that you send in your extension.

JSON Object

Use this format when you script a JSON object:

invokeRestService(String integrationName, 
                  String restResourcePath, 
                  JSONObject jsonObj, 
                  String method,
                  Map<String, String> headers, 
                  Map<String, Object> queryParams, 
                  Map<String, Object> pathParams);

For example:

def response = context.invokeRestService("ItemsV2", "", null, "GET", headers, queryParams, pathParams);
def response = context.invokeRestService("InventoryReservations", "", jsonObject, "POST", headers, queryParams, pathParams);

JSON Array

Use this format when you script a JSON array:

invokeRestService(String integrationName, 
                  String restResourcePath, 
                  JSONArray jsonArray, 
                  String method,
                  Map<String, String> headers, 
                  Map<String, Object> queryParams, 
                  Map<String, Object> pathParams) ;

For example:

def response = context.invokeRestService("RestPatchConnector", "", jsonArrayObject, "PATCH", headers, queryParams, pathParams);

REST Request

You can use these parameters in invokeRestService's request:

Position Parameter Type Description
1 ConnectorName String Name of the connector, such as QUERYPARAM.
2 restResourcePath String Placeholder. Use an empty string: "".

You must include this value for the connector, but the extension's logic ignores is.

3 JsonObj JSON Object

Include your JSON's object payload for the request.

If you don't need a payload, then leave it empty. For example, for a GET request.

3 JsonArray JSON Array Include your JSON's array payload for the request.
4 Operation String

Specify one of these HTTP methods:

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE
5 Headers Map string, string Include a value pair for the HTTP header.
6 QueryParams Map string, object Specify your URL query parameters that you want to append to the URL. For example, status=ACTIVE.
7 PathParams Map string, object

Specify a variable that you want to use to replace a part of the URL path. For example:

https://host:port/fscmRestApi/resources/latest/itemsV2/{itemsV2UniqID}/child/ItemDFF

REST Response

Use these methods in invokeRestService's response to extract data and implement logic:

Method Type Description
getStatus() String Result of the call.

Contains SUCCESS or ERROR.

getResponseStatusCode() Integer

Standard HTTP status code.

For example, 200 for OK, 201 for Created, or 400 for Bad Request.

getPayload() JSON Object Contains the JSON object that you sent in REST request.
getPayloadArray() JSON Array Contains the JSON array that you sent in REST request.
getResponse() String Contains the response payload when the status is SUCCESS.
getErrorMessage() String Contains the response payload when the status is ERROR.

Get Example

This example uses a connector named ItemsV2 to get item details, and then writes the response into the Shipping Instructions attribute. It uses this connector URL:

https://host:port/fscmRestApi/resources/latest/itemsV2

The extension script uses seven parameters in invokeRestService, and it uses null values in the GET payload.

It creates this URL at run time:

https://host:port/fscmRestApi/resources/latest/itemsV2? q=ItemNumber=AS54888;OrganizationCode=V1&onlyData=true&fields=ItemNumber,ItemDescription

Here's the extension's script:

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException
import org.json.simple.JSONObject;

// 1. Filter the condition:
def poNumber = header.getAttribute("CustomerPONumber");
if (poNumber == null || poNumber != "ItemsV2") return;
String connectorName = "ItemsV2";

// 2. Specify the query parameters:
// Matches: ?q=ItemNumber=AS54888;OrganizationCode=V1&onlyData=true&fields=ItemNumber,ItemDescription
Map<String, Object> queryParams = new HashMap<>();
queryParams.put("q", "ItemNumber=AS54888;OrganizationCode=V1");
queryParams.put("onlyData", "true");
queryParams.put("fields", "ItemNumber,ItemDescription");
//Map string, object pathParams = new HashMap<>();
//pathParams.put("itemsV2UniqID", "00040000000EACED0005770800005B0A5D2711C80000000EACED000577");
//Assumes you want to use this connector url: https://host:port/fscmRestApi/resources/latest/itemsV2/{itemsV2UniqID}/child/ItemDFF

// 3. Use a GET request. Parameter 3 is empty for a GET:
def response = context.invokeRestService(connectorName, "", null, "GET", null, queryParams, null);

// 4. Process the result:
def status = response.getStatus();
def data = "Response Status : " + status + ", Response Status Code : " + response.getResponseStatusCode() + ". ";
if ("SUCCESS".equals(status)) {
  def resp = response.getResponse(); // Access the response payload
  // See whether the "items" in the array contain data:
  if (resp.get("items") != null && resp.get("items").length > 0) {
    // Extract data from the first item in the array
    def itemRow = resp.get("items")[0];
    def itemInfo = itemRow.get("ItemNumber") + "-" + itemRow.get("ItemDescription");
    data = data + itemInfo;
  } else {
    data = data + "Could not fetch item information using connector " + connectorName + " with query parameters " + queryParams;
  }
} else { // ERROR
  // Capture error details:
  data = data + " ErrorMessage : " + response.getErrorMessage() + " Response : " + response.getResponse();
}

// 5. Update Order Header
header.setAttribute("ShippingInstructions", data);

POST Example

This example uses a connector named InventoryReservations to create an inventory reservation. It uses this connector URL:

https://host:port/fscmRestApi/resources/latest/inventoryReservations/

The extension script uses seven parameters in invokeRestService, and it includes a JSON payload values in the POST request.

It creates this URL at run time:

https://host:port/fscmRestApi/resources/latest/itemsV2? q=ItemNumber=AS54888;OrganizationCode=V1&onlyData=true&fields=ItemNumber,ItemDescription

Here's the extension's script:

import oracle.apps.scm.doo.common.extensions.ValidationException;
import oracle.apps.scm.doo.common.extensions.Message;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;

// 1. Filter the condition:
def poNumber = header.getAttribute("CustomerPONumber");
if (poNumber != "InventoryReservations") return;
//Map string, object pathParams  = new HashMap<>();
//Map string, object queryParams = new HashMap<>();
Map<String, String> headers = new HashMap<>();
headers.put("REST-Framework-Version", "4");

// 2. Create the JSON Object's request payload:
JSONObject jObj = new JSONObject();
jObj.put("OrganizationId", 204);
jObj.put("ItemNumber", "AS54888");
jObj.put("ReservationQuantity", 10000000);
jObj.put("ReservationUOMCode", "Ea");
jObj.put("SupplySourceType", "On Hand");
jObj.put("DemandSourceType", "User Defined");
jObj.put("DemandSourceName", "27210");

// 3. Send a POST request:
def response = context.invokeRestService("InventoryReservations", "", jObj, "POST", headers, null, null);
// As an option, you can read all the attributes from the response:
List<Message> msgs = new ArrayList<Message>();
msgs.add(new Message( Message.MessageType.WARNING, "Input Payload : " + response.getPayload() ));
msgs.add(new Message( Message.MessageType.WARNING, "Input Payload Array : " + response.getPayloadArray() ));
msgs.add(new Message( Message.MessageType.WARNING, "Response Status : "  + response.getStatus() ));
msgs.add(new Message( Message.MessageType.WARNING, "Response Status Code : " + response.getResponseStatusCode() ));
msgs.add(new Message( Message.MessageType.WARNING, "Error Message : "  + response.getErrorMessage() ));
msgs.add(new Message( Message.MessageType.WARNING, "Success Message : " + response.getResponse() ));

// 4. Evaluate the response:
def statusCode = response.getResponseStatusCode();
if (statusCode == 200 || statusCode == 201) {
  // Success. Get the specific ID from the response:
  def successMessage = response.getResponse();
  msgs.add(new Message(Message.MessageType.WARNING, "Reservation done successfully with ReservationID : " + successMessage.get("ReservationId")));
} else {
  // Error. Parse the error details from the service:
  def errorMessage = response.getErrorMessage();
  msgs.add(new Message(Message.MessageType.ERROR, "Error Message - " + errorMessage));
  if ( errorMessage != null && errorMessage.trim().startsWith("{")) {
    JSONParser parser = new JSONParser();
    JSONObject root = (JSONObject) parser.parse(errorMessage);
    // Use errorDetails to navigate through the error structure.
    // The structure and the node names depend on what's in the REST response:
    JSONArray errorDetails = (JSONArray) root.get("o:errorDetails");
    if (errorDetails != null && !errorDetails.isEmpty()) {
      JSONObject errorInfo = (JSONObject) errorDetails.get(0);
      def errorCode =  errorInfo.get("o:errorCode");
      def detail =  errorInfo.get("detail");
      msgs.add(new Message(Message.MessageType.ERROR, "ErrorCode - " + errorCode + ". ErrorDetail - " + detail));
    }
  }
}

// 5. Send the collected messages to the caller:
if(!msgs.isEmpty()) throw new ValidationException(msgs);