CodamAIDocs
Themafertig

Der Projektrahmen (Scaffold)

Was ein neues Projekt beim ersten Mal bekommt (POM, Start-Klasse, Konfiguration) und welche Zweige es gibt, z. B. CIAS eingebettet oder entfernt.

Ausprägungen
Authentifizierung OIDC oder NONECIAS EMBEDDED / REMOTE / NONEDatenbank MYSQL / MARIADBSpeicher FILESYSTEM oder NONEMonitoring ACTUATOR oder NONEAuditing (abgeleitet)erster Download, späterer Build

Worum es geht

Ein neues CDMS-Projekt fängst du nicht mit einem leeren Ordner an. Der Hub gibt dir einen Projektrahmen (englisch Scaffold, „Baugerüst“): ein ZIP mit POM, Start-Klasse, Konfiguration und dem aktuellen Modell. Den entpackst du, baust einmal, und die Anwendung läuft.

Was genau im Rahmen steht, hängt von ein paar Einstellungen am System im Hub ab: Mit welcher Datenbank arbeitet es? Braucht es Anmeldung? Läuft CIAS mit im selben Prozess? Jede Einstellung ist ein Zweig, der Abhängigkeiten, Konfiguration und manchmal Klassen hinzufügt.

So kommst du zum Rahmen

  1. 1
    Entwickler→Hub
    öffnet das System im Hub und klickt Projekt-Rahmen
  2. 2
    Hub
    liest die Einstellungen des Systems und das Modell
  3. 3
    Hub→Entwickler
    liefert <id>-project.zip
    Dahinter steht GET /api/rest/cms/system/{id}/scaffold. Du kannst den Rahmen also auch per Skript holen.
  4. 4
    Entwickler
    entpackt, trägt das Client-Secret in cdms-generator.properties ein, legt .env an
  5. 5
    Build
    mvn clean compile: holt die Metadaten, pflegt die POM, generiert den Code
    Ergebnis: Ein lauffähiges Projekt

Was im ZIP steht

katalog/
├── pom.xml                         ← Parent cdms-app-parent, Abhängigkeiten je Zweig
├── README.md                       ← Bauen, Starten, alle Umgebungsvariablen
├── cdms-generator.properties       ← Zugang zum Hub für den Build (Secret leer)
├── .env.example                    ← Laufzeitvariablen: Datenbank, Mandantenmodus, CIAS …
├── .gitignore
├── .cache/                         ← das Modell als YAML, damit der erste Build offline geht
│   ├── system.yaml
│   └── models.yaml …
└── src/
    ├── main/java/com/codamai/shop/katalog/
    │   ├── Start.java              ← Spring-Boot-Start-Klasse
    │   └── config/                 ← nur bei CIAS EMBEDDED: drei Verdrahtungsklassen
    ├── main/resources/application.yaml
    └── test/java/…/TenantContextArchitectureTest.java   ← nur mit Anmeldung (OIDC)
Dateiwozu
pom.xmlParent ist cdms-app-parent. Er bringt den ganzen Build mit: Metadaten holen, Codegenerator, Spring-Boot-Paket, Native Image. Deine POM enthält nur Koordinaten, ein paar Properties und die Abhängigkeiten.
Start.java@SpringBootApplication für das Paket com.codamai. Ohne sie gäbe es keine Quelldatei, und ohne Quelldatei laufen keine Annotation-Processors, also auch kein Generator.
application.yamldeine Konfiguration. Datenbank, Mandantenmodus und Identity Provider stehen bewusst nicht hier, sondern kommen aus der Umgebung.
.env.exampleVorlage für die Umgebungsvariablen. Immer dabei: CODAMAI_PERSISTENCE_TENANT_MODE=SINGLE und die Datenbankzugänge CODAMAI_PERSISTENCE_DATABASE_*.
cdms-generator.propertiesSystem-ID, Hub-Adresse, Keycloak-Adresse, Realm, Client-ID und cacheDir=.cache. Das clientSecret trägst du selbst ein. Die Datei steht in .gitignore.
.cache/das Modell zum Zeitpunkt des Downloads, siehe Codegenerierung im Build

Die Maven-Koordinaten leitet der Hub aus den Namen ab. Aus dem Projekt „Shop“ und dem System „Katalog“ wird groupId com.codamai.shop, artifactId katalog und das Basispaket com.codamai.shop.katalog.

Die Zweige

Die Einstellungen stehen am System im Hub. Der Build liest sie später aus .cache/system.yaml. Maven- oder Spring-Properties schalten die Zweige nicht.

