Previous topic

Relations

Next topic

Structures

DOCUMENTATION
Last updated 28-Jun-2016

Operations

Introduction

Purpose

In cases, when you need to use API methods other than CRUD introduced in the resource model overview, all of them must be specified as operations (custom operations) in the corresponding type definition. For example, imagine an application has a service that is able to perform a calculation-intensive operation, and you need to expose it.

This can be declared in the type definition as follows:

{
    "operations": {
        "calculateSomething": {
            "path": "/calculateSomething/{paramX}",
            "verb": "GET",

            "response": {
              "type": "string"  // Some JSON-schema that describes the response
            },

            "parameters": {
                "paramX": { "kind": "path", "type": "string" },
                "paramA": { "kind": "query", "type": "integer" },
                "paramB": { "kind": "query", "type": "integer" }
            }
         }
    }
}

To invoke the operation with parameters paramX=”special”, paramA=1, paramB=2, the GET request will look as follows:

GET /aps/2/resources/<id>/calculateSomething/special?paramA=1&paramB=2

On receiving such a request, the APS controller identifies the application endpoint URL (<endpoint>) and the application service (<service>) that must process the operation, and then calls the application method as follows:

GET <endpoint>/<service>/<id>/calculateSomething/special?paramA=1&paramB=2

As shown in the above example, each operation includes a number of attributes, such as name, path, and verb.

Base CRUD Operations

The base CRUD operations, correspondingly provision, retrieve, configure, and unprovision, are defined similarly in the APS core resource schema and implemented by all other APS types. For example, the retrieve operation is defined as follows:

"retrieve": {
   "name": "retrieve",
   "verb": "GET",
   "path": "/"
}

In accordance with this definition, the following table presents examples of incoming REST requests for all four CRUD operations.

Name APS controller Application
provision
POST /aps/2/resources/
{JSON object}
POST /<endpoint>/<service>/
{JSON object}
retrieve GET /aps/2/resources/<id> GET /<endpoint>/<service>/<id>
configure
PUT /aps/2/resources/<id>
{JSON object}
PUT /<endpoint>/<service>/<id>
{JSON object}
unprovision DELETE /aps/2/resources/<id> DELETE /<endpoint/<service>/<id>

In the APS infrastructure, base CRUD operations are processed as presented in the following diagram.

../../../_images/operation-crud.png

The APS controller processes internally a base CRUD request, and then, except for the GET (retrieve operation) request, calls the corresponding method of the application. There is no need to call the retrieve application method, since all needed data is stored in the APS database.

Note

Since the APS controller processes the operation internally, the caller must have access to all of the following objects: the operation, the resource, and the property. Otherwise, it returns an error code.

Custom Operations

When a custom operation is required, the APS proxy service calls the corresponding application method without internal processing.

../../../_images/operation-custom.png

Note

Since the APS controller does not process the operation internally, the caller must have access only to the resource and the operation. Otherwise, it returns an error code.

Operation Attributes

The full list of operation attributes is presented in the table:

Attribute Value Required? Default Example
name string Yes N/A “calculateSomething” in the above example
path string Yes N/A “path”: “/calculateSomething/{paramX}”
verb
GET
PUT
POST
DELETE
Yes N/A “verb”: “GET”
response
JSON object
MIME type
Yes N/A
“response”: { “type”: “string”}
“response”: { “contentType”: “image/jpeg”}
errorResponse JSON object Yes N/A
“errorResponse”: {
“type”: “object”,
“properties”: {
“code”: “integer”,
“error”: “string”,
“message”: “string”
}
}
parameters JSON object
-
null
“parameters”: {
“param_name_1”: { “kind”: “path”, “type”: “string” },
“param_name_2”: { “kind”: “query”, “type”: “integer” }
}
static boolean
-
false “static”: true
access JSON object
-
N/A “access”: { “referrer”: false }

name

Value: string
Default: N/A
Method name is used in documentation and code generation. In the above example, the operation name is “calculateSomething”.

path

Value: string
Default: N/A
This attribute defines a path (relative to the resource instance root), which corresponds to the operation. It is possible to define parameters in the URL. In this case, names of the parameters must be presented in the path and embraced in {}, like: “{paramX}” in the above example.

Limitations

  1. The path value must be a string starting with a letter and containing letters, numbers, and underscores, i.e., it must match the regular expression [a-zA-Z][0-9a-zA-Z_]*.
  2. There should not be two operations that declare the same path/method.
  3. An operation cannot have a path that matches a relation name, for example, there should not be a path “/ves” if we have a relation “ves”.

verb

Value: GET, POST, PUT, or DELETE
Default: null
Defines an HTTP method required to invoke the operation. See [RFC-2616-sec9] for the detailed description of these standard methods.

response

Value: JSON object or MIME type
Default: null
response can be specified as a valid JSON schema, just like any entry of the Structures array. The following example shows how a declaration of the “string” type return would look like:
{
   "response": {
       "type": "string"
       }
}

Note

It is possible to refer to any type declared in the Structures section.

It is possible to declare a non-JSON format as a response. To do that, the contentType attribute that contains a declaration of a valid MIME Media Type [RFC-2046] must be used. An example of a method that returns image/jpeg data is:

{
    "response": {
        "contentType": "image/jpeg"
    }
}

Warning

Simultaneous usage of the contentType and type attributes is not supported and will produce an error, because the type implicitly declares the application/json MIME type.

