What this is about
A model is either audited or not. Audited means: CDMS keeps the new state every time an object changes. Such a stored state is called a revision. All revisions of an object together are its history.
Whether a model is audited is decided by a single switch on the model: in the hub “Auditing: yes”, in a model file auditing: true. The switch applies to the whole model. You cannot leave out individual fields.
The timeline of an object
This is the history of an order that is created, changed twice, rolled back once and then deleted:
flowchart LR
A["Revision 17 · ADD<br/>POST /create<br/>price 90.8"] --> B["Revision 42 · MOD<br/>PATCH<br/>price 120.5"]
B --> C["Revision 51 · MOD<br/>PUT<br/>price 99.0"]
C --> D["Revision 58 · MOD<br/>rollback to 17<br/>price 90.8"]
D --> E["Revision 63 · DEL<br/>DELETE"]
Every revision has a type, in JSON revisionType:
| Type | Meaning | What the revision contains |
|---|---|---|
ADD | the object was created | the state right after creating |
MOD | the object was changed | the state right after the change |
DEL | the object was deleted | only the id, all other fields are empty |
The numbers go up, but they have gaps. Revisions of other objects lie in between. More in What a revision records.
Which operation creates which revision
| Operation | Revision |
|---|---|
POST /create | ADD |
PUT /update/{id}, PATCH /update/{id} | MOD, even if nothing changes in terms of content, because _updatedOn is set again |
| new file content for a file model | MOD, because fileVersion, size and type change |
POST /{id}/rollback/{revision} | MOD with the old content, see Rolling back to an old state |
DELETE /delete/{id} | DEL |
| a child is created, changed or deleted in the same request | an ADD, MOD or DEL revision of its own for the child, if its model is audited |
| only a list of the object changes | MOD for the object that holds the list |
| read, search, read history, download | no revision |
The revisions are only created when the request ends successfully. If it fails, the revision is discarded together with everything else. See One request, one transaction.
One request, one revision number
If a request changes several objects, all changes get the same revision number. An order with three new items, created in one request, therefore results in one revision 17, and it contains the order and the three items, each as ADD.
This applies per database. If a request touches models in the system database and in the tenant database, each database gets a revision of its own with its own number. See No atomicity across two databases.
Audited or not
| Model audited? | Request writes? | Request successful? | Result |
|---|---|---|---|
| no | – | – | no revision, there is only the current state |
| yes | no | – | no revision, reading is not recorded |
| yes | yes | no | no revision, the change was discarded |
| yes | yes | yes | new revision ADD, MOD or DEL |
- every change becomes a revision
- history and rollback are possible if the endpoints are listed
- for file models every old content stays as a version
- the database gets an audit table for every table
hibernate-enversis added to the POM
- only the current state
- no history, no rollback, even if the endpoints are listed
- new file content overwrites the old one
- nothing remains after deleting
What happens in the background
You do not need to know this to use the API. It helps, though, when you look into the database:
-
1HubThe model is set to "Auditing: yes".
-
2BuildThe generator writes
@Auditedon the entity class and addshibernate-enversto the POM.Envers is the library that writes revisions. See The project scaffold. -
3DatabaseFor every table of the model there is an audit table
<table>_AUD, plus the tablerevinfoonce per database. -
4CDMS→DatabaseOn every successful write, Envers adds a row to
revinfoand, for every changed object, a row to its_AUDtable.Result:revinfosays who, when and from where. The_AUDrow holds the state of the object.
The endpoints for reading the history and for rolling back are only created if the model is audited and they are in the endpoint list. See Which endpoints a model has.
Special cases
When: A model with existing data is set to audited and generated again.
The history starts with the first change after that. For an existing object the first revision is then a MOD, there is no ADD. CDMS does not know older states, and you cannot roll back to them either.
When: An audited model is set to not audited.
New changes are no longer recorded, and the endpoints for history and rollback go away. What was recorded until then stays in the database, but can no longer be reached through the API.
When: An audited model has a relation to another model.
The target model must be audited as well. Envers rejects an audited model that points to a model that is not audited, and the application then does not start. That is why you audit models that are connected to each other together.
Pitfalls
What comes next
- What a revision contains: What a revision records
- Fetching revisions: Reading the history
- Back to an old state: Rolling back to an old state
- What remains after a delete: What remains after a delete