Implement a Custom API for a Façade REST Service

When you develop a mobile application, you usually start with the user interface layer first, and then you connect your application with another application by using REST web services. This approach works well for small or simple applications. When applications are bigger, and you want connect with multiple back-end services, you can inadvertently introduce performance and security issues.

It's a best practice to start building a façade API layer between the external back-end services and the user interface to reduce the number of calls to the back-end services whenever possible. For example, your mobile application can execute a single call to the façade API layer which handles the calls to other REST services, and consolidates all the incoming data in a single response to your mobile application.

Create a Complete Custom API

To create a complete custom API using Oracle Mobile Hub.

Click open the side menu icon and select Development, and then APIs from the side menu. If an API was already created (whether in a Draft or a Published state), you'll see a list of APIs. If no custom APIs exist, then you'll see a page with the New API button. Click the API you already created, or click New API to get started.

Define Endpoints

You create resources to define the endpoints of your API. A resource is the crux of an API. It has a type, some data associated with it, a relationship to other resources, and contains one or more methods that act on it. A resource can be nearly anything: an image, a text file, a collection of other resources, a logical transaction, a procedure, etc.

  1. Click the Endpoints navigation link to begin.
  2. Click New Resource, and add some basic information.

    Each time you click New Resource, you create a top-level (root) resource. If you want to add a child (nested) resource, then click Add (+) next to the top-level resource. Click X to delete a resource.

    Note:

    See the icons under the Methods links? Each time you define a method for a resource, an icon for it appears under the Methods link. Use them as shortcuts to see which methods have already been defined for a resource. Click an icon to go directly to its definition on the Methods page.
  3. Provide the resource path, which is the URI (relative to the base URI). For example, if the base URI is /mobile/custom/audits/, then you could add the resource, findings, that is /mobile/custom/audits/findings.
  4. Provide the display name, which is a name for the resource that makes it easy to identify in the API documentation.
    Resources are listed by their display names on the left side of the API Test page.
  5. Provide a brief description of the resource.

    After you enter a description, the URI is displayed below the description field.

  6. (Optional) Provide a RAML resource type, which is the resource type (resourcesType:). You don't need to specify a resource type. If you want to use a resource type but you don't have one defined, then click the Types link and define one.

When you create a method for a resource, a symbol for that method appears below the Methods link. You can immediately see which methods are defined for a resource if you need to examine a resource definition. Click an icon to go directly to that method definition.

