diff --git a/docs/odata-json-format/odata-json-format.html b/docs/odata-json-format/odata-json-format.html index 046ff018..0ac47d76 100644 --- a/docs/odata-json-format/odata-json-format.html +++ b/docs/odata-json-format/odata-json-format.html @@ -1493,11 +1493,280 @@

19 Batch Requests and Responses

19.1 Batch Request

+

A JSON batch request body consists of a single JSON object that MUST contain the name/value pair requests and MAY contain annotations. It does not contain the context control information.

+

The value of requests is an array of request objects, each representing an individual request. Note: an individual request MUST NOT itself be a batch request.

+

A request object MUST contain the name/value pairs id, method and url, and it MAY contain the name/value pairs atomicityGroup, dependsOn, if, headers, and body.

+

The value of id is a string containing the request identifier of the individual request, see OData-Protocol. It MUST NOT be identical to the value of any other request identifier nor any atomicityGroup within the batch request.

+

Note: the id name/value pair corresponds to the Content-ID header in the multipart batch format specified in OData-Protocol.

+

The value of method is a string that MUST contain one of the literals delete, get, patch, post, or put. These literals are case-insensitive.

+

The value of url is a string containing the individual request URL. The URL MAY be an absolute path (starting with a forward slash /) which is appended to scheme, host, and port of the batch request URL, or a relative path (not starting with a forward slash /).

+

If the first segment of a relative path starts with a $ character and is not identical to the name of a top-level system resource ($batch, $crossjoin, $all, $entity, $root, $id, $metadata, or other system resources defined according to the OData-Version of the protocol specified in the request), then this first segment is replaced with the URL of the entity created by or returned from a preceding request whose id value is identical to the value of the first segment with the leading $ character removed. The id of this request MUST be specified in the dependsOn name/value pair.

+

Otherwise, the relative path is resolved relative to the batch request URL (i.e. relative to the service root).

+

The value of atomicityGroup is a string whose content MUST NOT be identical to any value of id within the batch request, and which MUST satisfy the rule request-id in OData-ABNF. All request objects with the same value for atomicityGroup MUST be adjacent in the requests array. These requests are processed as an atomic operation and MUST either all succeed, or all fail.

+

Note: the atomicity group is a generalization of the change set in the multipart batch format specified in OData-Protocol.

+

The value of dependsOn is an array of strings whose values MUST be values of either id or atomicityGroup of preceding request objects; forward references are not allowed. If a request depends on another request that is part of a different atomicity group, the atomicity group MUST be listed in dependsOn. In the absence of the optional if member a request that depends on other requests or atomicity groups is only executed if those requests were executed successfully, i.e. with a 2xx response code. If one of the requests it depends on has failed, the dependent request is not executed and a response with status code of 424 Failed Dependency is returned for it as part of the batch response.

+

The if member can specify an alternative condition for executing the dependent request. Its value MUST be URL expression (see OData-URL) that evaluates to a Boolean value. The URL expression syntax is extended and additionally allows

+ +

Services SHOULD advertise support of the if member by specifying the property RequestDependencyConditionsSupported in the Capabilities.BatchSupport term applied to the entity container, see OData-VocCap. If a service does not support request dependencies, the dependent request MUST fail with 424 Failed Dependency, and if the dependent request is part of an atomicity group, all requests in that group fail with 424 Failed Dependency with no changes applied.

+

The value of headers is an object whose name/value pairs represent request headers. The name of each pair MUST be the lower-case header name; the value is a string containing the header-encoded value of the header. The headers object MUST contain a name/value pair with the name content-type whose value is the media type.

+

The value of body can be null, which is equivalent to not specifying the body name/value pair.

+

For media type application/json or one of its subtypes, optionally with format parameters, the value of body is JSON.

+

For media types of top-level type text, for example text/plain, the value of body is a string containing the value of the request body.

+

For all other media types the value of body is a string containing the base64url-encoded value of the request body. In this case the body content can be compressed or chunked if this is correctly reflected in the Transfer-Encoding header.

+

A body MUST NOT be specified if the method is get or delete.

+
+

Example 48: a batch request that contains the following individual requests in the order listed

+
    +
  1. A query request
  2. +
  3. An atomicity group that contains the following requests: +
      +
    • Insert entity
    • +
    • Update entity
    • +
  4. +
  5. A second query request
  6. +
+

Note: For brevity, in the example, request bodies are excluded in favor of English descriptions inside <> brackets and OData-Version headers are omitted.

+
POST /service/$batch HTTP/1.1
+Host: host
+OData-Version: 4.01
+Content-Type: application/json
+Content-Length: ###
+
+{
+  "requests": [
+    {
+      "id": "0",
+      "method": "get",
+      "url": "/service/Customers('ALFKI')"
+    },
+    {
+      "id": "1",
+      "atomicityGroup": "group1",
+      "dependsOn": [ "0" ],
+      "method": "patch",
+      "url": "/service/Customers('ALFKI')",
+      "headers": {
+        "Prefer": "return=minimal"
+      },
+      "body": <JSON representation of changes to Customer ALFKI>
+    },
+    {
+      "id": "2",
+      "atomicityGroup": "group1",
+      "method": "post",
+      "url": "/service/Customers",
+      "body": <JSON representation of a new Customer entity>
+    },
+    {
+      "id": "3",
+      "dependsOn": [ "group1" ],
+      "method": "get",
+      "url": "/service/Products"
+    }
+  ]
+}
+

19.2 Referencing New Entities

+

The entity returned by a preceding request can be referenced in the request URL of subsequent requests.

+
+

Example 49: a batch request that contains the following operations in the order listed:

+ +
POST /service/$batch HTTP/1.1
+Host: host
+OData-Version: 4.01
+Content-Type: application/json
+Content-Length: ###
+
+{
+  "requests": [
+    {
+      "id": "1",
+      "method": "post",
+      "url": "/service/Customers",
+      "body": <JSON representation of a new Customer entity>
+    },
+    {
+      "id": "2",
+      "dependsOn": [ "1" ]
+      "method": "post",
+      "url": "$1/Orders",
+      "body": <JSON representation of a new Order>
+    }
+  ]
+}
+

19.3 Referencing an ETag

+
+

Example 50: a batch request that contains the following operations in the order listed:

+ +
POST /service/$batch HTTP/1.1
+Host: host
+OData-Version: 4.01
+Content-Type: application/json
+Content-Length: ###
+
+{
+  "requests": [
+    {
+      "id": "1",
+      "method": "get",
+      "url": "/service/Employees(0)",
+      "headers": {
+        "accept": "application/json"
+      }
+    },
+    {
+      "id": "2",
+      "dependsOn": [ "1" ],
+      "method": "patch",
+      "url": "/service/Employees(0)",
+      "headers": {
+        "if-match": "$1"
+      },
+      "body": {
+        "Salary": 75000
+      }
+    }
+  ]
+}
+

19.4 Processing a Batch Request

+

All requests in an atomicity group represent a single change unit. A service MUST successfully process and apply all the requests in the atomicity group or else apply none of them. It is up to the service implementation to define rollback semantics to undo any requests within an atomicity group that may have been applied before another request in that same atomicity group failed.

+

The service MAY process the individual requests and atomicity groups within a batch request, or individual requests within an atomicity group, in any order that is compatible with the dependencies expressed with the dependsOn name/value pair. Individual requests and atomicity groups that do not specify the dependsOn name/value pair may be processed in parallel. Clients that are only interested in completely successful batch responses MAY specify the preference continue-on-error=false to indicate that the service need not spend cycles on further processing once an error occurs in one of the dependency chains. In this case the response MAY omit response objects for requests that have not been processed. If the preference continue-on-error is not specified, or specified with a value of true, all requests are processed according to their dependencies.

+

The service MUST include the id name/value pair in each response object with the value of the request identifier that the client specified in the corresponding request, so clients can correlate requests and responses.

19.5 Batch Response

+

A JSON batch response body consists of a single JSON object that MUST contain the name/value pair responses and MAY contain annotations. It does not contain the context control information.

+

The value of responses is an array of response objects, each representing an individual response.

+

A JSON batch response MAY be a partial result containing the nextLink control information. This allows services to chunk results into manageable pieces, or to return results for already processed requests and continue processing the remaining individual requests while waiting for the client to fire a GET request to the next link.