errorResponse

Value: JSON object
Default: null
errorResponse works like the response element, but declares the return format that will be used in case of method failure. An example of an error structure may look like:
{
    "errorResponse": {
        "type": "object",
        "properties": {
            "code": "integer",
            "error": "string",
            "message": "string"
        }
    }
}

Note

It is NOT possible to declare a contentType element in the errorResponse.

parameters

Value: JSON object
Default: null
Parameters describe input data passed to the called operation. They are defined as follows:
{
   "parameters": {
       "arg1": {
           "kind": "query",
           "type": "long",
           "required": true
       },
       "arg2": {
           "kind": "body",
           "type": "MyType",
           "required": true
       }
   }
}

The parameters section may be empty if the operation does not require any parameters. A declared parameter can have the following attributes:

  • name uniquely identifies the parameter.

    {
       "parameters": {
         "param_name_1": { /* details */ },
         "param_name_2": { /* details */ },
         "param_name_3": { /* details */ }
        }
    }
    

    The name is explicitly sent in the URI if the kind attribute of the parameter is query.

  • kind specifies the way a parameter is passed to the application. It may be either path, query, or body:

    • path - the parameter is passed in the path part of the URL. Only the Primitives are supported.
    • query - the name and value of the parameter is passed as a query argument in the URL. Only the Primitives are supported.
    • body - the parameter is passed in the request body and can be a JSON object as defined in Structures or an object of any MIME Media Type .
  • A declaration of the parameter type is done using either the type or contentType attribute:

    • type declares if the parameter must be one of the Primitives (in case of path or query kind) or refers to one of Structures (in case of body kind) that defines the parameter format.

    • contentType requires the body kind and is used to declare non-JSON contents. The attribute must declare a valid MIME Media Type. An example of a method that receives image/jpeg data in the HTTP body is as follows:

      {
          "parameters": {
              "image": {
                "kind": "body",
                "contentType": "image/jpeg",
                "required": true
              }
          }
      }
      

      Warning

      Simultaneous usage of the contentType and type attributes is not supported and will produce an error since the type attribute implicitly declares the application/json MIME type.

  • required is an optional attribute that defines if the parameter is mandatory (true) for the operation or optional (false). The default value is false.

static

Value: boolean
Default: false
Defines the base URL that will be used for calling the method. By default, it is false, which means that the method URL is relative to the resource base URL. In the following examples, the resource collection URL is {base}/collection/.
{
  "verb": "GET",
  "path": "/test"
  /* "static" is "false" by default */
}

means:

GET {base}/collection/{ID}/test

If static is set to true, the method URL is relative to the collection URL:

{
  "verb": "GET",
  "path": "/test",
  "static": "true"
}

means:

GET {base}/collection/test

Such a declaration allows defining methods specific for the collection. For example, when a resource is created by the base provision operation, there is no resource ID yet, and therefore the operation is declared as static in the APS core resource schema.

access

Value: JSON object
Default: N/A
Allows or disallows access to the operation for different Security Roles. With the following definition, a referrer cannot run the start operation:
"operations": {
    "start": {
        "verb": "GET",
        "path": "/start",
        "response": {
            "contentType": "text/json",
            "type": "string",
            "items": null
        },
        "access": { "referrer": false }
    },
    ...
}

Examples

In the following examples, we will demonstrate how to use parameters of all three kinds : path, query, and body.

Sending JSON Object in Body

This example illustrates how to send a JSON object in HTTP body.

  • First, let us create a JSON schema for a parameter that will be passed in the body:

    "structures": {
       "MyType": {
          "type": "object",
          "properties": {
             "param1": {
                "type": "string"
             },
             "param2": {
                "type": "integer"
             }
          }
       }
    }
    
  • Now, we can define an operation with parameters of different kinds:

    "operations": {
       "calculateSomething": {
          "path": "/calculateSomething/{paramX}",
          "verb": "POST",
          "response": {"type": "string"},
          "parameters": {
              "paramX": { "kind": "path", "type": "string" },
              "paramA": { "kind": "query", "type": "long" },
              "paramB": { "kind": "query", "type": "long" },
              "bodyC":   { "kind": "body", "type": "MyType" }
          }
       }
    }
    
  • REST requests will send the first three parameters in the URI, while the forth parameter (JSON structure containing param1 and param2) will be sent in the message body as follows:

    POST /aps/2/resources/{ID}/calculateSomething/special?paramA=1&paramB=2
    Content-Length: 123
    Content-type: application/json
    
    {
        "param1" : "Testing parameter sent in body",
        "param2" : 1024
    }
    

Sending arbitrary Contents in Body

This example illustrates how to declare and then send a non-JSON object, e.g. plain text.

  • The operation is defined as:

    "operations": {
       "calculateSomething": {
          "path": "/calculateSomething/{paramX}",
          "verb": "POST",
          "response": {"type": "string"},
          "parameters": {
              "paramX":        { "kind": "path", "type": "string" },
              "paramA":        { "kind": "query", "type": "long" },
              "paramB":        { "kind": "query", "type": "long" },
              "description":   { "kind": "body", "contentType": "text/plain" }
          }
       }
    }
    
  • REST requests may look as follows:

    POST /aps/2/resources/{ID}/calculateSomething/special?paramA=1&paramB=2
    Content-Length: 3237
    Content-type: text/plain
    
    Description of parameters:
    o paramX presents...