In an OData 4.01 JSON batch, how do atomicityGroup and dependsOn decide what runs together, in what order, and what fails?
answer
- a generalised change set
- adjacent members, all or nothing
- no implicit order, only declared
- skipped dependents report 424
basics
~20 sRequests sharing an atomicityGroup must be adjacent and succeed or fail together. dependsOn names earlier ids or groups that must succeed first; anything undeclared may run in any order or in parallel, and a dependent whose prerequisite failed gets 424.
solid answer
~50 sOData 4.01 added a JSON batch: a `requests` array whose objects carry `id`, `method` and `url`, plus optional `atomicityGroup`, `dependsOn`, `if`, `headers` and `body`. An **atomicity group** generalises the multipart change set: requests with the same `atomicityGroup` value MUST be adjacent and MUST all succeed or all fail. **`dependsOn`** lists the ids or group names of *preceding* requests (no forward references), and a request that depends on a member of another group must list that group. The service MAY process requests in any order compatible with those dependencies, and requests without `dependsOn` may run in parallel, so array order alone guarantees nothing. If a prerequisite fails, the dependent is not executed and gets `424 Failed Dependency`, unless an `if` member sets a different condition. Responses come back in a `responses` array, possibly in any order, matched by `id`.
code
json · 14 lines{
"requests": [
{"id": "1", "atomicityGroup": "order", "method": "post",
"url": "Orders",
"headers": {"content-type": "application/json"},
"body": {"CustomerId": "C042", "Currency": "EUR"}},
{"id": "2", "atomicityGroup": "order", "dependsOn": ["1"],
"method": "post", "url": "$1/Items",
"headers": {"content-type": "application/json"},
"body": {"Sku": "TEA-250", "Quantity": 3}},
{"id": "3", "dependsOn": ["order", "1"],
"method": "get", "url": "$1/Items"}
]
}go deeper
Recall that OData 4.01 can send a batch as JSON, with a requests array whose objects carry id, method and url.
Explain atomicityGroup as the JSON form of a change set and dependsOn as the only ordering the service must honour.
Show you would declare every real dependency, list groups rather than members, and handle 424 for skipped work, since the service may parallelise everything undeclared.
Weigh how much orchestration logic to push into batch dependencies and if expressions against a server-side action that owns the whole workflow.
## Why OData 4.01 added a JSON batch OData 4.0 defined only the multipart batch format, which the OASIS "What's New in OData 4.01" document calls somewhat hard to implement. OData 4.01 added a **JSON batch format** so that clients can compose batch requests and read batch responses with ordinary JSON libraries. The batch is still a `POST` to `$batch`, now with `Content-Type: application/json`. The body is one JSON object that MUST contain `requests` and MAY contain annotations; an individual request MUST NOT itself be a batch. The JSON format also allows richer dependencies than change sets ever could. ## The request object | Member | Required | Meaning | |---|---|---| | `id` | yes | the request identifier: unique in the batch and unlike every `atomicityGroup` value; it plays the role of the multipart `Content-ID` | | `method` | yes | one of the literals `delete`, `get`, `patch`, `post`, `put`, matched case-insensitively | | `url` | yes | an absolute path appended to the batch URL's scheme, host and port, or a relative path resolved against the batch URL; a first segment `$<id>` is replaced by the URL of the entity that request created or returned | | `atomicityGroup` | no | a label shared by requests that must succeed or fail together | | `dependsOn` | no | an array of `id` or `atomicityGroup` values of *preceding* request objects | | `if` | no | a Boolean URL expression that replaces the default run-only-on-success condition | | `headers` | no | an object of request headers, each name in lower case | | `body` | no | JSON for `application/json`, a string for `text/*`, base64url for anything else; never on `get` or `delete` | ## Atomicity groups An atomicity group is the JSON format's generalisation of the multipart change set. - All request objects with the same `atomicityGroup` value MUST be **adjacent** in the `requests` array. - Their requests are one change unit: the service MUST apply all of them or none. How it undoes partial work is up to the service implementation. - If any response within a group returns a failure code, every request in that group is considered failed, whatever its own status; the service MAY return `424 Failed Dependency` for the members that failed or were never attempted because of it. - A group's name follows the same syntax rule as request identifiers and MUST NOT equal any `id` in the batch. ## Dependencies and ordering The multipart format makes the service process top-level parts in the order received. The JSON format does not. The service MAY process requests and atomicity groups in **any order compatible with `dependsOn`**, and requests and groups that declare no `dependsOn` may be processed **in parallel**. Array position promises nothing. 1. **Declare what must happen first.** `dependsOn` lists the ids or group names of preceding request objects; forward references are not allowed. 2. **Name the group, not just the member.** If a request depends on a request that belongs to a different atomicity group, that group MUST be listed in `dependsOn`. 3. **Declare what you reference.** A request whose `url` starts with `$<id>` MUST list that `id` in `dependsOn`. 4. **Expect 424 for skipped work.** Without `if`, a dependent runs only if everything it depends on returned `2xx`. Otherwise it is not executed, and its response carries `424 Failed Dependency`. 5. **Use `if` for other conditions.** Its expression may use `$<id>/$succeeded`, `$<id>` for a response body or `$<id>/<path>` for part of one; services SHOULD advertise it with `RequestDependencyConditionsSupported` in the Capabilities `BatchSupport` annotation. A service that does not support request dependencies MUST fail the dependent request with `424`, and if that request sits in an atomicity group, the whole group fails with `424` and nothing applied. ## The response - The body is an object with a `responses` array, again with no context control information. - Each response object MUST contain `id` and `status`, MAY contain `headers` (lower-case names) and `body`, and echoes `atomicityGroup` when its request had one. - Response objects MAY appear **in any order**, so clients correlate by `id`. - A response MAY be partial, ending with `nextLink`, while the service keeps processing. - URLs in responses MUST NOT contain `$`-prefixed identifiers. ## Common misreadings - Assuming array order is execution order, so a closing `GET` reads data before the writes it was meant to see. - Leaving the group out of `dependsOn` and naming only one of its members. - Expecting `412 Precondition Failed` for a skipped dependent instead of `424`. - Scattering a group's members across the array.
- How does the if member change dependency handling in an OData 4.01 JSON batch?Without `if`, a dependent runs only when every request it depends on returned `2xx`. The `if` member replaces that default with a Boolean URL expression that may use `$<id>/$succeeded`, `$<id>` for a response body or `$<id>/<path>` for part of one. Services SHOULD advertise support with `RequestDependencyConditionsSupported` in the Capabilities `BatchSupport` annotation.
- How can an OData client tell whether a service accepts JSON batch requests at all?The Capabilities vocabulary's `BatchSupport` term on the entity container has a `SupportedFormats` property whose allowed values are `multipart/mixed` and `application/json`. A service that lists only `multipart/mixed` expects the 4.0-style format; a client should read that annotation before switching formats.
saying these in an interview costs you the question
- JSON batch requests execute top to bottom, exactly like the multipart format.
- dependsOn may point forward to a request later in the array.
- A request skipped because its prerequisite failed reports 412 Precondition Failed.
- Members of one atomicity group may be scattered through the requests array.
- JSON batch responses come back in request order, so match them by position.