Creating an Interface part to access a REST service

You define an EGL Interface part in a file that is made available to the requester of that service. The Interface part can be in the same EGL package or can be imported from a separate package.

An EGL Interface part includes one or more function prototypes, which are descriptions of how to write code to access a given service operation. A function prototype includes the operation name, parameters (if any), and a return type (if any). The prototype does not include the logic of the operation, which is available in the service only.

The Interface part of an EGL REST-RPC service is simpler than an Interface part for a third-party REST service.

Interface part for accessing an EGL REST-RPC service

This example shows an Interface part for accessing an EGL REST-RPC service. The example includes a single function prototype:
Interface EmployeeService
   Function GetEmployeeDetail(employeeCode STRING IN, 
                              employeeSalary FLOAT OUT, 
                              employeeStatus STRING INOUT) 
            returns(myEmployeeRecordPart);
end

You can specify various EGL data types and can use the modifiers IN, OUT, and INOUT.

To create the Interface part in the EDT IDE:
  1. In the Project Explorer view, right-click the EGL file that defines the service
  2. Click EGL Services > Extract EGL Interface.
  3. In the New EGL Interface part window, specify the appropriate details, and click Finish.

Interface part for accessing a third-party REST service

This example shows Interface part for accessing a third-party REST service:
Interface WeatherForecast
   Function GetWeatherByZipCode(zipcode string in) returns(myRecordPart)
      {@GetRest{uriTemplate="/GetWeatherByZipCode?zipCode={zipcode}",
                requestFormat = JSON,
                responseFormat = JSON}};
end
If the purpose of the Interface part is to describe the operations that are available in a third-party REST service (not an EGL REST-RPC service), you must specify an annotation for each function prototype. The name of the annotation indicates the HTTP verb that is used to access the service:
  • For the GET method, the name is GetREST.
  • For the POST method, the name is PostREST.
  • For the PUT method, the name is PutREST.
  • For the DELETE method, the name is DeleteREST.

Those annotations are called the xREST annotations because the same three fields are in each, as described in the xREST annotations section of this topic.

In the service-invocation statement that is used to access a third-party REST service, the argument that is passed to a given function parameter has one of two purposes:
  • Usually, the argument provides a value that the requester includes in the URI. This usage is shown later in this topic, in the description of the xREST annotations. Those values are not passed to the service logic; they are values that are embedded in the URI. In particular, if the annotation is GetREST, all of the arguments that are assigned to the function parameters are used to construct the URI.
  • In the case of one argument (at most), the argument is a representation that is processed by the service; for example, a record that contains values used to create a database-table row. Here are details:
    • If the annotation is PostREST or PutREST for a given operation, the additional argument must be present, and the related parameter is called the representation parameter.
    • The argument also might be required if the annotation is DeleteREST. The need for such an argument depends on the service provider.
If the function prototype has a parameter that is not identified in the uriTemplate annotation field (for PostREST, PutREST, or DeleteREST), that parameter is a representation parameter. Either of the following cases is an error:
  • Specifying more than one representation parameter
  • Specifying a representation parameter when GetREST is in use

For restrictions on the arguments sent to a service, see “Restrictions in the prototypes used for service access.”

You do not need to create an Interface part. Instead, you can use IRest, which is an Interface part that is provided for you and that can be the basis of a variable that is used to access a third-party REST service. For more information about that Interface part, see “Using a provided Interface for a third-party REST service.”

xREST annotations used for third-party REST services

Each of the xREST annotations has these fields: uriTemplate, requestFormat, and responseFormat.

uriTemplate
A string, or template, that in most cases outlines a relative URI, which identifies the last qualifiers in the URI that are used to access the service.
The first URI qualifiers are specified in one of the following ways:
  • When you declare a variable based on the Interface part, you can identify an entry in a deployment descriptor. In this case, an initial value for the URI is in the deployment descriptor, and at configuration time, a code installer can change that value.
  • You can update the URI at run time, as described in "Binding an access variable dynamically.”

