API-Nutzung im Frontend
Kurzantwort: CDMS liefert eine REST-API — welches Frontend Sie davorsetzen,
ist Ihre Entscheidung. Empfohlen ist eine serverseitige Zwischenschicht
(Backend for Frontend), die den Token hält und die CDMS-Payloads kapselt, damit
im Browser weder Zugangsdaten noch Backend-Details landen. Dateien laufen als
echtes FormData, nie als JSON.
Das Muster
Abschnitt betitelt „Das Muster“flowchart LR
B["Browser<br/>Komponenten · State"] -->|"/api/…"| N["Serverschicht (BFF)"]
N -->|"Bearer-Token"| C["CDMS<br/>/api/rest/**"]
N -.->|OIDC| K[(Keycloak)]
B -.->|Login-Redirect| K
Warum eine Zwischenschicht?
- Der Token bleibt serverseitig. Der Browser bekommt keinen Backend-Access-Token in die Hand.
- Payload-Kapselung. Response Requests, Diskriminatoren und Filter sind Backend-Details; die Komponenten sehen fertige, typisierte Objekte.
- Fehleraufbereitung. Die Schicht kann Methode, URL, Statuscode und Antwortkörper durchreichen, sodass Fehler nachvollziehbar bleiben.
- Dateiumgang. Multipart-Uploads und Blob-Downloads laufen über den Server, nicht über Browser-Direktaufrufe.
Ein direkter Zugriff aus dem Browser ist technisch möglich — dann müssen Sie CORS, Token-Handling und Refresh selbst lösen und akzeptieren, dass alle Payload-Details im Client sichtbar sind.
Ein Aufruf
Abschnitt betitelt „Ein Aufruf“const response = await fetch(`${apiBaseUrl}/crm/customer/query`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${accessToken}`, }, body: JSON.stringify({ response: ['id', 'name'], parameter: { limit: 25, page: 0, query: { type: 'AND', filter: [{ key: 'name', value: term, param: 'LIKE' }] }, }, }),});Feste Regeln:
- Die Basis-URL zeigt inklusive
/api/restauf das Backend. - Trägt ein Modellname einen Namespace mit Punkten, werden die Punkte im Pfad zu
Schrägstrichen (
crm.customer→crm/customer). - Der Token gehört in den
Authorization-Header, nie in die URL.
Response Requests bewusst wählen
Abschnitt betitelt „Response Requests bewusst wählen“Was nicht in response steht, wird weder geladen noch geliefert. Drei Muster
haben sich bewährt:
| Fall | response |
|---|---|
| Listen und Tabellen | genau die angezeigten Spalten |
| Detailansicht | ["+"] plus gezielt ausgebaute Referenzen |
| Navigation und Bäume | leichter Read, Details erst beim Öffnen nachladen |
Beispiel für eine ausgebaute Referenz:
{ "response": [ "+", { "field": "orders", "response": ["id", "total"], "parameter": { "limit": 10, "order": [{ "field": "total", "order": "DESC" }] } } ]}Details unter Response Requests.
Diskriminatoren
Abschnitt betitelt „Diskriminatoren“Bei polymorphen Modellen muss der konkrete Typ mitgeschickt werden — als
@type im Datenobjekt. Beim Lesen ist er entbehrlich, weil CDMS über die ID
auflöst; beim Anlegen und Ändern ist er verbindlich. Siehe
Vererbung und abstrakte Modelle.
PUT oder PATCH?
Abschnitt betitelt „PUT oder PATCH?“| Absicht | Verb |
|---|---|
| vollständiges Formular speichern | PUT – der Payload ist der Zielzustand |
| einzelne Felder ändern | PATCH – nur die genannten Felder |
| eine Referenz auf „leer” setzen | PATCH mit ausdrücklichem null, oder PUT ohne das Feld |
Nie ein generiertes Payload-Objekt an PATCH schicken. Die Serialisierung schreibt alle nicht gesetzten Felder als
null— und das leert sie. Für PATCH ein schlichtes Objekt mit genau den geänderten Feldern bauen. Siehe Schreibsemantik.
Dateien
Abschnitt betitelt „Dateien“Upload:
const formData = new FormData();formData.append('data', new Blob([JSON.stringify(payload)], { type: 'application/json' }));formData.append('files', file); // Feldname 'files'- Das Feld
nameim Datei-Objekt des Payloads muss dem Originalnamen der Datei entsprechen – darüber läuft die Zuordnung. - Doppelte Dateinamen werden abgelehnt.
- Alternativ Base64 im JSON: ein Objekt mit
content(undname) wird in beliebiger Tiefe erkannt.
Falsch:
{ "file": "[object File]" }Das entsteht, wenn eine File in JSON serialisiert wird.
Download: über die eigene Serverschicht als Blob oder ArrayBuffer, nicht per direktem Browser-Aufruf – der Token gehört nicht in eine URL.
Fehlerbehandlung
Abschnitt betitelt „Fehlerbehandlung“Reichen Sie in der Serverschicht Methode, URL, Statuscode und Antwortkörper durch. Besonders relevant:
| Status | typische Ursache im Frontend |
|---|---|
| 400 | response fehlt, ungültiger Filter, ungültige UUID |
| 403 | Rolle fehlt oder Mandantenwechsel nicht erlaubt |
| 404 | Objekt existiert nicht oder ist unter den Filtern nicht sichtbar |
| 422 | Feldvalidierung – violations direkt auf die Formularfelder mappen |
Die violations tragen den vollen Feldpfad inklusive Verschachtelung
(orders.0.total) und lassen sich damit direkt am Formularfeld anzeigen. Siehe
Fehler und Statuscodes.
Pagination
Abschnitt betitelt „Pagination“parameter.limit = -1 schaltet die Pagination ab. Das ist praktisch für
überschaubare Strukturen wie Navigationsbäume, die in einem Zug kommen sollen —
für Listen unbekannter Größe gehört ein echtes Limit gesetzt.
meta.totalCount kommt nur, wenn parameter.meta = true (Standard).