+

In a response to a batch request using the multipart format defined in OData-Protocol the response objects MUST appear in the same order as required for multipart batch responses because the Content-ID header is not required outside of change sets. Response objects corresponding to requests that specify a Content-ID header MUST contain the id name/value pair, and the value of id MUST be the value of the Content-ID header of the corresponding request. This is necessarily the case for requests contained within a change set. Responses to requests within a change set MUST contain the atomicityGroup name/value pair with a value common within a change set and unique across change sets.

+

In a response to a batch request using the JSON batch request format specified in the preceding section the response objects MAY appear in any order, and each response object MUST contain the id name/value pair with the same value as in the corresponding request object. If the corresponding request object contains the atomicityGroup name/value pair, it MUST also be present in the response object with the same value.

+

If any response within an atomicity group returns a failure code, all requests within that atomicity group are considered failed, regardless of their individual returned status code. The service MAY return 424 Failed Dependency for statements within an atomicity group that fail or are not attempted due to other failures within the same atomicity group.

+

A response object MUST contain the name/value pair status whose value is a number representing the HTTP status code of the response to the individual request.

+

The response object MAY contain the name/value pair headers whose value is an object with name/value pairs representing response headers. The name of each pair MUST be the lower-case header name; the value is a string containing the header-encoded value of the header.

+

The response object MAY contain the name/value pair body which follows the same rules as within request objects.

+

If the media type is not exactly equal to application/json (i.e. it is a subtype or has format parameters), the headers object MUST contain a name/value pair with the name content-type whose value is the media type.

+

Relative URLs in a response object follow the rules for relative URLs based on the request URL of the corresponding request. Especially: URLs in responses MUST NOT contain $-prefixed request identifiers.

+
+

Example 51: referencing the batch request example 48 above, assume all the requests except the final query request succeed. In this case the response would be

+
{
+  "responses": [
+    {
+      "id": "0",
+      "status": 200,
+      "body": <JSON representation of the Customer entity with key ALFKI>
+    },
+    {
+      "id": "1",
+      "status": 204
+    },
+    {
+      "id": "2",
+      "status": 201,
+      "headers": {
+        "location": "http://host/service.svc/Customer('POIUY')"
+      },
+      "body": <JSON representation of the new Customer entity>
+    },
+    {
+      "id": "3",
+      "status": 404,
+      "body": <Error message>
+    }
+  ]
+}
+

19.6 Asynchronous Batch Requests

+

A batch request that specifies the respond-async preference MAY be executed asynchronously. This means that the "outer" batch request is executed asynchronously; this preference does not automatically cascade down to the individual requests within the batch. After successful execution of the batch request the response to the batch request is returned in the body of a response to an interrogation request against the status monitor resource URL, see section "Asynchronous Requests" in OData-Protocol.

+

A service MAY return interim results to an asynchronously executing batch. It does this by responding with 200 OK to a GET request to the monitor resource and including a nextLink control information in the JSON batch response, thus signaling that the response is only a partial result. A subsequent GET request to the next link MAY result in a 202 Accepted response with a location header pointing to a new status monitor resource.

+
+

Example 52: referencing the example 47 above again, assume that the request is sent with the respond-async preference. This results in a 202 response pointing to a status monitor resource:

+
HTTP/1.1 202 Accepted
+Location: http://service-root/async-monitor-0
+Retry-After: ###
+

When interrogating the monitor URL only the first request in the batch has finished processing and all the remaining requests are still being processed. The service signals that asynchronous processing is "finished" and returns a partial result with the first response and a next link. The client did not explicitly accept application/http, so the response is "unwrapped" and only indicates with the AsyncResult header that it is a response to a status monitor resource:

+
HTTP/1.1 200 Ok
+AsyncResult: 200
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+  "responses": [
+    {
+      "id": "0",
+      "status": 200,
+      "body": <JSON representation of the Customer entity with key ALFKI>
+    }
+  ],
+  "@nextLink": "...?$skiptoken=YmF0Y2gx"
+}
+

Client makes a GET request to the next link and receives a 202 response with the location of a new monitor resource.

+
HTTP/1.1 202 Accepted
+Location: http://service-root/async-monitor-1
+Retry-After: ###
+

After some time a GET request to the monitor resource returns the remainder of the result.

+
HTTP/1.1 200 Ok
+AsyncResult: 200
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+  "responses": [
+    {
+      "id": "1",
+      "status": 204
+    },
+    {
+      "id": "2",
+      "status": 201,
+      "headers": {
+        "location": "http://host/service.svc/Customer('POIUY')"
+      },
+      "body": <JSON representation of the new Customer entity>
+    },
+    {
+      "id": "3",
+      "status": 404,
+      "body": <Error message>
+    }
+  ]
+}
+
+

In addition to the above interaction pattern individual requests within a batch with no other requests depending on it and not part of an atomicity group MAY be executed asynchronously if they specify the respond-async preference and if the service responds with a JSON batch response. In this case the response array contains a response object for each asynchronously executed individual request with a status of 202, a location header pointing to an individual status monitor resource, and optionally a retry-after header.

+
+

Example 53: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously

+
HTTP/1.1 200 OK
+OData-Version: 4.01
+Content-Length: ###
+Content-Type: application/json
+
+{
+  "responses": [
+    {
+      "id": "0",
+      "status": 202,
+      "headers": {
+        "location": "http://service-root/async-monitor-0"
+      }
+    },
+    {
+      "id": "1",
+      "status": 204
+    }
+  ]
+}
+

20 Instance Annotations

Annotations are an extensibility mechanism that allows services and clients to include information other than the raw data in the request or response.

@@ -1506,20 +1775,20 @@

single primitive or collection value, the annotations for the value appear next to the value property and are not prefixed with a property name.

-

Example 48:

-
{
-  "@context": "http://host/service/$metadata#Customers",
-  "@com.example.customer.setkind": "VIPs",
-  "value": [
-    {
-      "@com.example.display.highlight": true,
-      "ID": "ALFKI",
-      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
-      "CompanyName": "Alfreds Futterkiste",
-      "Orders@com.example.display.style#simple": { "order": 2 }
-    }
-  ]
-}
+

Example 54:

+
{
+  "@context": "http://host/service/$metadata#Customers",
+  "@com.example.customer.setkind": "VIPs",
+  "value": [
+    {
+      "@com.example.display.highlight": true,
+      "ID": "ALFKI",
+      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
+      "CompanyName": "Alfreds Futterkiste",
+      "Orders@com.example.display.style#simple": { "order": 2 }
+    }
+  ]
+}

20.1 Annotate a JSON Object

When annotating a name/value pair for which the value is represented as a JSON object, each annotation is placed within the object and represented as a single name/value pair.

@@ -1546,25 +1815,25 @@

21.1 E

Service implementations SHOULD carefully consider which information to include in production environments to guard against potential security concerns around information disclosure.

Error responses MAY contain annotations in any of its JSON objects.

-

Example 49:

-
{
-  "error": {
-    "code": "err123",
-    "message": "Unsupported functionality",
-    "target": "query",
-    "details": [
-      {
-      "code": "forty-two",
-      "target": "$search",
-      "message": "$search query option not supported"
-      }
-    ],
-    "innererror": {
-      "trace": [...],
-      "context": {...}
-    }
-  }
-}
+

Example 55:

+
{
+  "error": {
+    "code": "err123",
+    "message": "Unsupported functionality",
+    "target": "query",
+    "details": [
+      {
+      "code": "forty-two",
+      "target": "$search",
+      "message": "$search query option not supported"
+      }
+    ],
+    "innererror": {
+      "trace": [...],
+      "context": {...}
+    }
+  }
+}

21.2 In-Stream Error

In the case that a service encounters an error after sending a success status to the client, the service MUST leave the response malformed. This can be achieved by immediately stopping response serialization and thus omitting (among others) the end-object character of the top-level JSON object in the response.

@@ -1575,10 +1844,10 @@