flowchart TD
    A{"authentication"} -- "NONE" --> N["keine Anmeldung<br/>CIAS ist immer NONE"]
    A -- "OIDC" --> O["+ cias-authentication<br/>+ Architekturtest<br/>+ CIAS_ISSUER, CIAS_CLIENT …"]
    O --> C{"cias"}
    C -- "REMOTE" --> R["+ cias-tenancy-client<br/>CIAS läuft als eigener Service"]
    C -- "EMBEDDED" --> E["+ cias-tenancy, cias-user,<br/>cias-authorization, cias-iam-keycloak<br/>+ Block codamai.cias<br/>+ 3 Klassen unter config/"]
    C -- "NONE" --> X["kein CIAS-Mandantendienst"]
    D{"database"} -- "MYSQL" --> D1["mysql-connector-j"]
    D -- "MARIADB" --> D2["mariadb-java-client"]
    S{"storage"} -- "FILESYSTEM" --> S1["+ cdms-localfs-storage<br/>+ basePath /files/"]
    S -- "NONE" --> S0["keine Dateien"]
    M{"monitoring"} -- "ACTUATOR" --> M1["+ Prometheus, AOP<br/>+ Metriken und Probes auf 8081"]
    M -- "NONE" --> M0["nur Actuator-Grundausstattung<br/>auf 8081"]
    U{"ein Modell auditiert?"} -- "ja" --> U1["+ hibernate-envers"]
Was jeder Zweig am Rahmen ändert

Wann: authentication: OIDC oder NONE

OIDC: Die POM bekommt cias-authentication (prüft jedes Token) und für Tests cias-test-support. In .env.example stehen CIAS_ISSUER (der Issuer so, wie er im Token steht), CIAS_CLIENT und CIAS_CLIENT_SECRET, dazu auskommentiert CIAS_BACKCHANNEL_URL. Dazu kommt der Test TenantContextArchitectureTest. Er prüft, dass der Mandant nur aus dem Mandanten-Tor kommt. NONE: nichts davon. Ohne Anmeldung gibt es auch kein CIAS.

Ergebnis: Mit OIDC ist jede Anfrage angemeldet, siehe Token-Prüfung

Wann: cias: EMBEDDED (nur mit OIDC)

CIAS läuft im selben Prozess wie CDMS. Die POM bekommt cias-tenancy, cias-user, cias-authorization und cias-iam-keycloak. application.yaml bekommt einen Block codamai.cias (Mandantenverwaltung an, Mandanten werden lokal nachgeschlagen). Unter config/ liegen drei Klassen, die CIAS verdrahten: CiasEmbeddedConfiguration, CiasIdentityConfiguration, CiasRepositoryTransactionsPostProcessor. Benutzer- und Rechteverwaltung sind vorbereitet und schaltest du über CIAS_USER und CIAS_AUTHORIZATION ein.

Ergebnis: Eine Einheit, siehe Eingebettet

Wann: cias: REMOTE (nur mit OIDC, Standard)

CIAS läuft als eigener Service. Die POM bekommt nur cias-tenancy-client. Er fragt CIAS nach den Mandanten. In .env.example steht CODAMAI_CIAS_TENANCY_CLIENT_BASE_URL, die Adresse des CIAS-Service.

Ergebnis: Zwei Services, siehe Getrennt

Wann: cias: NONE

Kein CIAS-Baustein im Rahmen. Die Anwendung prüft Tokens, fragt aber keinen Mandantendienst.

Wann: database: MYSQL oder MARIADB

Die POM bekommt den passenden JDBC-Treiber. .env.example bekommt CODAMAI_PERSISTENCE_DATABASE_DRIVER und eine Beispiel-URL wie jdbc:mysql://localhost:3306/{tenant}. {tenant} ersetzt CDMS zur Laufzeit durch den Mandanten, siehe Welche Datenbank?

Wann: storage: FILESYSTEM oder NONE

FILESYSTEM: Die POM bekommt cdms-localfs-storage, application.yaml den Ablageort codamai.cdms.persistence.file.basePath (Standard /files/, per CODAMAI_CDMS_PERSISTENCE_FILE_BASE_PATH änderbar). NONE: kein Dateispeicher.

Ergebnis: Siehe Speicher-Backends

Wann: monitoring: ACTUATOR oder NONE

Den Spring-Boot-Actuator hat jede Anwendung, immer auf dem eigenen Management-Port 8081, der nicht nach außen geht. ACTUATOR legt nach: micrometer-registry-prometheus und spring-boot-starter-aop in der POM, in application.yaml die Endpunkte health, info, metrics, prometheus und Health-Probes für Kubernetes.

