What this is about
A hook reports an error by throwing an exception. In Java, an exception is an object that interrupts the normal flow and is passed upwards until something handles it. In CDMS, the central error handling does this: it rolls back the request and builds the error response.
So a hook never fails alone. It takes the whole request with it: the object, all children, all objects deleted along, everything other hooks changed in the database before.
Which exception gives which response
| Your hook throws | Status | error | messageKey | layer |
|---|---|---|---|---|
HookValidationException("stock-negative", null) | 422 | HookValidationException | stock-negative | hook |
HookExecutionException("erp-unreachable", e) | 500 | HookExecutionException | erp-unreachable | hook |
another CodamAI exception, e.g. NoAccessException | its status | its class | its key | its layer |
any other exception, e.g. IllegalStateException | 500 | name of a Java class | details see logfiles | undefined |
Both hook exceptions live in com.codamai.cdms.commons.exceptions. The first parameter is the key the client evaluates. The second one is an optional cause: if you pass one, its text appears in message.
PATCH /api/rest/shop/stock/update/s-17
{ "data": { "id": "s-17", "quantity": -3 }, "response": ["id", "quantity"] }{
"error": "HookValidationException",
"messageKey": "stock-negative",
"code": "422",
"layer": "hook"
}A response from a hook has no violations. You build the text for the user in the client from messageKey. What the error format looks like in general is described in The error format.
Before, after, READ
When: in beforeDatabaseChange, with create, PUT, PATCH, DELETE or ROLLBACK
-
1CDMSrecursion done, roles checked
-
2Hookthrows an exception
-
3CDMSstops right away: no further before hooks, no validation, no saving, no after hooks
-
4CDMS→Databaserolls back the request
-
5CDMS→Clienterror response, e.g. 422
stock-negative
Result: Nothing is saved. Collected validation violations do not reach the response either, because validation gives its verdict only after the before hooks.
When: in afterDatabaseChange, with create, PUT, PATCH, DELETE or ROLLBACK
-
1CDMS→Databasehas already handed over the object, but not yet committed it
-
2Hookthrows an exception
-
3CDMSstops: no further after hooks, no flush, no read-back
-
4CDMS→Databaserolls back the request
-
5CDMS→Clienterror response
Result: Nothing is saved, even though the before hooks and validation went through. After hooks run before the commit.
When: in afterDatabaseChange with READ, when reading, searching or reading back
-
1Hookthrows an exception while reading
-
2CDMS→Clientfor a plain read or search: error response instead of data
-
3CDMS→Databasewhen reading back after PUT, PATCH, ROLLBACK and create in mode
STRICT: rolls back the change
Result: For a create in mode LENIENT, the object stays created. See Create and read back: STRICT or LENIENT.
How far the rollback reaches
-
1Client→CDMS
PUT /department/update/d-1with two changed employees and one new employee -
2Hookthe before hooks of the first objects go through
-
3Hookthe before hook of one employee throws
HookValidationException -
4CDMS→Databaserolls back the whole request: the department, all three employees, also children deleted along
-
5CDMS→Client422 with the key from the hookResult: The database looks as it did before the request.
There is no partial success. No matter on which level of the tree the hook sits: the request is one transaction. See One request, one transaction.
Decision table
| Where the hook throws | Operation | Result |
|---|---|---|
| before | create, PUT, PATCH, DELETE, ROLLBACK | error response, nothing saved |
| after | create, PUT, PATCH, DELETE, ROLLBACK | error response, nothing saved |
| READ | read, search | error response, no data |
| READ | read-back after PUT, PATCH, ROLLBACK or create with STRICT | error response, nothing saved |
| READ | read-back after create with LENIENT | object created, response with the id instead of the object |
Pitfalls
Where to go next
- When which hook runs: Hooks: types and timing
- Which steps lie before and after the hooks: The order within a write operation
- Which other status codes exist: The error format