CodamAIDocs
Topicdone

When a hook fails

An error in a hook rolls back the whole request. How the error reaches the client.

Variants
before hook throwsafter hook throwsREAD hook throwsHookValidationException → 422HookExecutionException → 500other exception → 500

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 throwsStatuserrormessageKeylayer
HookValidationException("stock-negative", null)422HookValidationExceptionstock-negativehook
HookExecutionException("erp-unreachable", e)500HookExecutionExceptionerp-unreachablehook
another CodamAI exception, e.g. NoAccessExceptionits statusits classits keyits layer
any other exception, e.g. IllegalStateException500name of a Java classdetails see logfilesundefined

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.

A before hook rejects
Request
PATCH /api/rest/shop/stock/update/s-17
{ "data": { "id": "s-17", "quantity": -3 }, "response": ["id", "quantity"] }
Response 422
{
  "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

Where the hook fails

When: in beforeDatabaseChange, with create, PUT, PATCH, DELETE or ROLLBACK

  1. 1
    CDMS
    recursion done, roles checked
  2. 2
    Hook
    throws an exception
  3. 3
    CDMS
    stops right away: no further before hooks, no validation, no saving, no after hooks
  4. 4
    CDMS→Database
    rolls back the request
  5. 5
    CDMS→Client
    error 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

  1. 1
    CDMS→Database
    has already handed over the object, but not yet committed it
  2. 2
    Hook
    throws an exception
  3. 3
    CDMS
    stops: no further after hooks, no flush, no read-back
  4. 4
    CDMS→Database
    rolls back the request
  5. 5
    CDMS→Client
    error 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

  1. 1
    Hook
    throws an exception while reading
  2. 2
    CDMS→Client
    for a plain read or search: error response instead of data
  3. 3
    CDMS→Database
    when 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

A hook of a child throws
  1. 1
    Client→CDMS
    PUT /department/update/d-1 with two changed employees and one new employee
  2. 2
    Hook
    the before hooks of the first objects go through
  3. 3
    Hook
    the before hook of one employee throws HookValidationException
  4. 4
    CDMS→Database
    rolls back the whole request: the department, all three employees, also children deleted along
  5. 5
    CDMS→Client
    422 with the key from the hook
    Result: 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

What remains when a hook throws
Where the hook throwsOperationResult
beforecreate, PUT, PATCH, DELETE, ROLLBACKerror response, nothing saved
aftercreate, PUT, PATCH, DELETE, ROLLBACKerror response, nothing saved
READread, searcherror response, no data
READread-back after PUT, PATCH, ROLLBACK or create with STRICTerror response, nothing saved
READread-back after create with LENIENTobject created, response with the id instead of the object

Pitfalls

Where to go next

Sources in the code and the knowledge base
  • commons – global/commons/exceptions/AbstractCodamaiException (httpStatusCode, messageKey, layer, embedded)
  • CDMS/cdms-commons – exceptions/HookValidationException (422, layer hook), HookExecutionException (500, layer hook)
  • CDMS/cdms-system-layer – AbstractSystemLayer, AbstractSystemSingletonLayer (createObject, updateObject, patchObject, deleteObject, historyRollback, readObject: rollback, throw); session/HookRequestContext (runBefore, runAfter)
  • CDMS/cdms-rest-api – CdmsExceptionMapper (markRollbackOnly, handleCmsException, handleDefault), RequestTransactionCommitter
  • documentation/60-erweiterung/01-hooks.md
Search