CodamAIDocs
Topicdone

System fields that the server sets

CDMS sets fields such as id, _createdOn, _userId, _MODELTYPE and _version itself. This page explains when each field is set and which of them the client may send.

Variants
id_createdOn_updatedOn_userId (USER models only)_MODELTYPE / @type_version (file models only)internal helper fieldssent by the client → ignored

What this is about

Besides its business fields, every object in CDMS has a few system fields. The server sets them, not the client. You can almost always recognize them by the leading underscore.

The system fields

FieldMeaningPresent onJSON name
idunique identifier, a UUIDevery modelid
_createdOnwhen the object was createdevery model_createdOn
_updatedOntime of the last changeevery model_updatedOn
_userIdID of the person the object belongs touser models only_userId
_MODELTYPEconcrete type of the objectevery model, important for abstract models@type
_versionversion counter against concurrent overwritesfile models only–

On top of that there are internal helper fields such as _reference, which CDMS uses during processing, for example so that nested writing does not run in circles. Do not evaluate them in the client.

Who sets what, and when?

System fields per operation
Create (POST /create)Replace / update (PUT, PATCH)Roll back
idgenerated by the database on save; an id sent by the client is ignoredstays; it decides which object is changedstays
_createdOnset to nowunchangedstays
_updatedOnstays emptyset to nowunchanged
_userIdset to the signed-in personunchangedstays
_MODELTYPE / @typefollows from the concrete type; for abstract models the client picks it with @typeunchanged, an object never changes its typestays
_versioncreated by the databaseincremented on every changeas for a change

What happens if the client sends them?

A create with system fields sent along
  1. 1
    Client→CDMS
    sends { "data": { "id": "abc", "_userId": "someone-else", "_createdOn": "2020-01-01 00:00:00", "name": "Muster" }, "response": ["+"] }
  2. 2
    CDMS
    walks through the fields of the model and skips id and every field starting with _
  3. 3
    CDMS
    sets _createdOn to now and _userId to the signed-in person
  4. 4
    Database
    assigns a new id
  5. 5
    CDMS→Client
    responds with the server's values
    Result: name is stored. id, _userId and _createdOn come from the server, not from the request. There is no error.

PUT and PATCH behave the same way, with one exception: there the id must be in data, because it says which object is meant. It is never changed.

The id in the write operations
Operationid in data?What happens
POST /createanyignored, the server assigns a new one
PUT /update/{id}yesdecides the object that is replaced
PUT /update/{id}no400 missing-id
PATCH /update/{id}yesdecides the object that is changed
PATCH /update/{id}no400 missing-id

What you get when reading

CDMS reads four values on every access, even if they are not in response: id, _createdOn, _updatedOn and the type.

Request with response: ["name"] on a model with name, email, address
simple fieldreferencereturned
RequestResult
["name"]
id_createdOn_updatedOn@typenameemailaddress
id, _createdOn, _updatedOn and the type always come along. email and address are null in the response.

There is a practical reason for this: with id and type the client can always identify an object unambiguously, even if it requested only one business field.

Each field in brief

The system fields one by one

When: every object

A UUID, stored as 16 bytes in the database. It is created on the first save and never changes. You address an object by it in every path: /read/{id}, /update/{id}, /delete/{id}. Singletons have one too, but it does not appear in any path.

When: every object

The server sets the time on create, including child objects created in the same request. After that it never changes, not even on a rollback.

When: every object

The server sets the time to now on every PUT and PATCH. On create the field stays empty; on a rollback to an old revision it stays unchanged. So it tells you when the object was last changed, but not by whom or what. That is what the history is for.

When: only models with the scope “user”

The ID of the person the row belongs to, taken from the sub claim of the token. It is set on create and then used by the owner filter: each person only sees rows with their own _userId. See Model levels.

When: every object, essential for abstract models

In the database the column is called _MODELTYPE, in JSON @type. For an abstract model, e.g. customer with privatecustomer and businesscustomer, it says which concrete type an object is. When creating under an abstract model, the client has to name it. See Abstract models.

When: file models only

A counter that the database increments on every change of the object. If two requests write a new file into the same object at the same time, the second fails with 409 instead of silently overwriting the first. See Concurrent changes.

System fields and history are two different things

System fields
on the object itself
  • one value per field, the current state
  • present on every model
  • says: created when, belongs to whom, which type
History
revisions, audited models only
  • every change with the old state
  • with time, person, IP address, browser
  • says: who changed what, and when

More in Audit is not the same as system fields.

Sources in the code and the knowledge base
  • CDMS/cdms-persistence-database – AbstractEntityModel, AbstractUserModel, projection/SelectionBuilder, auditing/AuditHistoryReader
  • CDMS/cdms-system-layer – AbstractLayer (recursiveCreate/Update/Patch: `_` fields and id are skipped, _createdOn/_userId on create)
  • CDMS/cdms-system-layer – models/AbstractDtoModel, AbstractDtoHubModel
  • CDMS/cdms-generator – EntityProcessor (_version on file models, _MODELTYPE discriminator)
Search