Worum es geht
Eine Render-Anfrage sagt CRMS, welches Dokument du haben willst: aus welcher Vorlage, in welchem Format, mit welchen Daten. CRMS antwortet im selben Aufruf mit dem fertigen Dokument.
Du kannst CRMS auf zwei Wegen fragen. Eingebettet läuft CRMS in deiner Anwendung, und du rufst eine Java-Schnittstelle auf. Getrennt läuft CRMS als eigener Dienst, und du schickst die Anfrage über HTTP. Der Inhalt der Anfrage ist in beiden Fällen derselbe. Wie die beiden Betriebsarten zustande kommen, steht unter Eingebettet oder getrennt.
Eine Anfrage, Feld für Feld
POST /crms/render
Content-Type: application/json
Authorization: Bearer <Token>
{
"template": "audit-report", ← Schlüssel der Vorlage, Pflicht
"format": "PDF", ← Format, Pflicht
"mode": "FINAL", ← PREVIEW, FINAL oder TRANSIENT, Pflicht
"reference": "audit-4711", ← deine Referenz, Pflicht bei FINAL
"locale": "de-DE", ← Sprache, optional
"timeZone": "Europe/Berlin", ← Zeitzone, optional
"pdfProfile": "PDF_A_3A", ← nur bei PDF, optional
"data": { ← die Payload
"customer": { "name": "ACME" }
},
"attachments": [] ← Bilder dieser Anfrage, optional
}HTTP 200
Content-Type: application/pdf
Content-Disposition: inline; filename="audit-report.pdf"
Crms-Template-Key: audit-report
Crms-Template-Scope: TENANT
Crms-Template-Variant: de
Crms-Template-Revision: 3f0c…
Crms-Template-Revision-Hash: sha-256:9a1e…
Crms-Document-Revision: 7b42… ← nur bei FINAL
X-Content-Type-Options: nosniff
%PDF-1.7 …| Feld | Bedeutung | Pflicht | Wenn es fehlt |
|---|---|---|---|
template | der Vorlagenschlüssel: der feste Name einer Vorlage, kebab-case, etwa audit-report, höchstens 128 Zeichen | ja | required |
format | das Format der Ausgabe: HTML, PDF, DOCX, XLSX, CSV, ODS. Groß- und Kleinschreibung ist egal | ja | required |
mode | PREVIEW, FINAL oder TRANSIENT, siehe Vorschau, endgültig, flüchtig. Groß- und Kleinschreibung ist egal | ja | required |
reference | die Referenz: dein eigener Name für die Sache, zu der das Dokument gehört, etwa die ID eines Audits. CRMS liest sie nicht, es legt endgültige Dokumente darunter ab. 1 bis 255 Zeichen, ohne Leerzeichen am Rand und ohne Steuerzeichen | nur bei FINAL | bei FINAL required |
locale | die Sprache als Sprach-Tag, etwa de oder de-CH | nein | CRMS nimmt die Sprache des Aufrufers, siehe Sprache und Zeitzone |
timeZone | die Zeitzone, etwa Europe/Berlin | nein | die Zeitzone des Containers (TZ), sonst UTC |
pdfProfile | NONE, PDF_A_3A, PDF_UA oder PDF_A_3A_UA, nur bei format: PDF | nein | das Standardprofil der Installation, siehe Ausgabetypen und Formate |
data | die Payload: die Daten, die die Vorlage einsetzt. Ein JSON-Objekt | nein | leere Payload |
attachments | Bilder, die nur zu dieser Anfrage gehören, siehe Bilder und SVG | nein | keine Anhänge |
Die Antwort-Header sagen dir genau, woraus das Dokument entstanden ist: welche Vorlage, aus welchem Scope (Ebene, auf der die Vorlage gilt: System, Mandant oder Benutzer), welche Sprachvariante, welche Revision (eine freigegebene, unveränderliche Fassung der Vorlage) und deren Hash. Wie CRMS die Vorlage findet, steht unter Wie CRMS die Vorlage findet.
Wie CRMS die Anfrage liest
Über REST liest CRMS den JSON-Körper Feld für Feld. Dabei gelten strenge Regeln:
- Unbekannte Felder werden abgelehnt (
not-allowed). Ein vertippter Name wierefrencefällt sofort auf, statt still nichts zu bewirken. - Falscher JSON-Typ ist
invalid. CRMS wandelt nichts um:42ist kein Vorlagenschlüssel. nullzählt wie ein fehlendes Feld.- Kommazahlen in
datawerden als exakte Dezimalzahlen gelesen, nicht als Gleitkommazahlen. Ein Betrag behält so genau seine Stellen. pdfProfilebei einem anderen Format als PDF istnot-allowed.- Alle kaputten Felder kommen in einer Antwort: 422
validation-failedmitviolations.
Der Körper ist begrenzt, bevor er gelesen wird. Die Grenze ergibt sich aus der Payload-Grenze, der Anhang-Grenze und etwas Platz für die übrigen Felder. Ist er größer, antwortet CRMS mit 422 payload-rejected und dem Verstoß payload-too-large. Der Körper darf mit Content-Encoding: gzip gepackt kommen. Die Grenze gilt dann für die entpackten Bytes. Andere Kodierungen sind 415 content-encoding-unsupported.
Die Stationen bis zum Rendern
Bevor CRMS rendert, prüft es die Anfrage in dieser Reihenfolge. Jede Station kann die Anfrage beenden.
-
CRMSFormatBietet die Installation das Format an, und ist ein Formatierer dafür installiert?↳ nein 422
format-not-offered|<format> -
CRMSModusIst FINAL bzw. TRANSIENT in dieser Installation eingeschaltet?↳ nein 409
document-revisions-disabledodertransient-documents-disabled -
CRMSAnhängeWenn Anhänge dabei sind, ist es kein FINAL, und kann das Format sie zeichnen?↳ nein 422
attachments-not-for-finaloderattachments-not-for-format|<format> -
CIASAufruferIst der Aufrufer angemeldet?↳ nein 401
crms-authentication-required -
CRMSVorlageGibt es eine Vorlage mit diesem Schlüssel, die der Aufrufer erreicht?↳ nein 404
template-not-found -
CRMSScope bei TRANSIENTKommt die Revision bei TRANSIENT aus dem Scope SYSTEM?↳ nein 422
transient-requires-system-template -
CRMSAusgabetypPasst das Format zum Ausgabetyp der Vorlage?↳ nein 422
format-not-for-template|<format>|<ausgabetyp> -
CRMSPayload und AnhängeHält die Payload die Regeln ein, und sind die Anhänge in Ordnung?↳ nein 422
payload-rejectedmit allen Verstößen - CRMS rendert und gibt das Dokument zurück
Erst nach der letzten Station kommt die eigentliche Arbeit: Vorlage ausführen, Format erzeugen, bei FINAL siegeln und ablegen. Was dabei schiefgehen kann, steht unter Ausführung und Grenzen. Alle Fehler kommen in einer Form zurück, siehe Fehler und Message Keys.
Die Wege, eine Anfrage zu stellen
Wann: CRMS läuft in deiner Anwendung
Du lässt dir ReportRenderPort geben und rufst render(request) auf. Für die drei Modi gibt es Kurzformen: RenderRequest.preview(key, format, data), RenderRequest.transientDocument(key, format, data) und RenderRequest.finalDocument(key, format, reference, data). Sprache, Zeitzone und PDF-Profil bleiben dabei CRMS überlassen. Du bekommst ein RenderedDocument mit Format, Bytes, Herkunft und bei FINAL der Dokument-Revision. Fehler kommen als CrmsException mit Message Key, eine abgelehnte Payload als PayloadRejectedException mit den Verstößen.
Ergebnis: Dokument als Bytes im selben Aufruf
Wann: CRMS läuft als eigener Dienst, oder ein Frontend ruft CRMS direkt
POST /crms/render mit dem JSON von oben und einem Token. Die Antwort sind die Bytes des Dokuments mit Content-Type und den Crms-Template-*-Headern. Eine Anwendung ruft CRMS meist über crms-client, der dieselbe Schnittstelle wie eingebettet anbietet, siehe crms-client.
Ergebnis: Dokument als HTTP-Antwort
Wann: du willst wissen, ob eine Anfrage rendern würde, ohne ein Dokument zu erzeugen
POST /crms/render/validate mit demselben Körper, eingebettet validate(request). CRMS läuft alle Stationen durch und führt die Vorlage einmal zur Probe aus, erzeugt aber kein Format. Die Antwort ist {"violations": [...]}. Leer heißt: würde rendern. Verstöße der Payload und Fehler in der Vorlage (im Feld template) stehen in der Liste. Scheitert eine andere Station, etwa das Format, kommt der Fehler wie beim Rendern.
Ergebnis: Liste der Verstöße, leer oder nicht
Wann: eingebettet, für sehr große Dokumente
renderTo(request, outputStream) schreibt die Bytes direkt in deinen Stream und gibt nur Format, Größe und Herkunft zurück. Bei FINAL puffert CRMS trotzdem das ganze Dokument, weil es erst abgelegt wird und dann zu dir geht.
Ergebnis: Bytes im Stream, Beschreibung als Rückgabe
Ein eingebetteter Aufruf aus dem Hub sieht so aus. Er rendert eine flüchtige Kopie ohne Referenz und ohne eigene Zeitzone:
RenderedDocument document = renderer.render(new RenderRequest(
new TemplateKey("arc42"), // template key
Locale.forLanguageTag("de"), // language, or null
null, // time zone: TZ, then UTC
OutputFormat.PDF,
null, // PDF profile: the installation's default
RenderMode.TRANSIENT,
null, // reference: only for FINAL
data));
Was eine Installation anbietet
GET /crms/capabilities sagt, was du anfragen kannst: die angebotenen Formate, das Standard-PDF-Profil, die zugelassenen Scopes, die Sprachen der Installation, ob endgültige Dokumente gespeichert werden (documentRevisions), ob flüchtige erlaubt sind (transientDocuments) und die Grenzen. Eingebettet liefert CapabilitiesPort dasselbe. Die Werte kommen aus der Konfiguration und ändern sich im Betrieb nicht.
GET /crms/capabilities{
"formats": ["HTML", "PDF", "DOCX"],
"defaultPdfProfile": "PDF_A_3A",
"scopes": ["TENANT", "SYSTEM"],
"locales": ["de", "en"],
"documentRevisions": true,
"transientDocuments": false,
"limits": {
"timeout": "PT30S",
"maxOutputBytes": 52428800,
"maxPayloadBytes": 5242880,
"maxAttachmentCount": 200,
"maxAttachmentBytes": 52428800
}
}