If you do not set the URI, the value of the uriTemplate annotation field includes the complete URI. In most cases, the value of the uriTemplate field has two aspects:

  • The value of the uriTemplate field can include a constant value. Those characters are present in or after every URI that is used to access the function. In the previous example, the value of uriTemplate includes a query variable, and the constant value is as follows:
       /GetWeatherByZip?zipcode= 
    If the example is changed to include a path variable instead of the query string, the constant value is as follows:
       /GetWeatherByZip/
  • The value of the uriTemplate annotation can include path variables and query variables. The previous example includes a single query variable:
       {zipcode}
    For the original example with a query string, here is a relative URI and value that are used to access the service:
    /GetWeatherByZip?zipcode=02135
    If the template includes a path variable instead of a query string, here is a relative URI:
    /GetWeatherByZip/02135

    The EGL runtime code automatically completes a URI encoding on each substitution value that is specified in a service invocation statement, with one exception.

    For example, if your service-invocation statement indicates that the value for a given substitution variable is "Jeff Smith", the EGL runtime code converts the string to "Jeff%20Smith" so that the URI is valid. However, if the value of a substitution value begins with http, the EGL runtime code does no URI encoding because the service-invocation statement is specifying an argument that provides a complete URI. If you are responsible for URI encoding, review the documentation on the httpLib.convertToURLEncoded system function.

The default value of the uriTemplate field is an empty string so that, by default, you can specify the complete URI by setting the base URI.

requestFormat
A value that indicates the format of the representation that is sent to the service:
  • XML, to indicate that the format is Extensible Markup Language
  • NONE, to indicate that the representation is a string, or a value that is compatible with a string, and is sent as is
  • JSON, to indicate that the format is JavaScript Object Notation
  • FORM, to indicate that the format is form data, which is a record composed of argument-value pairs. In the following example of the content sent to the service, each pair is separated from the next by an ampersand (&):
    division=Consumer&dept=Sales
    For a given field in the Record part that is the basis of form data, you can specify the FormName annotation. You can use that annotation to work with an argument name that is an EGL reserved word or is not valid in EGL. Here is an example use of the FormName annotation:
    record anyRecord
       continue boolean {FormName="continue-content"};
    end
    The runtime code uses the value of the FormName annotation as the name of the argument transmitted to the service. Here is a representation that might be sent to the service:
    continue-content=yes

    The default value of the FormName annotation is the name of the record field. In this example, the default is continue.

    You cannot override the value of the FormName annotation when you declare a record that is based on the Record part.

If the representation is a record, the following statements apply:
  • The default value of requestFormat is XML.
  • JSON is also valid.
  • FORM is valid only if every field in the record is of type STRING or is of a type that is assignment-compatible with STRING. FORM is not valid if the record references another record.
responseFormat
A value that indicates the format of the representation that is returned to the requester:
  • XML, to indicate that the returned representation is in XML format
  • NONE, to indicate that the returned representation is a string
  • JSON, to indicate that the returned representation is in JSON format

If the return value in the Interface part function prototype is a string or a value that is compatible with a string, the default value of responseFormat is NONE, which is the only valid format. If the return value is a record, the default value of responseFormat is XML, and JSON is also valid.

You can specify an xREST annotation without assigning values to the annotation fields:
Interface IEmployeeService
   Function GetEmployeeDetail() returns(myRecordPart)
      {@GetRest{}};
end
The lack of annotation fields indicates these behaviors:
  • You must provide the complete REST service URI, such as http://www.ibm.com/myservice, without providing detail in the Interface part. For information about the three choices for specifying the base URI, see the description of uriTemplate in this topic.
  • If the representation parameter (or, for the GetREST annotation, the return value) is a string, the EGL runtime code does no conversion. You must handle the conversion and can use any of the following functions for that purpose:
    • JSONLib.convertFromJSON
    • JSONLib.convertToJSON
    • XMLLib.convertFromXML
    • XMLLib.convertToXML
  • If the representation parameter is a record, the EGL runtime code converts the related argument to Extensible Markup Language (XML) format.
  • For the GetREST annotation, if the return value is a record, the EGL runtime code converts that record from XML format.
.