Wann: mindestens ein Modell ist auditiert

Dafür gibt es keinen Schalter. Sobald ein Modell im Hub auditiert ist, kommt hibernate-envers in die POM.

Ergebnis: Siehe Was auditiert wird

Ob die Anwendung einen oder viele Mandanten bedient, ist kein Zweig des Rahmens. Das entscheidet zur Laufzeit CODAMAI_PERSISTENCE_TENANT_MODE (SINGLE oder MULTI), siehe Single- oder Multi-Tenant.

Ein Beispiel

Rahmen für OIDC, CIAS REMOTE, MySQL, Dateien, Actuator, ein Modell auditiert
pom.xml (gekürzt)
<parent>
  <groupId>com.codamai.cdms</groupId>
  <artifactId>cdms-app-parent</artifactId>
</parent>
<properties>
  <cdms.main.class>com.codamai.shop.katalog.Start</cdms.main.class>
  <cdms.generator.fetch.skip>false</cdms.generator.fetch.skip>
</properties>
<dependencies>
  <!-- cdms-managed:dependencies:start -->
  … Kern: cdms-rest-api, cdms-system-layer, cdms-database …
  hibernate-envers               ← Auditing
  mysql-connector-j              ← database: MYSQL
  cdms-localfs-storage           ← storage: FILESYSTEM
  cias-authentication            ← authentication: OIDC
  micrometer-registry-prometheus ← monitoring: ACTUATOR
  cias-tenancy-client            ← cias: REMOTE
  <!-- cdms-managed:dependencies:end -->
</dependencies>
application.yaml (gekürzt)
spring:
  application: { name: katalog }
  threads: { virtual: { enabled: true } }
codamai:
  cdms:
    api: { createReadMode: STRICT }
    persistence:                         ← storage: FILESYSTEM
      file:
        basePath: ${CODAMAI_CDMS_PERSISTENCE_FILE_BASE_PATH:/files/}
management:
  server: { port: 8081 }
  endpoints: { web: { exposure: { include: health, info, metrics, prometheus } } }   ← monitoring: ACTUATOR

Einmal erzeugt, danach deins

Was passiert mit den Dateien, wenn du später baust oder den Rahmen erneut herunterlädst?

Wer schreibt welche Datei nach dem ersten Mal?
DateiWas bei jedem Build passiert
pom.xml: Parent, verwaltete Properties, Bereich zwischen den cdms-managed-Markernwird nach dem Hub neu geschrieben
pom.xml: Koordinaten, eigene Abhängigkeiten, Plugins, eigene Propertiesbleibt erhalten
Start.java, OpenApiConfiguration, NativeHintsConfigurationlegt der Generator an, wenn sie fehlen, sonst nie angefasst
application.yaml, .env.example, CIAS-Klassen unter config/nie angefasst
generierter Code in target/generated-sources/bei jedem Build neu

Zwei Konsequenzen:

  • Einen Zweig nachträglich ändern (etwa storage auf FILESYSTEM) wirkt beim nächsten Build auf die POM: Die Abhängigkeit kommt hinzu, abgewählte fliegen raus. Die passende Konfiguration in application.yaml und .env trägst du selbst nach. Das README eines frischen Rahmens zeigt dir, was dort stehen muss.
  • Ein neuer Download ist ein neues ZIP. Es wird nichts mit deinem Projekt zusammengeführt. Nimm dir daraus, was du brauchst.

Die POM-Pflege schaltest du mit CODEGEN_POM_GENERATE=false ab.

Fallen

Quellen im Code und in der Wissensdatenbank
  • CDMS/cdms-scaffold – CdmsScaffoldService, CdmsPomWriter, CdmsDependencyRegistry, CdmsReadmeWriter, model/CdmsProjectCoordinates, cdms-version-registry.yaml, templates/
  • CDMS/cdms-generator – generator/CdmsProcessor, StartClassProcessor, OpenApiConfigProcessor, NativeHintsConfigProcessor, CdmsPomProcessor, CdmsPomMerger, CdmsSystemContext
  • CDMS/cdms-parent – cdms-app-parent/pom.xml (Profil cdms-application)
  • hub-backend – services/SystemExportApi, SystemScaffoldService, config/ScaffoldProperties
  • CDMS/frontend – pages/modules/[id]/index.vue, composables/cdms/useCdmsSystemScaffold.ts
  • documentation/10-cdms-grundlagen/03-generierung.md, 04-konfiguration.md
Suchen