CodamAIDocs
Themafertig

Singletons: genau ein Objekt

Manche Modelle gibt es nur einmal pro Scope, etwa Einstellungen eines Benutzers. Hier steht, wie die Pfade ohne ID funktionieren und was bei doppeltem Anlegen oder fehlendem Objekt passiert.

Ausprägungen
Singleton pro Systempro Mandantpro Benutzeranlegen, lesen, ersetzen, ändern, löschenzweites Create → 400Lesen/Ändern ohne Objekt → 404Löschen ohne Objekt → keine WirkungDatei, Historie und Rollback

Worum es geht

Manche Daten gibt es nur einmal: die Einstellungen einer Person, die Konfiguration eines Mandanten, die Grundeinstellungen der ganzen Installation. Für solche Fälle markierst du ein Modell im Hub als Singleton.

Ein Objekt pro was?

Wie viele Objekte es insgesamt gibt, bestimmt die Modell-Ebene:

Die drei Singleton-Arten
System-Singleton
Scope „Systemweit“
  • ein Objekt für die ganze Installation
  • in der System-Datenbank
  • Beispiel: Grundeinstellungen der Plattform
Mandanten-Singleton
Scope „Mandant“
  • ein Objekt je Mandant
  • in der Mandanten-Datenbank
  • Beispiel: Konfiguration einer Firma
Benutzer-Singleton
Scope „Benutzer“
  • ein Objekt je Person
  • in der Mandanten-Datenbank, gefiltert nach _userId
  • Beispiel: persönliche Einstellungen

Die Endpunkte ohne ID

Normales Modell und Singleton nebeneinander
Normales ModellSingleton
anlegenPOST /createPOST /create
lesenPOST /read/{id}POST /read
schnell ansehenGET /read/{id}GET /read
ersetzenPUT /update/{id}PUT /update
ändernPATCH /update/{id}PATCH /update
löschenDELETE /delete/{id}DELETE /delete
suchenPOST /querygibt es nicht
Datei herunterladenGET /{id}/fileGET /file
HistoriePOST /{id}/historyPOST /history
RollbackPOST /{id}/rollback/{revision}POST /rollback/{revision}

Das Objekt hat trotzdem eine id. Sie steht in der Antwort, der Client muss sie aber nie mitschicken.

Nur die Suche fehlt, denn es gibt nichts zu suchen. Historie und Rollback gibt es dagegen genau wie bei jedem anderen auditierten Modell: Die Historie ist keine Liste von Objekten, sondern der Verlauf eines Objekts über die Zeit.

Wie der Server das eine Objekt findet

Vor jeder Operation sucht der Server das vorhandene Objekt, mit denselben Regeln wie eine normale Suche:

Das Objekt ermitteln
  1. 1
    CDMS
    wählt die Datenbank nach der Modell-Ebene (System-DB oder die des Mandanten aus dem Token)
  2. 2
    CDMS
    hängt bei Benutzer-Singletons den Filter _userId = angemeldete Person an
  3. 3
    CDMS→Database
    sucht das Objekt
  4. 4
    CDMS
    gefunden → dessen id wird für die Operation benutzt. Nicht gefunden → es gibt noch keins

Alle Operationen im Ablauf

Was bei jeder Operation passiert

Wann: POST /create

  1. 1
    CDMS
    Gibt es schon ein Objekt in diesem Scope?
  2. 2
    CDMS→Client
    ja → 400 object-already-exists|use-update
  3. 3
    CDMS→Database
    nein → legt das Objekt an wie bei einem normalen Modell, mit Rechteprüfung, Validierung und Hooks

Ergebnis: Das eine Objekt existiert jetzt.

Wann: POST /read mit response, oder GET /read

  1. 1
    CDMS
    ermittelt das Objekt
  2. 2
    CDMS→Client
    nicht vorhanden → 404 no-object-found
  3. 3
    CDMS→Client
    vorhanden → liefert es mit den angeforderten Feldern

Wann: PUT /update

  1. 1
    CDMS
    ermittelt das Objekt
  2. 2
    CDMS→Client
    nicht vorhanden → 404 no-data-exists|use-create
  3. 3
    CDMS
    vorhanden → setzt dessen id selbst in die Payload ein und ersetzt wie ein normales PUT

Wann: PATCH /update

  1. 1
    CDMS
    ermittelt das Objekt
  2. 2
    CDMS→Client
    nicht vorhanden → 404 no-object-found
  3. 3
    CDMS
    vorhanden → setzt die id selbst ein und ändert wie ein normales PATCH: fehlendes Feld bleibt, null leert

Wann: DELETE /delete

  1. 1
    CDMS
    ermittelt das Objekt
  2. 2
    CDMS
    vorhanden → löscht es wie ein normales DELETE. Nicht vorhanden → nichts zu tun, kein Fehler

Ergebnis: Danach gibt es kein Objekt mehr; ein neues create ist wieder möglich.

Wann: GET /file, POST /history

Wie beim normalen Modell, nur ohne id im Pfad. Beide antworten mit 404, wenn es noch kein Objekt gibt. Die Historie gibt es nur bei auditierten Modellen.

Wann: POST /rollback/{revision}, bei auditierten Modellen mit Rollback-Endpunkt

  1. 1
    CDMS
    ermittelt das Objekt
  2. 2
    CDMS→Client
    nicht vorhanden → 404 data-not-found
  3. 3
    CDMS
    vorhanden → prüft die Rollback-Rolle, führt die ROLLBACK-Hooks aus und stellt die genannte Revision wieder her, genau wie beim normalen Modell

Ergebnis: Der alte Stand ist zurück, als neue Revision. Die Revisionsnummer stammt aus der Historie (revisionMeta.ref).

Die Lebenslinie eines Singletons

stateDiagram-v2
    direction LR
    [*] --> Leer
    Leer --> Vorhanden: POST /create
    Leer --> Leer: read / update / patch → 404
    Vorhanden --> Vorhanden: read, PUT, PATCH, rollback
    Vorhanden --> Vorhanden: create → 400 use-update
    Vorhanden --> Leer: DELETE

Typisches Muster im Client

Weil create und update getrennt sind, braucht ein Einstellungsdialog eine kleine Weiche:

Einstellungen speichern
Hat GET /read beim Öffnen ein Objekt geliefert?Beim Speichern aufrufen
jaPATCH /update mit den geänderten Feldern
nein (404)POST /create mit allen Feldern

Fallen

Quellen im Code und in der Wissensdatenbank
  • CDMS/cdms-rest-api – AbstractRestSingletonApi
  • CDMS/cdms-system-layer – AbstractSystemSingletonLayer, AbstractSystemLayer.getSingletonByQuery
  • CDMS/cdms-generator – ApiSingletonProcessor, CdmsYamlLoader (singleton)
  • documentation/10-cdms-grundlagen/02-modelle-und-metadaten.md (Singletons)
Suchen