21.2
  • Control characters (00 to 1F and 7F) and Unicode characters beyond 00FF within JSON strings are encoded as \uXXXX or \uXXXX\uXXXX (see RFC8259, section 7)

  • -

    Example 50: note that this is one HTTP header line without any line breaks or optional whitespace

    -
    OData-error: {"code":"err123","message":"Unsupported
    -functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    -query option not supported"}]}
    +

    Example 56: note that this is one HTTP header line without any line breaks or optional whitespace

    +
    OData-error: {"code":"err123","message":"Unsupported
    +functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    +query option not supported"}]}

    21.3 Error Information in a Success Payload

    Services may return error information within a success payload; for example, if the client has specified the continue-on-error preference.

    diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index e0d6fb27..7513cee2 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -2832,16 +2832,519 @@ MUST also support clients passing an empty request body for this case. ## 19.1 Batch Request +A JSON batch request body consists of a single JSON object that MUST +contain the name/value pair `requests` and MAY contain +[annotations](#InstanceAnnotations). It does not contain the +`context` control information. + +The value of `requests` is an array of request objects, each +representing an individual request. Note: an individual request MUST NOT +itself be a batch request. + +A _request object_ MUST contain the name/value pairs `id`, +`method` and `url`, and it MAY contain the +name/value pairs `atomicityGroup`, `dependsOn`, `if`, `headers`, and `body`. + +The value of `id` is a string containing the request +identifier of the individual request, see +[OData-Protocol](#ODataProtocol). It MUST NOT be identical to the value +of any other request identifier nor any `atomicityGroup` +within the batch request. + +Note: the `id` name/value pair corresponds to the +`Content-ID` header in the multipart batch format specified +in [OData-Protocol](#ODataProtocol). + +The value of `method` is a string that MUST contain one of +the literals `delete`, `get`, `patch`, `post`, or `put`. +These literals are case-insensitive. + +The value of `url` is a string containing the individual +request URL. The URL MAY be an absolute path (starting with a forward +slash `/`) which is appended to scheme, host, and port of the +batch request URL, or a relative path (not starting with a forward slash `/`). + +If the first segment of a relative path starts with a `$` +character and is not identical to the name of a top-level system +resource (`$batch`, `$crossjoin,` `$all,` `$entity`, `$root,` +`$id`, `$metadata`, or other system resources +defined according to the `OData-Version` of the protocol +specified in the request), then this first segment is replaced with the +URL of the entity created by or returned from a preceding request whose +`id` value is identical to the value of the first segment +with the leading `$` character removed. The `id` +of this request MUST be specified in the `dependsOn` +name/value pair. + +Otherwise, the relative path is resolved relative to the batch request +URL (i.e. relative to the service root). + +The value of `atomicityGroup` is a string whose content MUST +NOT be identical to any value of `id` within the batch +request, and which MUST satisfy the rule `request-id` in +[OData-ABNF](#ODataABNF). All request objects with the same value for +`atomicityGroup` MUST be adjacent in the +`requests` array. These requests are processed as an atomic +operation and MUST either all succeed, or all fail. + +Note: the atomicity group is a generalization of the change set in the +multipart batch format specified in [OData-Protocol](#ODataProtocol). + +The value of `dependsOn` is an array of strings whose values +MUST be values of either `id` or `atomicityGroup` +of preceding request objects; forward references are not allowed. If a +request depends on another request that is part of a different atomicity +group, the atomicity group MUST be listed in `dependsOn`. In +the absence of the optional `if` member a request that +depends on other requests or atomicity groups is only executed if those +requests were executed successfully, i.e. with a `2xx` +response code. If one of the requests it depends on has failed, the +dependent request is not executed and a response with status code of +`424 Failed Dependency` is returned for it as part of the batch response. + +The `if` member can specify an alternative condition for +executing the dependent request. Its value MUST be URL expression (see +[OData-URL](#ODataURL)) that evaluates to a Boolean value. +The URL expression syntax is extended and additionally allows + +- `$/$succeeded` + to check if the referenced request has succeeded +- `$` + to reference the response body of the referenced request +- `$/` + to reference a part of the response body + +Services SHOULD advertise support of the `if` member by +specifying the property +`RequestDependencyConditionsSupported` in the +[`Capabilities.BatchSupport`](https://github.com/oasis-tcs/odata-vocabularies/blob/master/vocabularies/Org.OData.Capabilities.V1.md#BatchSupport) +term applied to the entity container, see +[OData-VocCap](#ODataVocCap). If a service does not +support request dependencies, the dependent request MUST fail with +`424 Failed Dependency`, and if the dependent request is part of an +atomicity group, all requests in that group fail with +`424 Failed Dependency` with no changes applied. + +The value of `headers` is an object whose name/value pairs +represent request headers. The name of each pair MUST be the lower-case +header name; the value is a string containing the header-encoded value +of the header. The `headers` object MUST contain a name/value +pair with the name `content-type` whose value is the media type. + +The value of `body` can be `null`, which is +equivalent to not specifying the `body` name/value pair. + +For media type `application/json` or one of its subtypes, +optionally with format parameters, the value of `body` is JSON. + +For media types of top-level type `text`, for example +`text/plain`, the value of `body` is a string +containing the value of the request body. + +For all other media types the value of `body` is a string +containing the base64url-encoded value of the request body. In this case +the body content can be compressed or chunked if this is correctly +reflected in the `Transfer-Encoding` header. + +A `body` MUST NOT be specified if the `method` is `get` or `delete`. + +::: example +Example 48: a batch request that contains +the following individual requests in the order listed + + 1. A query request + 2. An atomicity group that contains the following requests: + - Insert entity + - Update entity + 3. A second query request + +Note: For brevity, in the example, request bodies are excluded in favor +of English descriptions inside `<>` brackets and +`OData-Version` headers are omitted. +```json +POST /service/$batch HTTP/1.1 +Host: host +OData-Version: 4.01 +Content-Type: application/json +Content-Length: ### + +{ + "requests": [ + { + "id": "0", + "method": "get", + "url": "/service/Customers('ALFKI')" + }, + { + "id": "1", + "atomicityGroup": "group1", + "dependsOn": [ "0" ], + "method": "patch", + "url": "/service/Customers('ALFKI')", + "headers": { + "Prefer": "return=minimal" + }, + "body": + }, + { + "id": "2", + "atomicityGroup": "group1", + "method": "post", + "url": "/service/Customers", + "body": + }, + { + "id": "3", + "dependsOn": [ "group1" ], + "method": "get", + "url": "/service/Products" + } + ] +} +``` +::: + ## 19.2 Referencing New Entities +The entity returned by a preceding request can be referenced in the +request URL of subsequent requests. + +::: example +Example 49: a batch request that contains the following operations in +the order listed: + +- Insert a new entity (with `id = 1`) +- Insert a second new entity (references request with `id = 1`) +```json +POST /service/$batch HTTP/1.1 +Host: host +OData-Version: 4.01 +Content-Type: application/json +Content-Length: ### + +{ + "requests": [ + { + "id": "1", + "method": "post", + "url": "/service/Customers", + "body": + }, + { + "id": "2", + "dependsOn": [ "1" ] + "method": "post", + "url": "$1/Orders", + "body": + } + ] +} +``` +::: + ## 19.3 Referencing an ETag +::: example +Example 50: a batch request that contains the following operations in +the order listed: + +- Get an Employee (with `id` = 1) +- Update the salary only if the employee has not changed +```json +POST /service/$batch HTTP/1.1 +Host: host +OData-Version: 4.01 +Content-Type: application/json +Content-Length: ### + +{ + "requests": [ + { + "id": "1", + "method": "get", + "url": "/service/Employees(0)", + "headers": { + "accept": "application/json" + } + }, + { + "id": "2", + "dependsOn": [ "1" ], + "method": "patch", + "url": "/service/Employees(0)", + "headers": { + "if-match": "$1" + }, + "body": { + "Salary": 75000 + } + } + ] +} +``` +::: + ## 19.4 Processing a Batch Request +All requests in an atomicity group represent a single change unit. A +service MUST successfully process and apply all the requests in the +atomicity group or else apply none of them. It is up to the service +implementation to define rollback semantics to undo any requests within +an atomicity group that may have been applied before another request in +that same atomicity group failed. + +The service MAY process the individual requests and atomicity groups +within a batch request, or individual requests within an atomicity +group, in any order that is compatible with the dependencies expressed +with the `dependsOn` name/value pair. Individual requests and +atomicity groups that do not specify the `dependsOn` +name/value pair may be processed in parallel. Clients that are only +interested in completely successful batch responses MAY specify the +preference `continue-on-error=false` to indicate that the service need not spend cycles on further processing once an error occurs in one of the dependency chains. In this case the +response MAY omit response objects for requests that have not been +processed. If the preference `continue-on-error` is not +specified, or specified with a value of `true`, all requests +are processed according to their dependencies. + +The service MUST include the `id` name/value pair in each +response object with the value of the request identifier that the client +specified in the corresponding request, so clients can correlate +requests and responses. + ## 19.5 Batch Response +A JSON batch response body consists of a single JSON object that MUST +contain the name/value pair `responses` and MAY contain +[annotations](#InstanceAnnotations). It does not contain the +`context` control information. + +The value of `responses` is an array of response objects, +each representing an individual response. + +A JSON batch response MAY be a partial result containing the +[`nextLink`](#ControlInformationnextLinkodatanextLink) control +information. This allows services to chunk results into manageable +pieces, or to return results for already processed requests and continue +processing the remaining individual requests while waiting for the +client to fire a `GET` request to the next link. + +In a response to a batch request using the multipart format defined in +[OData-Protocol](#ODataProtocol) the response objects +MUST appear in the same order as required for multipart batch responses +because the `Content-ID` header is not required outside of change sets. Response objects +corresponding to requests that specify a `Content-ID` header MUST contain the +`id` name/value pair, and the value of `id` MUST be the value of the +`Content-ID` header of the corresponding request. This is necessarily the case for +requests contained within a change set. Responses to requests within a +change set MUST contain the `atomicityGroup` +name/value pair with a value common within a change set and unique +across change sets. + +In a response to a batch request using the JSON batch request format +specified in the preceding section the response objects MAY appear in +any order, and each response object MUST contain the `id` name/value +pair with the same value as in the corresponding request object. If the +corresponding request object contains the `atomicityGroup` +name/value pair, it MUST also be present in the response object with the +same value. + +If any response within an atomicity group returns a failure code, all +requests within that atomicity group are considered failed, regardless +of their individual returned status code. The service MAY return `424 Failed Dependency` for statements +within an atomicity group that fail or are not attempted due to other +failures within the same atomicity group. + +A response object MUST contain the name/value pair `status` +whose value is a number representing the HTTP status code of the +response to the individual request. + +The response object MAY contain the name/value pair `headers` +whose value is an object with name/value pairs representing response +headers. The name of each pair MUST be the lower-case header name; the +value is a string containing the header-encoded value of the header. + +The response object MAY contain the name/value pair `body` +which follows the same rules as within [request objects](#BatchRequest). + +If the media type is not exactly equal to `application/json` +(i.e. it is a subtype or has format parameters), the +`headers` object MUST contain a name/value pair with the name +`content-type` whose value is the media type. + +Relative URLs in a response object follow the rules for [relative +URLs](#RelativeURLs) based on the request URL of the corresponding +request. Especially: URLs in responses MUST NOT contain +`$`-prefixed request identifiers. + +::: example +Example 51: referencing the batch request [example 48](#batchRequest) above, assume all +the requests except the final query request succeed. In this case the +response would be +```json +{ + "responses": [ + { + "id": "0", + "status": 200, + "body": + }, + { + "id": "1", + "status": 204 + }, + { + "id": "2", + "status": 201, + "headers": { + "location": "http://host/service.svc/Customer('POIUY')" + }, + "body": + }, + { + "id": "3", + "status": 404, + "body": + } + ] +} +``` +::: + ## 19.6 Asynchronous Batch Requests +A batch request that specifies the `respond-async` preference MAY be executed asynchronously. This means that the "outer" batch request is executed asynchronously; this +preference does not automatically cascade down to the individual +requests within the batch. After successful execution of the batch +request the response to the batch request is returned in the body of a +response to an interrogation request against the status monitor resource +URL, see section "Asynchronous Requests" in +[OData-Protocol](#ODataProtocol). + +A service MAY return interim results to an asynchronously executing +batch. It does this by responding with `200 OK` to a +`GET` request to the monitor resource and including a +[`nextLink`](#ControlInformationnextLinkodatanextLink) +control information in the JSON batch response, thus signaling that the +response is only a partial result. A subsequent `GET` request +to the next link MAY result in a `202 Accepted` response with a +`location` header pointing to a new status monitor resource. + +::: example +Example 52: referencing the example 47 above again, assume that the +request is sent with the `respond-async` preference. This +results in a `202` response pointing to a status monitor resource: +```json +HTTP/1.1 202 Accepted +Location: http://service-root/async-monitor-0 +Retry-After: ### + +``` + +When interrogating the monitor URL only the first request in the batch +has finished processing and all the remaining requests are still being +processed. The service signals that asynchronous processing is +"finished" and returns a partial result with the first response and a +next link. The client did not explicitly accept +`application/http`, so the response is "unwrapped" and only +indicates with the `AsyncResult` header that it is a response +to a status monitor resource: +```json +HTTP/1.1 200 Ok +AsyncResult: 200 +OData-Version: 4.01 +Content-Length: ### +Content-Type: application/json + +{ + "responses": [ + { + "id": "0", + "status": 200, + "body": + } + ], + "@nextLink": "...?$skiptoken=YmF0Y2gx" +} +``` + +Client makes a `GET` request to the next link and receives a +`202` response with the location of a new monitor resource. + +```json +HTTP/1.1 202 Accepted +Location: http://service-root/async-monitor-1 +Retry-After: ### +``` + +After some time a `GET` request to the monitor resource returns the remainder of the result. + +```json +HTTP/1.1 200 Ok +AsyncResult: 200 +OData-Version: 4.01 +Content-Length: ### +Content-Type: application/json + +{ + "responses": [ + { + "id": "1", + "status": 204 + }, + { + "id": "2", + "status": 201, + "headers": { + "location": "http://host/service.svc/Customer('POIUY')" + }, + "body": + }, + { + "id": "3", + "status": 404, + "body": + } + ] +} +``` +::: + +In addition to the above interaction pattern individual requests within +a batch with no other requests depending on it and not part of an +atomicity group MAY be executed asynchronously if they specify the +`respond-async` preference and if +the service responds with a JSON batch response. In this case the +`response` array contains a response object for each +asynchronously executed individual request with a `status` of +`202`, a `location` header pointing to an +individual status monitor resource, and optionally a `retry-after` header. + +::: example +Example 53: the first individual request is processed asynchronously, +the second synchronously, the batch itself is processed synchronously +```json +HTTP/1.1 200 OK +OData-Version: 4.01 +Content-Length: ### +Content-Type: application/json + +{ + "responses": [ + { + "id": "0", + "status": 202, + "headers": { + "location": "http://service-root/async-monitor-0" + } + }, + { + "id": "1", + "status": 204 + } + ] +} +``` +::: ------- # 20 Instance Annotations @@ -2876,7 +3379,7 @@ the annotations for the value appear next to the `value` property and are not prefixed with a property name. ::: example -Example 48: +Example 54: ```json { "@context": "http://host/service/$metadata#Customers", @@ -2986,7 +3489,7 @@ Error responses MAY contain [annotations](#InstanceAnnotations) in any of its JSON objects. ::: example -Example 49: +Example 55: ```json { "error": { @@ -3035,7 +3538,7 @@ header-appropriate way: [RFC8259](#rfc8259), section 7) ::: example -Example 50: note that this is one HTTP header line without any line +Example 56: note that this is one HTTP header line without any line breaks or optional whitespace ```json OData-error: {"code":"err123","message":"Unsupported diff --git a/odata-json-format/19 Batch Requests and Responses.md b/odata-json-format/19 Batch Requests and Responses.md index abd2ad0f..323ff4ea 100644 --- a/odata-json-format/19 Batch Requests and Responses.md +++ b/odata-json-format/19 Batch Requests and Responses.md @@ -4,12 +4,517 @@ ## ##subsec Batch Request +A JSON batch request body consists of a single JSON object that MUST +contain the name/value pair `requests` and MAY contain +[annotations](#InstanceAnnotations). It does not contain the +`context` control information. + +The value of `requests` is an array of request objects, each +representing an individual request. Note: an individual request MUST NOT +itself be a batch request. + +A _request object_ MUST contain the name/value pairs `id`, +`method` and `url`, and it MAY contain the +name/value pairs `atomicityGroup`, `dependsOn`, `if`, `headers`, and `body`. + +The value of `id` is a string containing the request +identifier of the individual request, see +[OData-Protocol](#ODataProtocol). It MUST NOT be identical to the value +of any other request identifier nor any `atomicityGroup` +within the batch request. + +Note: the `id` name/value pair corresponds to the +`Content-ID` header in the multipart batch format specified +in [OData-Protocol](#ODataProtocol). + +The value of `method` is a string that MUST contain one of +the literals `delete`, `get`, `patch`, `post`, or `put`. +These literals are case-insensitive. + +The value of `url` is a string containing the individual +request URL. The URL MAY be an absolute path (starting with a forward +slash `/`) which is appended to scheme, host, and port of the +batch request URL, or a relative path (not starting with a forward slash `/`). + +If the first segment of a relative path starts with a `$` +character and is not identical to the name of a top-level system +resource (`$batch`, `$crossjoin,` `$all,` `$entity`, `$root,` +`$id`, `$metadata`, or other system resources +defined according to the `OData-Version` of the protocol +specified in the request), then this first segment is replaced with the +URL of the entity created by or returned from a preceding request whose +`id` value is identical to the value of the first segment +with the leading `$` character removed. The `id` +of this request MUST be specified in the `dependsOn` +name/value pair. + +Otherwise, the relative path is resolved relative to the batch request +URL (i.e. relative to the service root). + +The value of `atomicityGroup` is a string whose content MUST +NOT be identical to any value of `id` within the batch +request, and which MUST satisfy the rule `request-id` in +[OData-ABNF](#ODataABNF). All request objects with the same value for +`atomicityGroup` MUST be adjacent in the +`requests` array. These requests are processed as an atomic +operation and MUST either all succeed, or all fail. + +Note: the atomicity group is a generalization of the change set in the +multipart batch format specified in [OData-Protocol](#ODataProtocol). + +The value of `dependsOn` is an array of strings whose values +MUST be values of either `id` or `atomicityGroup` +of preceding request objects; forward references are not allowed. If a +request depends on another request that is part of a different atomicity +group, the atomicity group MUST be listed in `dependsOn`. In +the absence of the optional `if` member a request that +depends on other requests or atomicity groups is only executed if those +requests were executed successfully, i.e. with a `2xx` +response code. If one of the requests it depends on has failed, the +dependent request is not executed and a response with status code of +`424 Failed Dependency` is returned for it as part of the batch response. + +The `if` member can specify an alternative condition for +executing the dependent request. Its value MUST be URL expression (see +[OData-URL](#ODataURL)) that evaluates to a Boolean value. +The URL expression syntax is extended and additionally allows + +- `$/$succeeded` + to check if the referenced request has succeeded +- `$` + to reference the response body of the referenced request +- `$/` + to reference a part of the response body + +Services SHOULD advertise support of the `if` member by +specifying the property +`RequestDependencyConditionsSupported` in the +[`Capabilities.BatchSupport`](https://github.com/oasis-tcs/odata-vocabularies/blob/master/vocabularies/Org.OData.Capabilities.V1.md#BatchSupport) +term applied to the entity container, see +[OData-VocCap](#ODataVocCap). If a service does not +support request dependencies, the dependent request MUST fail with +`424 Failed Dependency`, and if the dependent request is part of an +atomicity group, all requests in that group fail with +`424 Failed Dependency` with no changes applied. + +The value of `headers` is an object whose name/value pairs +represent request headers. The name of each pair MUST be the lower-case +header name; the value is a string containing the header-encoded value +of the header. The `headers` object MUST contain a name/value +pair with the name `content-type` whose value is the media type. + +The value of `body` can be `null`, which is +equivalent to not specifying the `body` name/value pair. + +For media type `application/json` or one of its subtypes, +optionally with format parameters, the value of `body` is JSON. + +For media types of top-level type `text`, for example +`text/plain`, the value of `body` is a string +containing the value of the request body. + +For all other media types the value of `body` is a string +containing the base64url-encoded value of the request body. In this case +the body content can be compressed or chunked if this is correctly +reflected in the `Transfer-Encoding` header. + +A `body` MUST NOT be specified if the `method` is `get` or `delete`. + +::: example +Example ##ex_batchRequest: a batch request that contains +the following individual requests in the order listed + + 1. A query request + 2. An atomicity group that contains the following requests: + - Insert entity + - Update entity + 3. A second query request + +Note: For brevity, in the example, request bodies are excluded in favor +of English descriptions inside `<>` brackets and +`OData-Version` headers are omitted. +```json +POST /service/$batch HTTP/1.1 +Host: host +OData-Version: 4.01 +Content-Type: application/json +Content-Length: ### + +{ + "requests": [ + { + "id": "0", + "method": "get", + "url": "/service/Customers('ALFKI')" + }, + { + "id": "1", + "atomicityGroup": "group1", + "dependsOn": [ "0" ], + "method": "patch", + "url": "/service/Customers('ALFKI')", + "headers": { + "Prefer": "return=minimal" + }, + "body": + }, + { + "id": "2", + "atomicityGroup": "group1", + "method": "post", + "url": "/service/Customers", + "body": + }, + { + "id": "3", + "dependsOn": [ "group1" ], + "method": "get", + "url": "/service/Products" + } + ] +} +``` +::: + ## ##subsec Referencing New Entities +The entity returned by a preceding request can be referenced in the +request URL of subsequent requests. + +::: example +Example ##ex: a batch request that contains the following operations in +the order listed: + +- Insert a new entity (with `id = 1`) +- Insert a second new entity (references request with `id = 1`) +```json +POST /service/$batch HTTP/1.1 +Host: host +OData-Version: 4.01 +Content-Type: application/json +Content-Length: ### + +{ + "requests": [ + { + "id": "1", + "method": "post", + "url": "/service/Customers", + "body": + }, + { + "id": "2", + "dependsOn": [ "1" ] + "method": "post", + "url": "$1/Orders", + "body": + } + ] +} +``` +::: + ## ##subsec Referencing an ETag +::: example +Example ##ex: a batch request that contains the following operations in +the order listed: + +- Get an Employee (with `id` = 1) +- Update the salary only if the employee has not changed +```json +POST /service/$batch HTTP/1.1 +Host: host +OData-Version: 4.01 +Content-Type: application/json +Content-Length: ### + +{ + "requests": [ + { + "id": "1", + "method": "get", + "url": "/service/Employees(0)", + "headers": { + "accept": "application/json" + } + }, + { + "id": "2", + "dependsOn": [ "1" ], + "method": "patch", + "url": "/service/Employees(0)", + "headers": { + "if-match": "$1" + }, + "body": { + "Salary": 75000 + } + } + ] +} +``` +::: + ## ##subsec Processing a Batch Request +All requests in an atomicity group represent a single change unit. A +service MUST successfully process and apply all the requests in the +atomicity group or else apply none of them. It is up to the service +implementation to define rollback semantics to undo any requests within +an atomicity group that may have been applied before another request in +that same atomicity group failed. + +The service MAY process the individual requests and atomicity groups +within a batch request, or individual requests within an atomicity +group, in any order that is compatible with the dependencies expressed +with the `dependsOn` name/value pair. Individual requests and +atomicity groups that do not specify the `dependsOn` +name/value pair may be processed in parallel. Clients that are only +interested in completely successful batch responses MAY specify the +preference `continue-on-error=false` to indicate that the service need not spend cycles on further processing once an error occurs in one of the dependency chains. In this case the +response MAY omit response objects for requests that have not been +processed. If the preference `continue-on-error` is not +specified, or specified with a value of `true`, all requests +are processed according to their dependencies. + +The service MUST include the `id` name/value pair in each +response object with the value of the request identifier that the client +specified in the corresponding request, so clients can correlate +requests and responses. + ## ##subsec Batch Response +A JSON batch response body consists of a single JSON object that MUST +contain the name/value pair `responses` and MAY contain +[annotations](#InstanceAnnotations). It does not contain the +`context` control information. + +The value of `responses` is an array of response objects, +each representing an individual response. + +A JSON batch response MAY be a partial result containing the +[`nextLink`](#ControlInformationnextLinkodatanextLink) control +information. This allows services to chunk results into manageable +pieces, or to return results for already processed requests and continue +processing the remaining individual requests while waiting for the +client to fire a `GET` request to the next link. + +In a response to a batch request using the multipart format defined in +[OData-Protocol](#ODataProtocol) the response objects +MUST appear in the same order as required for multipart batch responses +because the `Content-ID` header is not required outside of change sets. Response objects +corresponding to requests that specify a `Content-ID` header MUST contain the +`id` name/value pair, and the value of `id` MUST be the value of the +`Content-ID` header of the corresponding request. This is necessarily the case for +requests contained within a change set. Responses to requests within a +change set MUST contain the `atomicityGroup` +name/value pair with a value common within a change set and unique +across change sets. + +In a response to a batch request using the JSON batch request format +specified in the preceding section the response objects MAY appear in +any order, and each response object MUST contain the `id` name/value +pair with the same value as in the corresponding request object. If the +corresponding request object contains the `atomicityGroup` +name/value pair, it MUST also be present in the response object with the +same value. + +If any response within an atomicity group returns a failure code, all +requests within that atomicity group are considered failed, regardless +of their individual returned status code. The service MAY return +`424 Failed Dependency` for statements +within an atomicity group that fail or are not attempted due to other +failures within the same atomicity group. + +A response object MUST contain the name/value pair `status` +whose value is a number representing the HTTP status code of the +response to the individual request. + +The response object MAY contain the name/value pair `headers` +whose value is an object with name/value pairs representing response +headers. The name of each pair MUST be the lower-case header name; the +value is a string containing the header-encoded value of the header. + +The response object MAY contain the name/value pair `body` +which follows the same rules as within [request objects](#BatchRequest). + +If the media type is not exactly equal to `application/json` +(i.e. it is a subtype or has format parameters), the +`headers` object MUST contain a name/value pair with the name +`content-type` whose value is the media type. + +Relative URLs in a response object follow the rules for [relative +URLs](#RelativeURLs) based on the request URL of the corresponding +request. Especially: URLs in responses MUST NOT contain +`$`-prefixed request identifiers. + +::: example +Example ##ex: referencing the batch request [example ##batchRequest] above, assume all +the requests except the final query request succeed. In this case the +response would be +```json +{ + "responses": [ + { + "id": "0", + "status": 200, + "body": + }, + { + "id": "1", + "status": 204 + }, + { + "id": "2", + "status": 201, + "headers": { + "location": "http://host/service.svc/Customer('POIUY')" + }, + "body": + }, + { + "id": "3", + "status": 404, + "body": + } + ] +} +``` +::: + ## ##subsec Asynchronous Batch Requests + +A batch request that specifies the `respond-async` preference MAY be executed asynchronously. This means that the "outer" batch request is executed asynchronously; this +preference does not automatically cascade down to the individual +requests within the batch. After successful execution of the batch +request the response to the batch request is returned in the body of a +response to an interrogation request against the status monitor resource +URL, see section "Asynchronous Requests" in +[OData-Protocol](#ODataProtocol). + +A service MAY return interim results to an asynchronously executing +batch. It does this by responding with `200 OK` to a +`GET` request to the monitor resource and including a +[`nextLink`](#ControlInformationnextLinkodatanextLink) +control information in the JSON batch response, thus signaling that the +response is only a partial result. A subsequent `GET` request +to the next link MAY result in a `202 Accepted` response with a +`location` header pointing to a new status monitor resource. + +::: example +Example ##ex: referencing the example 47 above again, assume that the +request is sent with the `respond-async` preference. This +results in a `202` response pointing to a status monitor resource: +```json +HTTP/1.1 202 Accepted +Location: http://service-root/async-monitor-0 +Retry-After: ### + +``` + +When interrogating the monitor URL only the first request in the batch +has finished processing and all the remaining requests are still being +processed. The service signals that asynchronous processing is +"finished" and returns a partial result with the first response and a +next link. The client did not explicitly accept +`application/http`, so the response is "unwrapped" and only +indicates with the `AsyncResult` header that it is a response +to a status monitor resource: +```json +HTTP/1.1 200 Ok +AsyncResult: 200 +OData-Version: 4.01 +Content-Length: ### +Content-Type: application/json + +{ + "responses": [ + { + "id": "0", + "status": 200, + "body": + } + ], + "@nextLink": "...?$skiptoken=YmF0Y2gx" +} +``` + +Client makes a `GET` request to the next link and receives a +`202` response with the location of a new monitor resource. + +```json +HTTP/1.1 202 Accepted +Location: http://service-root/async-monitor-1 +Retry-After: ### +``` + +After some time a `GET` request to the monitor resource returns the remainder of the result. + +```json +HTTP/1.1 200 Ok +AsyncResult: 200 +OData-Version: 4.01 +Content-Length: ### +Content-Type: application/json + +{ + "responses": [ + { + "id": "1", + "status": 204 + }, + { + "id": "2", + "status": 201, + "headers": { + "location": "http://host/service.svc/Customer('POIUY')" + }, + "body": + }, + { + "id": "3", + "status": 404, + "body": + } + ] +} +``` +::: + +In addition to the above interaction pattern individual requests within +a batch with no other requests depending on it and not part of an +atomicity group MAY be executed asynchronously if they specify the +`respond-async` preference and if +the service responds with a JSON batch response. In this case the +`response` array contains a response object for each +asynchronously executed individual request with a `status` of +`202`, a `location` header pointing to an +individual status monitor resource, and optionally a `retry-after` header. + +::: example +Example ##ex: the first individual request is processed asynchronously, +the second synchronously, the batch itself is processed synchronously +```json +HTTP/1.1 200 OK +OData-Version: 4.01 +Content-Length: ### +Content-Type: application/json + +{ + "responses": [ + { + "id": "0", + "status": 202, + "headers": { + "location": "http://service-root/async-monitor-0" + } + }, + { + "id": "1", + "status": 204 + } + ] +} +``` +::: diff --git a/odata-json-format/temp/odata-json-format-v4.01-os.md b/odata-json-format/temp/odata-json-format-v4.01-os.md deleted file mode 100644 index b69184e9..00000000 --- a/odata-json-format/temp/odata-json-format-v4.01-os.md +++ /dev/null @@ -1,595 +0,0 @@ -# {#sec_BatchRequestsandResponses}[19[ ]{style="font:7.0pt "Times New Roman""}][Batch Requests and Responses](#BatchRequestsandResponses) {#batch-requests-and-responses style="margin-left:19.85pt;text-indent:-19.85pt"} - -::: - -## {#sec_BatchRequest}[19.1] [Batch Request](#BatchRequest) - -A JSON batch request body consists of a single JSON object that MUST -contain the name/value pair `requests` and MAY contain -[annotations](#InstanceAnnotations). It does not contain the -`context` control information. - -The value of `requests` is an array of request objects, each -representing an individual request. Note: an individual request MUST NOT -itself be a batch request. - -A _request object_ MUST contain the name/value pairs `id`, -`method` and `url`, and it MAY contain the -name/value pairs `atomicityGroup`, `dependsOn`[[, -]{style="font-family:"Arial",sans-serif"}]{.Datatype}`if`[[, -]{style="font-family:"Arial",sans-serif"}]{.Datatype}`headers`, -and `body`. - -The value of `id` is a string containing the request -identifier of the individual request, see -[OData-Protocol](#ODataProtocol). It MUST NOT be identical to the value -of any other request identifier nor any `atomicityGroup` -within the batch request. - -Note: the `id` name/value pair corresponds to the -`Content-ID` header in the multipart batch format specified -in [OData-Protocol](#ODataProtocol). - -The value of `method` is a string that MUST contain one of -the literals `delete`, `get`, `patch`, -`post`, or `put`. These literals are -case-insensitive. - -The value of `url` is a string containing the individual -request URL. The URL MAY be an absolute path (starting with a forward -slash `/`) which is appended to scheme, host, and port of the -batch request URL, or a relative path (not starting with a forward slash -`/`). - -If the first segment of a relative path starts with a `$` -character and is not identical to the name of a top-level system -resource (`$batch`, `$crossjoin,` -`$all,` `$entity`, `$root,` -`$id`, `$metadata`, or other system resources -defined according to the -`OData-Version` of the protocol -specified in the request), then this first segment is replaced with the -URL of the entity created by or returned from a preceding request whose -`id` value is identical to the value of the first segment -with the leading `$` character removed. The `id` -of this request MUST be specified in the `dependsOn` -name/value pair. - -Otherwise, the relative path is resolved relative to the batch request -URL (i.e. relative to the service root). - -The value of `atomicityGroup` is a string whose content MUST -NOT be identical to any value of `id` within the batch -request, and which MUST satisfy the rule `request-id` in -[OData-ABNF](#ODataABNF). All request objects with the same value for -`atomicityGroup` MUST be adjacent in the -`requests` array. These requests are processed as an atomic -operation and MUST either all succeed, or all fail. - -Note: the atomicity group is a generalization of the change set in the -multipart batch format specified in [OData-Protocol](#ODataProtocol). - -The value of `dependsOn` is an array of strings whose values -MUST be values of either `id` or `atomicityGroup` -of preceding request objects; forward references are not allowed. If a -request depends on another request that is part of a different atomicity -group, the atomicity group MUST be listed in `dependsOn`. In -the absence of the optional `if` member a request that -depends on other requests or atomicity groups is only executed if those -requests were executed successfully, i.e. with a `2xx` -response code. If one of the requests it depends on has failed, the -dependent request is not executed and a response with status code of -`424 Failed Dependency`[[ is returned for it as part of the -batch response.]{style="font-family:"Arial",sans-serif"}]{.Datatype} - -The `if` member can specify an alternative condition for -executing the dependent request. Its value MUST be URL expression (see -[OData-URL](#ODataURL)) that evaluates to a Boolean value. -The URL expression syntax is extended and additionally allows - -- `$\/$succeeded` - to check if the referenced request has succeeded - -- `$\` - to reference the response body of the referenced request - -- `$\/\` - to reference a part of the response body - -Services SHOULD advertise support of the `if` member by -specifying the property -`RequestDependencyConditionsSupported` in the -[`Capabilities.BatchSupport`](https://github.com/oasis-tcs/odata-vocabularies/blob/master/vocabularies/Org.OData.Capabilities.V1.md#BatchSupport) -term applied to the entity container, see -[OData-VocCap](#ODataVocCap)[[. If a service does not -support request dependencies, the dependent request MUST fail with -]{style="color:windowtext"}]{.MsoHyperlink}[424 Failed -Dependency]{.Datatype}[[, and if the dependent request is part of an -atomicity group, all requests in that group fail with -]{style="color:windowtext"}]{.MsoHyperlink}[424 Failed -Dependency]{.Datatype}[[ with no changes -applied]{style="color:windowtext"}]{.MsoHyperlink}. - -The value of `headers` is an object whose name/value pairs -represent request headers. The name of each pair MUST be the lower-case -header name; the value is a string containing the header-encoded value -of the header. The `headers` object MUST contain a name/value -pair with the name `content-type` whose value is the media -type. - -The value of `body` can be `null`, which is -equivalent to not specifying the `body` name/value pair. - -For media type `application/json`[[ or one of its subtypes, -optionally with format parameters, the value of -]{style="font-family:"Arial",sans-serif"}]{.Datatype}`body`[[ -is JSON.]{style="font-family:"Arial",sans-serif"}]{.Datatype} - -For media types of top-level type `text`, for example -`text/plain`, the value of `body` is a string -containing the value of the request body. - -For all other media types the value of `body` is a string -containing the base64url-encoded value of the request body. In this case -the body content can be compressed or chunked if this is correctly -reflected in the `Transfer-Encoding` header. - -A `body` MUST NOT be specified if the `method` is -`get` or `delete`. - -::: example -Example ##ex: a batch request that contains -the following individual requests in the order listed - -1.[ ]{style="font:7.0pt "Times New Roman""}A query request - -2.[ ]{style="font:7.0pt "Times New Roman""}An atomicity group that -contains the following requests: - -]{style="font:7.0pt "Times New Roman""}]{style="font-family:Symbol;font-style:normal"}Insert -entity - -]{style="font:7.0pt "Times New Roman""}]{style="font-family:Symbol;font-style:normal"}Update -entity - -3.[ ]{style="font:7.0pt "Times New Roman""}A second query request - -Note: For brevity, in the example, request bodies are excluded in favor -of English descriptions inside `\<\>` brackets and -`OData-Version` headers are omitted. -```json -POST /service/$batch HTTP/1.1\ -Host: host\ -OData-Version: 4.01\ -Content-Type: application/json\ -Content-Length: \### - - -[{ - "requests": \ - - { - "id": "0", - "method": "get", - "url": "/service/Customers('ALFKI')" - }, - { - "id": "1", - "atomicityGroup": "group1", - "dependsOn": \[ "0" \], - "method": "patch", - "url": "/service/Customers('ALFKI')", - "headers": { - "Prefer": "return=minimal" - }, - "body": \ - }, - { - "id": "2", - "atomicityGroup": "group1", - "method": "post", - "url": "/service/Customers", - "body": \ - }, - { - "id": "3", - "dependsOn": \[ "group1" \], - "method": "get", - "url": "/service/Products" - } - \] -} -``` -::: - -## {#sec_ReferencingNewEntities}[[19.2 ]{style="color:#0000EE"}][Referencing New Entities](#ReferencingNewEntities) - -The entity returned by a preceding request can be referenced in the -request URL of subsequent requests. - -::: example -Example ##ex: a batch request that contains the following operations in -the order listed: - -]{style="font:7.0pt "Times New Roman""}]{style="font-family:Symbol;font-style:normal"}Insert -a new entity (with `id = 1`) - -]{style="font:7.0pt "Times New Roman""}]{style="font-family:Symbol;font-style:normal"}Insert -a second new entity (references request with `id = 1`) -```json -POST /service/$batch HTTP/1.1\ -Host: host\ -OData-Version: 4.01\ -Content-Type: application/json\ -Content-Length: \###\ -\ -{ - "requests": \ - - { - "id": "1", - "method": "post", - "url": "/service/Customers", - "body": \ - }, - { - "id": "2", - "dependsOn": \[ "1" \] - "method": "post", - "url": "$1/Orders", - "body": \ - } - \] -} -``` -::: - -## {#sec_ReferencinganETag}[[19.3 ]{style="color:#0000EE"}][Referencing an ETag](#ReferencinganETag) - -::: example -Example ##ex: a batch request that contains the following operations in -the order listed: - -]{style="font:7.0pt "Times New Roman""}]{style="font-family:Symbol;font-style:normal"}Get -an Employee (with `id` = 1) - -]{style="font:7.0pt "Times New Roman""}]{style="font-family:Symbol;font-style:normal"}Update -the salary only if the employee has not changed -```json -POST /service/$batch HTTP/1.1\ -Host: host\ -OData-Version: 4.01\ -Content-Type: application/json\ -Content-Length: \###\ -\ - -[{ - "requests": \ - - { - "id": "1", - "method": "get", - "url": "/service/Employees(0)", - "headers": { - "accept": "application/json" - } - }, - { - "id": "2", - "dependsOn": \[ "1" \], - "method": "patch", - "url": "/service/Employees(0)", - "headers": { - "if-match": "$1" - }, - "body": { - "Salary": 75000 - } - } - \] -} -``` -::: - -## {#sec_ProcessingaBatchRequest}19.4 [Processing a Batch Request](#ProcessingaBatchRequest) - -All requests in an atomicity group represent a single change unit. A -service MUST successfully process and apply all the requests in the -atomicity group or else apply none of them. It is up to the service -implementation to define rollback semantics to undo any requests within -an atomicity group that may have been applied before another request in -that same atomicity group failed. - -The service MAY process the individual requests and atomicity groups -within a batch request, or individual requests within an atomicity -group, in any order that is compatible with the dependencies expressed -with the `dependsOn` name/value pair. Individual requests and -atomicity groups that do not specify the `dependsOn` -name/value pair may be processed in parallel. Clients that are only -interested in completely successful batch responses MAY specify the -preference -[continue-on-error=false]{style="font-family:"Courier New";color:#3B006F"} -to indicate that the service need not spend cycles on further processing -once an error occurs in one of the dependency chains. In this case the -response MAY omit response objects for requests that have not been -processed. If the preference `continue-on-error` is not -specified, or specified with a value of `true`, all requests -are processed according to their dependencies. - -The service MUST include the `id` name/value pair in each -response object with the value of the request identifier that the client -specified in the corresponding request, so clients can correlate -requests and responses. - -## {#sec_BatchResponse}[19.5] [Batch Response](#BatchResponse) - -A JSON batch response body consists of a single JSON object that MUST -contain the name/value pair `responses` and MAY contain -[annotations](#InstanceAnnotations). It does not contain the -`context` control information. - -The value of `responses` is an array of response objects, -each representing an individual response. - -A JSON batch response MAY be a partial result containing the -[[nextLink]{style="font-family: -"Courier New""}](#ControlInformationnextLinkodatanextLink) control -information. This allows services to chunk results into manageable -pieces, or to return results for already processed requests and continue -processing the remaining individual requests while waiting for the -client to fire a `GET` request to the next link. - -In a response to a batch request using the multipart format defined in -[OData-Protocol](#ODataProtocol) [[the response objects -MUST appear in the same order as required for multipart batch responses -because the -]{style="color:windowtext"}]{.MsoHyperlink}`Content-ID`[[ -header is not required outside of change sets. Response objects -corresponding to requests that specify a -]{style="color:windowtext"}]{.MsoHyperlink}`Content-ID`[[ -header MUST contain the -]{style="color:windowtext"}]{.MsoHyperlink}`id`[[ name/value -pair, and the value of -]{style="color:windowtext"}]{.MsoHyperlink}`id`[[ MUST be the -value of the -]{style="color:windowtext"}]{.MsoHyperlink}`Content-ID`[[ -header of the corresponding request. This is necessarily the case for -requests contained within a change set. Responses to requests within a -change set MUST contain the -]{style="color:windowtext"}]{.MsoHyperlink}`atomicityGroup`[[ -name/value pair with a value common within a change set and unique -across change sets.]{style="color:windowtext"}]{.MsoHyperlink} - -[[In a response to a batch request using the JSON batch request format -specified in the preceding section the response objects MAY appear in -any order, and each response object MUST contain the -]{style="color:windowtext"}]{.MsoHyperlink}`id`[[ name/value -pair with the same value as in the corresponding request object. If the -corresponding request object contains the -]{style="color:windowtext"}]{.MsoHyperlink}`atomicityGroup`[[ -name/value pair, it MUST also be present in the response object with the -same value.]{style="color:windowtext"}]{.MsoHyperlink} - -If any response within an atomicity group returns a failure code, all -requests within that atomicity group are considered failed, regardless -of their individual returned status code. The service MAY return [424 -Failed Dependency]{.Datatype}[[ -]{style="font-family:"Arial",sans-serif"}]{.Datatype}for statements -within an atomicity group that fail or are not attempted due to other -failures within the same atomicity group. - -A response object MUST contain the name/value pair `status` -whose value is a number representing the HTTP status code of the -response to the individual request. - -The response object MAY contain the name/value pair `headers` -whose value is an object with name/value pairs representing response -headers. The name of each pair MUST be the lower-case header name; the -value is a string containing the header-encoded value of the header. - -The response object MAY contain the name/value pair `body` -which follows the same rules as within [request -objects](#BatchRequest). - -If the media type is not exactly equal to `application/json` -(i.e. it is a subtype or has format parameters), the -`headers` object MUST contain a name/value pair with the name -`content-type` whose value is the media type. - -Relative URLs in a response object follow the rules for [relative -URLs](#RelativeURLs) based on the request URL of the corresponding -request. Especially: URLs in responses MUST NOT contain -`$`-prefixed request identifiers. - -::: example -Example ##ex: referencing the batch request example 47 above, assume all -the requests except the final query request succeed. In this case the -response would be -```json -{ - "responses": \ - - { - "id": "0", - "status": 200, - "body": \ - }, - { - "id": "1", - "status": 204 - }, - { - "id": "2", - "status": 201, - "headers": { - "location": -"http://host/service.svc/Customer('POIUY')" - }, - "body": \ - }, - { - "id": "3", - "status": 404, - "body": \ - } - \] -} -``` -::: - -## {#sec_AsynchronousBatchRequests}{#\_Ref358207547}{#\_Instance_Annotations}19.6 [Asynchronous Batch Requests](#AsynchronousBatchRequests) - -A batch request that specifies the [respond-async]{style="font-family: -"Courier New""} preference MAY be executed asynchronously. This means -that the "outer" batch request is executed asynchronously; this -preference does not automatically cascade down to the individual -requests within the batch. After successful execution of the batch -request the response to the batch request is returned in the body of a -response to an interrogation request against the status monitor resource -URL, see section "Asynchronous Requests" in -[OData-Protocol](#ODataProtocol). - -A service MAY return interim results to an asynchronously executing -batch. It does this by responding with `200 OK` to a -`GET` request to the monitor resource and including a -[`nextLink`](#ControlInformationnextLinkodatanextLink) -control information in the JSON batch response, thus signaling that the -response is only a partial result. A subsequent `GET` request -to the next link MAY result in a [202 -Accepted]{style="font-family:"Courier New""} response with a -`location` header pointing to a new status monitor resource. - -::: example -Example ##ex: referencing the example 47 above again, assume that the -request is sent with the `respond-async` preference. This -results in a `202` response pointing to a status monitor -resource: -````json -HTTP/1.1 202 Accepted\ -Location: http://service-root/async-monitor-0\ -Retry-After: \###\ -\ -::: - -When interrogating the monitor URL only the first request in the batch -has finished processing and all the remaining requests are still being -processed. The service signals that asynchronous processing is -"finished" and returns a partial result with the first response and a -next link. The client did not explicitly accept -`application/http`, so the response is "unwrapped" and only -indicates with the `AsyncResult` header that it is a response -to a status monitor resource: -```json -HTTP/1.1 200 Ok\ -AsyncResult: 200\ -OData-Version: 4.01\ -Content-Length: \####\ -Content-Type: application/json\ -\ - -[{ - "responses": \ - - { - "id": "0", - "status": 200, - "body": \ - \], - "@nextLink": "...?$skiptoken=YmF0Y2gx" -} -```` - -Client makes a `GET` request to the next link and receives a -`202` response with the location of a new monitor resource. -````json -HTTP/1.1 202 Accepted\ -Location: http://service-root/async-monitor-1\ -Retry-After: \###\ -\ -::: - -After some time a `GET` request to the monitor resource -returns the remainder of the result[[. -]{style="font-family:"Arial",sans-serif"}]{.Datatype} -```json -HTTP/1.1 200 Ok\ -AsyncResult: 200\ -OData-Version: 4.01 -[Content-Length: \####\ -Content-Type: application/json\ -\ - -[{ - "responses": \ - - { - "id": "1", - "status": 204 - }, - { - "id": "2", - "status": 201, - "headers": { - "location": -"http://host/service.svc/Customer('POIUY')" - }, - "body": \ - }, - { - "id": "3", - "status": 404, - "body": \ - } - \] -} -```` - -In addition to the above interaction pattern individual requests within -a batch with no other requests depending on it and not part of an -atomicity group MAY be executed asynchronously if they specify the -`respond-async` preference and if -the service responds with a JSON batch response. In this case the -`response` array contains a response object for each -asynchronously executed individual request with a `status`[[ -]{style="font-family:"Arial",sans-serif"}]{.Datatype}of -`202`, a `location` header pointing to an -individual status monitor resource, and optionally a -`retry-after` header. - -::: example -Example ##ex: the first individual request is processed asynchronously, -the second synchronously, the batch itself is processed synchronously -```json -HTTP/1.1 200 OK\ -OData-Version: 4.01\ -Content-Length: \####\ -Content-Type: application/json\ -\ - -[{ - "responses": \ - - { - "id": "0", - "status": 202, - "headers": { - "location": -"http://service-root/async-monitor-0" - } - }, - { - "id": "1", - "status": 204 - } - \] -} -``` -:::