19 ACTION INVOKE RESOURCE
The action invoke resource is used to either invoke an action on a particular domain object instance or a service, or to just validate arguments to an action without invoking it. It is usually obtained from the detailed representation §C18.2 returned by an action resource §C17.5.
The endpoint URL for this resource for a domain service is:
/services/{serviceId}/actions/{actionId}/invoke
where:
-
{serviceId}
is a unique identifier for the service -
{actionId}
is the action identifier
The endpoint URL for this resource for a domain object is:
/objects/{domainType}/{instanceId}/actions/{actionId}/invoke
where:
-
{domainType}
uniquely identifies the object’s type, and -
{instanceId}
uniquely identifies an object instance of that type -
{actionId}
is the action identifier
19.1 HTTP GET
Invoke an action and return a representation. Alternatively, validate the query arguments without invoking the action.
The action invoked must be query-only (does not modify any persisted objects); a typical example is to search for objects from a domain service repository.
The action cannot be void (it must return some representation).
19.1.1 Request
The request can either be to invoke the action, or to request validation of arguments using the reserved x-ro-validate-only query parameter §A3.2.
19.1.1.1 Query String
Query arguments should be formatted as a map (§A2.9.2), and encoded in the URL (§A2.9.2.3). Note that if any argument is a blob/clob, then its value must be in-lined (URL encoded for a blob) [1].
In addition, the following may optionally be included in the map:
19.1.2 Success Response
19.1.2.2 Headers
-
Content-Length:
-
size of the entity body
-
-
Content-Type (if returning a domain object):
-
application/json;profile="…/action-result";x-ro-domain-type="yyy"
-
where yyy indicates the domain type (for object representations, §A2.4.2);
-
the domain type id (if simple scheme)
-
URI of domain type (if formal scheme)
-
-
-
-
Content-Type (if returning a list of domain objects):
-
application/json;profile="…/action-result";x-ro-element-type="yyy"
-
where yyy indicates the domain type (for object representations, §A2.4.2);
-
the domain type id (if simple scheme)
-
URI of domain type (if formal scheme)
-
-
-
-
Content-Type (if returning a scalar or void):
-
application/json;profile="…/action-result"
-
-
Caching headers:
Note that an ETag is never returned for an action result. A client that wishes to modify the returned domain object must therefore re-retrieve it explicitly.
19.1.2.3 Body
As per §C19.4.
19.2 HTTP PUT
Invoke an action and return a representation if the action returns a result. Alternatively, validate the query arguments but do not invoke the action.
The action invoked must be idempotent (though may have side-effects).
An example might be Order#submit()
, which (depending on how the application logic is written) might have the same post-conditions irrespective of whether the order has already been submitted or not.
19.2.1 Request
19.2.1.2 Headers
-
Accept
-
application/json
-
application/json;profile="…/action-result"
-
-
If-Match
-
timestamp digest
-
obtained from ETag header of representation
-
-
19.2.2 Success Response
As per §C19.1.2.
19.3 HTTP POST
Invoke an action, and return a representation if the action returns a result. Alternatively, validate the query arguments but do not invoke the action. The action invoked can have side effects and need not be idempotent.
19.3.1 Request
19.3.1.2 Headers
-
Accept
-
application/json
-
application/json;profile="…/action-result"
-
-
If-Match
-
timestamp digest
-
obtained from ETag header of representation
-
-
19.3.2 Success Response
19.3.2.1 Status code
Successfully invoking an action with possible side effects can return either a 200 or a 201.
-
200 "OK"
-
the action was successfully executed.
-
-
201 "Created"
-
only permitted when the action returns a domain object (that is "resultType" json-property is "object")
-
indicates that this object was newly created.
-
19.3.2.2 Headers
-
Location (if returning 201):
-
URL of the newly-created action
-
-
Content-Length:
-
size of the entity body
-
-
Content-Type (if returning a domain object):
-
application/json;profile="…/action-result";x-ro-domain-type="yyy"
-
where yyy indicates the domain type (for object representations, §A2.4.2;
-
the domain type id (if simple scheme)
-
URI of domain type (if formal scheme)
-
-
-
-
Content-Type (if returning a list of domain objects):
-
application/json;profile="…/action-result";x-ro-element-type="yyy"
-
where yyy indicates the domain type (of the objects referenced in the list, §A2.4.2;
-
the domain type id (if simple scheme)
-
URI of domain type (if formal scheme)
-
-
-
-
Content-Type (if returning a scalar or void):
-
application/json;profile="…/action-result"
-
-
Caching headers:
Note that an ETag is never returned for an action result. A client that wishes to modify the returned domain object must therefore follow the self link on the in-lined object to retrieve that object directly as an object representation (which will then have an Etag).
19.3.2.3 Body
As per §C19.4. If a 201 is returned, the "resultType" json-property must be "object".
19.4 Representation
If the "x-ro-validate-only" query parameter was passed in and the validation succeeded, then no representation will be returned. Instead:
-
if the validation succeeded, then a 204 (success, no content) is returned
-
If the validation failed then a representation will be returned, with a status code 400 (bad request).
See §C13 for further details.
Otherwise (ie, if the invocation was not validate-only), then all action invocations will return an actionresult representation. This representation provides details of the action invocation, and (for non-void actions) also in-lines the representation of the result of the invocation.
For example:
{
"links": [ {
"rel": "self",
"href": "http://~/services/TaskRepository/actions/countUrgentTasksFor/invoke",
"type": "application/json;profile=\".../action-result\"",
"arguments": {
"employee": {
"href": "http://~/objects/EMP/090123"
}
}
}, ...
],
"resultType": ...
"value": ...,
"extensions": { ... }
}
where:
JSON-Property | Description |
---|---|
links |
list of links to other resources. |
links[rel=self] |
(optional) link to the action invocation resource that generated the representation (applies only to query-only actions) |
resultType |
either "object", "list", "scalar" or "void" result (optional) the action result itself. |
extensions |
additional metadata about the representation. |
The "self" link can be used as a bookmark so that the action can easily be resubmitted. However, the link is only included in the representation if the action is query-only. This is to prevent accidental bookmarking of links that if followed would result in side-effects.
The "resulttype" indicates whether there is an in-lined representation (for an action returning a domain object, a list, a scalar) or none (if void).
Finally, the "result" holds the representation of the returned domain object, list, or scalar. This is discussed in sections below.
19.4.1 Action returning a Domain Object
If the action invocation returns a domain object, then the actionresult representation will in-line the domain object’s representation (§C14.1):
For example, the following might be the result of invoking an action representing Customer
's favoriteProduct()
action:
{
"links": [ {
"rel": "self",
"href": "http://~/objects/CUS/123/actions/favoriteProduct/invoke",
"type": "application/json;profile=\".../action-result\"",
"arguments": {},
"method": "GET"
} ],
"resultType": "object", "
result": {
"links": [ {
"rel": "self",
"href": "http://~/objects/PRD/2468",
"type": "application/json;profile=\".../object\"",
"method": "GET"
}, ...
],
"members": { ... },
"extensions": { ... } ...
},
"extensions": { ... }
}
Note that this representation has two "self" links:
-
links[rel=self]
-
is the link to the action invocation.
-
-
result.links[rel=self]
-
is the link to the returned domain object.
-
If the action returned null, then the "result" json-property will still be present, but set to the JSON value null:
{
...
"resultType": "object",
"result": null,
...
}
19.4.2 Action Returning a List
If the action invocation returns a list, then the actionresult representation will in-line a list representation (§B11):
For example, the following might be the result of invoking an action resource §C17.5 representing CustomerRepository
's findBlacklistedCustomers()
action:
{
"links": [ {
"rel": "self",
"href": "http://~/services/CustomerRepository/actions/findBlackListedCustomers/invoke",
"type": "application/json;profile=\".../action-result\"",
"arguments": {},
"method": "GET"
} ],
"resultType": "list",
"result": {
"links": [ {
"rel": ".../element-type",
"href": "http://~/domain-types/CUS,
"type": "application/json;profile=\".../domain-type\"",
"method": "GET"
} ],
"value": [ {
"ref": ".../element",
"href": "http://~/objects/CUS/123",
"type": "application/json;profile=\".../object\"",
"method": "GET"
}, {
"ref": ".../element",
"href": "http://~/objects/CUS/456",
"type": "application/json;profile=\".../object\"",
"method": "GET"
}, ...
],
"extensions": { ... }
},
"extensions": { ... }
}
Actions that return no links typically are expected to return an empty list:
{
...
"resultType": "list",
"result": {
...
"value": [ ]
...
},
...
}
Although not recommended, it is also legal for actions to return a null list. In this case the "result" json-property will still be present, but will be set to the JSON value null:
{
...
"resultType": "list",
"result": null
...
}
19.4.3 Action returning a Scalar Value
If the action invocation returns a scalar, then the actionresult representation will in-line a scalar representation (§B12):
For example, the TaskRepository
's countUrgentTasksFor(Employee)
action might generate the following representation:
{
"links": [ {
"rel": "self",
"href": "http://~/services/TaskRepository/actions/countUrgentTasksFor/invoke",
"type": "application/json;profile=\".../action-result\"",
"arguments": {
"employee": {
"href": "http://~/objects/EMP/090123"
}
},
"method": "GET"
} ],
"resultType": "scalar",
"result": {
"links": [ {
"rel": ".../returntype",
"href": "http://~/domain-types/int,
"type": "application/json;profile=\".../domain-type\"",
"method": "GET"
} ],
"value": 25,
"extensions": { ... }
},
"extensions": { ... }
}
As for actions returning lists and domain objects, if the scalar return type is non-primitive and a null is returned, then the "result" json-property will be set to the JSON null value:
{
...
"resultType": "scalar",
"result": null ...
}
19.4.4 Action returning a Void
If the action invocation does not have a return type (known as a ‘void’ method in some programming languages), then the simple actionresult representation (with no in-lined representation) will be returned.
For example, the Customer
's toggleBlacklistStatus()
action might generate the following representation:
{
"links": [ {
"rel": "self",
"href": "http://~/objects/CUS/123/actions/toggleBlacklistStatus/invoke",
"type": "application/json;profile=\".../action-result\"",
"arguments": {},
"method": "GET"
}, ...
],
"resultType": "void",
"extensions": { ... }
}
Note that there is no "result" json-property.