You can clear the clutter to locate a resource more quickly by switching to Compact Mode (it's to the right of New Resource). The compact display hides the resource description, resource type, and path.

Add Methods to Your Resources

Methods are actions that can be performed on a resource. The Methods page shows you one method at a time. After at least two methods are defined, you can click on the icon for a method at the top of the page to see its details.

  1. Add some methods to the resource by clicking Methods.

    If the resource you're defining methods for has path parameters, then they're displayed above Add Method.

    1. (Optional) Click Required if you want the path parameters to be passed with each method.
      The parameter name is displayed.
    2. Provide a display name for the parameter and example code.
    3. From the drop-down list, select the valid value type for the parameter.
  2. Click Add Method, and select the method that you want.

    After you select a method, it’s no longer listed in the method list because you use a method only once per resource (for example, you can't define two DELETE methods for a single resource). An icon for each method that you define is displayed at the top of the page. Click a method icon to go directly to its definition.

  3. (Optional) Enter a brief description of the method in the Description field.
  4. (Optional) Enter a display name for the method.
  5. (Optional) Provide any traits to apply to the method.

    If you don't have any resource traits defined, click Endpoints to go back to the main Resources page, and click the Traits link to define one. Traits let you define a collection of similar operations.

After you define methods for the resource, you can define the requests and responses for those methods.

Define a Request for the Method

Now that you've selected a method, define the request you're making of the service that you want to connect to. For instance, if you selected a POST method, then now you can define what to create. You do this by adding parameters and a request body, which contains the description of the data to send to the service.

  1. Click Request to define a request.
  2. Click Add Parameter and select a parameter type: Query or Header. Select Required if the parameter is required for the method.
    1. Give the parameter a name and a display name.
    2. Select a valid value type: String, Number, Integer, Date, or Boolean.
    3. (Optional) Provide a description of the parameter and an example you can use when you test the validity of the endpoint. For example, you could have a resource, audits, and add a query parameter, auditorID, that takes a number value, and another parameter, auditName, that takes a string value:
      /audits: 
        get: 
          description: | 
            Gets list of audits, organizations etc.     
          queryParameters: 
            auditorID:  
              id: Auditor ID
              description: | 
                display auditor identifier 
              type: integer 
              example: |
                1234
              required: false      
            auditName:
              displayName: auditName
              description: |
                Audit name
              example: "Payroll Process Audit"

      In this example, a GET method is defined with the query parameters, auditorID, and auditName.

    4. (Optional) Click More Properties to add nested properties to the parameter. Click Repeat to add multiples of the current parameter.
    5. Click Add Parameter to add another top-level parameter for the method.
  3. Depending on the method you selected, click Add Media Type and define the method body. The body contains the data that you're sending to the server. For instance if you’re defining a POST method, you’ll need to define the item you’re creating, such as a new customer listing or service request. If you’re defining a GET method, you don’t need to send a method body so you don’t need to specify a media type.
    1. Select the media type for your method body, that is the format of the message that you're sending, such as text, images, or web forms.
      Depending on the type (for instance, you wouldn't enter a schema for an image type), you have the option of adding a schema or an example, or both.

      When defining a schema, add only the data necessary for the purpose of the resource. That is, don’t add unnecessary data that will only slow down the transmission and potentially increase the potential for errors.

    2. (Optional) Click Schema, and enter a schema (in JSON format) in the editor pane. A schema is like a template for the body. It's what you use to define the contents of the message.
    3. (Optional) Click Example, and enter an example (in JSON format) in the editor pane, which is used by the mock implementation as a mock response for the method. Using mock data can help you to verify the behavior of your methods. The example shows mock values for the data being sent in the message body as defined in the POST method of the audits resource:
      body: 
        application/json: 
          example: | 
            { 
              "Title": "Leaking Water Heater",
              "Username": "joh1017",  
              "imageLink": "storage/collections/2e029813-d1a9-4957-a69a-fbd0d7431d77/objects/6cdaa3a8-097e-49f7-9bd2-88966c45668f?user=lynn1014", 
              "Notes": "my water heater is broken"
            }                               
      
  4. Click Add Media Type to add additional media types. If you decide that you don't want the method, then click X in the banner to delete it.

Define a Response for the Method

Depending on the request, you may or may not need a response. A response describes the process for returning results from the service. You might want to define a response that verifies that the data you requested was returned, or you might want a response that acknowledges whether or not the request was received. Defining a response is similar to defining a request. The main difference is that you'll need to select a status code to let you know the result of the connection.

  1. Click Response to define one or more responses.
  2. Click Add Response, and select the status code that you want returned.

    A status code of 200 is provided by default but if that isn’t the code you want, then select one from the drop-down list.

    • 2xx indicates that a successful connection.

    • 3xx indicates that a redirection occurred.

    • 4xx indicates that a user error occurred.

    • 5xx indicates that a server error occurred.

    To help whoever uses the API to understand the reason for a potential error in the API you’re configuring, use an HTTP status code to return code that best matches the error situation.

  3. Provide a description of what the code designates.
  4. Click Add Header, select a response Header or Query, provide the name of the header or query and a display name for the header, and the valid value type for the header.
  5. Click Add Media Type, and select the format of the response. Depending on the media type you select, you can add parameters, schemas, or examples just as you did for the Request body.
    1. For the text-based media type (for example, application/json or text/xml), click Schema to enter a schema (in JSON format) for the body.
      As with the request body, add only pertinent data to the response body. Don’t include more data than you actually need for the operation.
    2. Click Example to add mock data (in JSON format) for your response body. Use mock data to verify the behavior of your methods before testing with real data.
    3. For form-based media type (for example, multipart/form-data), click Add Parameter and select Required if the parameter is mandatory. Then provide a name and select a value type. Optionally, you can give your parameter a name.
    4. For image-based media type (for example, image/png), you don’t have to do anything because there are no schemas or attributes to provide.
The following example shows that a response for the POST method of the audits resource was created with a status code of 201 indicating a new resource was successfully created. The example also shows a return response format of application/json, a Location header that was added, and the message body containing mock data:
responses: 
  201: 
    description: | 
      The request has been fulfilled and resulted in a new resource 
      being created. The newly created resource can be referenced  
      by the URI(s)returned in the entity of the response, with the 
      most specific URI for the resource given by a Location header
      field.  

    headers:
      Location:
        displayName: Location
        description: |
          Identifies the location of the newly created resource.

        type: string
        example: |
          /20934

        required: true

    body: 
      application/json: 
        example: | 
          {
            "id": 20934,
            "title": "Lynn's Leaking Water Heater",
            "contact": {
               "name": "Lynn Adams",                 
               "street": "45 O'Connor Street",
               "city": "Ottawa", 
               "postalcode": "a1a1a1",
               "username": "johnbeta"
              },
           "status": "New",
           "driveTime": 30,
           "priority": "high",
           "notes": "My notes",
           "createdon": "2014-01-20 23:15:03 EDT",
           "imageLink": "storage/collections/2e029813-d1a9-4957-a69a-fbd0d74331d77/objects/6cdaa3a8-097e-49f7--9bd2-88966c45668f?user=lynn1014"
          }

When you define your response, you can decide to test your endpoints or click Endpoints in the navigation bar to return to the main Resources page. From there, you can proceed to another page in the API Designer to create a root, resource types or traits, or add API documentation.

If you decide you don't want the method, then click X in the banner to delete it.

Create a REST Connector API

Use the REST Connector API wizard to create, configure, and test your connector API.

To get a basic working connector API, you can provide as little as a name for the connector API and a URL to the external service.

From there, you can:

  • Define rules to form specific requests or responses for the data that you want to access.

  • Configure client-side security policies for the service that you’re accessing.

  • Test the connection and test the results of calls made to the connection.

You must create a custom API and implementation to enable your applications to call the connector APIs, and generate the API and implementation automatically. If you want to do this manually, you have to create a custom API with the appropriate resources, and then implement the custom code.

Set Up a Basic Connector

You can create a functioning connector by completing the first two pages in the REST Connector API wizard.

  1. Click open the side menu icon and select Development, and then APIs from the side menu.

  2. Click REST (if this is the first connector API to be created) or New Connector and from the drop-down list, select REST.

  3. Identify your new REST connector API by providing the following:

    1. API Display Name: The name as it will appear in the list of connector APIs.

    2. API Name: The unique name for your connector API.

      By default, this name is appended to the relative base URI as the resource name for the connector API. You can see the base URI below the API Name field.

      Other than a new version of this connector API, no other connector API can have the same resource name.

    3. Short Description: This description will be displayed on the Connectors page when this API is selected.

  4. Click Create.

  5. In the General page of the REST Connector API dialog box, set the timeout values:

    • HTTP Read Timeout: The maximum time (in milliseconds) that can be spent on waiting to read the data. If you don’t provide a value, the default value of 20 seconds is applied.

    • HTTP Connection Timeout: The time (in milliseconds) spent connecting to the remote URL. A value of 0mms means an infinite timeout is permitted.

      The HTTP timeout values must be less than the Network_HttpRequestTimeout policy, which has a default value of 40,000 ms.

      Note:

      If you have a mobile cloud administrator role in addition to your service developer role, you can open the policies.properties file to see the value for the network policies for the current environment from the Administrator view. Otherwise, ask your mobile cloud administrator for the values.
  6. Click Descriptor, and enter the connection information for the service.

    If you provide a Swagger descriptor URL, the available resources are identified and displayed, and you can select which ones you want.

    Note:

    Only standard internet access ports 80 and 443 are supported. Connection to a service can't be made using a custom port.
  7. Click Save.

  8. (Optional) Click Test, select authentication credentials, and make test calls to the service.

From there, you can further configure the connector in the following ways:

  • (If you have provided a descriptor on the Descriptor page) go to the Resources page, and select the methods for the exposed resources.

  • Define rules.

  • Set security policies.

To be sure your connector API configuration is valid, you should test it thoroughly (not just from the Connector API Test page) before publishing it. That is, you should also test the custom API (with its implementation) that uses this connector API. Essentially, if you’re ready to publish the connector API, you should also be ready to publish the custom API that calls it.

Set Rules

You set rules to define the interactions between your mobile app and a service. Rules provide a way for you to add default parameter values for all calls to resources on the service, calls to a specific proxy path, and calls for certain types of operations (verbs). This helps enforce consistent syntax of the URL string, saves the custom code developer from having to insert these values, and makes it possible to track the different calls through analytics.

You can create one or more rules. Each rule can have one or more parameters of type Query and Header.

If no rules are applied, all calls are passed through the proxy to the existing service.

  1. If the connector is not already open, click side menu icon and select Development and then APIs from the side menu.
  2. Select the connector API that you want to edit and click Open.
  3. Select Roles.
  4. Click New Rule.
  5. Click Add Parameter, and select a Query or Header parameter type and enter the query or header name, and its value.

    Note:

    Although you can define rules to set certain headers by default, the rules aren’t applied if the client that called the connector directly through custom code or indirectly, such as from a web browser or mobile app, has already set the same headers.

    In particular, setting the format of the request body is usually done in the custom code with the Content-Type header, not as a REST Connector rule. Similarly, setting the format of the response body is also done in the custom code with the Accept header, not as a REST Connector rule.

    You can add as many parameters to a rule as you want but it's better not to overload a rule with too many operations. A simpler rule construct is easier to troubleshoot.

  6. Expand Resources, and edit the remote URL to provide a resource for the rule to be applied to. The base URL value is what you entered in the setting basic information step and it can’t be edited.
  7. Select Do not apply to lower level resources if you want the rules applied only to the resource level specified in the Remote URL.
  8. (Optional) Unselect the HTTP methods that you don’t want applied to rules that you just defined. By default, all methods are selected.
  9. (Optional) Click New Rule to create another rule.

    Note:

    If you define a rule that conflicts with another rule, the first rule applied takes precedence and the conflicting rule is ignored.

    When you're done, click Save and then click Next (>) to go to the next step in configuring your connector API.

The description of the rule that you just defined is shown in the Rule banner just above the Default Parameters section. For example, let's say the following values were provided:

  • Remote URL = https://maps.googleapis.com/maps/api/directions/json?origin=los+angeles&destination=seattle

  • Local URI = myMapAPI

  • Rule with the following parameter: Query:key:A3FAEAJ903022

  • GET and PUT HTTP methods

The rule description would read as follows:

For GET to https://maps.googleapis.com/maps/api/directions/json?origin=los+angeles&destination=seattle available at myMapAPI/directions, Include Query:key=A3FAEAJ903022.

If no rules were created, the description would read:

For ALL METHODS to https://maps.googleapis.com/maps/api/directions available at myMapAPI, No default parameters will be applied.

Now you have a base URI that maps to the existing service. Using our example:

mobile/connector/myMapAPI/directions/json?origin=los+angeles&destination=seattle maps to https://maps.googleapis.com/maps/api/directions/json?origin=los+angeles&destination=seattle

Configure Security Policies and Override Properties

Before you finalize your connector API, you should consider how to handle its security. You can use either security policies or authorization headers. Selecting a security policy that describes the authentication scheme of the service to which you’re connecting to is the recommended approach.

Every security policy has properties, called overrides, that you can configure. One reason to override a policy configuration property is to limit the number of policies that you have to maintain: rather than creating multiple policies with slightly varied configurations, you can use the same generic policy and override specific values to meet your requirements.

To select a security policy and set the policy overrides:

  1. If the connector is not already open, click side menu icon and select Development, and then APIs from the side menu.
  2. Select the connector API that you want to edit and click Open.
  3. Select Security.
  4. Select the security policy from the list of available policies and click the right arrow to move it to the Selected Policies list.
    Select only a single policy for your connector API. A description of a selected policy is displayed below the list.
  5. Specify overrides, if applicable, to the selected policy if you don't want to use the default values.
    To override a property, enter or select a value other than the default.
  6. Click Save to save your work or Save and Close to save your work and exit the REST Connector API wizard.
  7. Click Next (>) to go to the next step.