Response Requests – welche Felder kommen zurück?
Kurzantwort: In jedem Payload steht eine response-Liste. Sie bestimmt,
welche Felder die Antwort enthält – und damit auch, was überhaupt aus der
Datenbank geladen wird. + steht für alle skalaren Felder, * zusätzlich für
alle Referenzen (jeweils nur mit id). Referenzen lassen sich mit einem
verschachtelten Objekt gezielt ausbauen. Eine fehlende response ist ein
Fehler.
Warum es das gibt
Abschnitt betitelt „Warum es das gibt“- kein Overfetching – es wird genau selektiert, was angefragt ist
- keine unkontrollierte Tiefenladung über den ganzen Objektgraphen
- der Client entscheidet, der Server erlaubt
- die Feldprojektion greift bis in die SQL-Abfrage durch (Tuple-Projektion)
Einfache Felder
Abschnitt betitelt „Einfache Felder“{ "response": ["id", "name", "createdAt"] }Wildcards
Abschnitt betitelt „Wildcards“| Wildcard | Wirkung |
|---|---|
+ | alle skalaren Felder |
* | alle skalaren Felder und alle Referenzen, letztere nur mit id |
+suffix / *suffix | alle Felder, deren Name auf suffix endet |
prefix+ / prefix* | alle Felder, deren Name mit prefix beginnt |
{ "response": ["*"] }{ "response": ["+", "name*"] }GET /read/{id} verwendet intern immer ["*"].
Ausschließen
Abschnitt betitelt „Ausschließen“{ "response": ["*"], "exclude": ["internalComment", "secretValue"] }exclude wirkt auf die Wildcard-Expansion: ausgeschlossene Felder werden weder
als skalares Feld noch als Referenz aufgenommen.
Verschachtelte Anfragen
Abschnitt betitelt „Verschachtelte Anfragen“Eine Referenz wird über ein Objekt mit field und eigener response ausgebaut:
{ "response": [ "id", "name", { "field": "orders", "response": ["id", "total", {"field": "items", "response": ["+"]}], "parameter": { "limit": 5, "page": 0, "order": [{"field": "total", "order": "DESC"}], "query": { "type": "AND", "filter": [{"key": "status", "value": "OPEN", "param": "EQ"}] } } } ]}Für Listenreferenzen ist parameter erlaubt – mit Filter, Sortierung und
Pagination wie bei einer eigenständigen Abfrage. CDMS ergänzt automatisch den
Filter auf die Rückreferenz (<backReference>.id = <id des Elternobjekts>).
Was der Expander macht
Abschnitt betitelt „Was der Expander macht“flowchart TB
A["response aus dem Payload"] --> B{Eintrag}
B -->|String ohne Wildcard| C["Feld direkt übernehmen"]
B -->|"'+' oder Muster mit +"| D["alle passenden skalaren Felder"]
B -->|"'*' oder Muster mit *"| E["skalare Felder<br/>+ Referenzen mit nur 'id'"]
B -->|"ModelResponse (field + response)"| F["rekursiv expandieren<br/>je konkretem Untertyp"]
C --> G["RequestSingle/RequestQuery:<br/>fields · models · lists"]
D --> G
E --> G
F --> G
G --> H["Persistenz: Tuple-Projektion<br/>lädt genau diese Spalten"]
Der Expander (cdms-rest-api) zerlegt die response in drei Töpfe:
| Topf | Inhalt |
|---|---|
fields | skalare Felder |
models | Einzelreferenzen, je mit eigenem Unter-Request |
lists | Listenreferenzen, je mit eigenem Unter-Request und parameter |
Er schreibt die expandierte Liste zusätzlich in die response zurück – die
Antwort spiegelt also, was aus der Anfrage geworden ist.
Abstrakte Referenzen
Abschnitt betitelt „Abstrakte Referenzen“Zeigt ein Feld auf ein abstraktes Modell, löst der Expander es für jeden
konkreten Untertyp auf und vereinigt die Ergebnisse. Ein + in einer solchen
verschachtelten Anfrage bedeutet damit „alle skalaren Felder aller möglichen
Untertypen”. Der Unter-Request wird nur einmal an die Elternantwort gehängt.
Fehlerfälle
Abschnitt betitelt „Fehlerfälle“| Situation | Verhalten |
|---|---|
response fehlt ganz | InvalidQueryDefinitionException (400) |
| unbekanntes Feld in einer verschachtelten Anfrage | wird protokolliert und übersprungen |
Feld ist kein Beziehungsfeld, wird aber als ModelResponse angefragt | protokolliert, übersprungen |
| Feld ohne Leserecht | im Strict Mode Fehler, sonst still weggelassen |
Wirkung auf die Datenbank
Abschnitt betitelt „Wirkung auf die Datenbank“Der Response Request ist keine Nachbearbeitung, sondern steuert die Abfrage:
Die Persistenz baut eine CriteriaQuery<Tuple> mit genau den angefragten
Spalten, Referenzen werden mit LEFT JOIN angebunden (damit Objekte ohne
Beziehung nicht herausfallen), und die Aliase in Punktschreibweise
(customer.id) werden wieder zu einer verschachtelten Struktur zusammengesetzt.
Es findet kein Lazy Loading während des Mappings statt.