Zum Inhalt springen

Codegenerierung

Kurzantwort: Der cdms-generator ist ein Java-Annotation-Processor. Er liest beim Maven-Build einen YAML-Cache mit der Modellbeschreibung und erzeugt pro Modell rund 20 Java-Klassen nach target/generated-sources/annotations/. Der YAML-Cache kommt vorher vom CdmsMetadataFetcher aus einer laufenden CDMS-Instanz – oder liegt bereits lokal vor (Offline-Modus).


flowchart TB
    subgraph "Maven: generate-sources"
        F[CdmsMetadataFetcher]
        K[(Keycloak)]
        API[(CDMS REST-API)]
        Y["YAML-Cache<br/>models.yaml · folders.yaml<br/>enumerations.yaml · system.yaml"]
        F -->|Client-Credentials-Token| K
        F -->|Modelle, Felder, Endpunkte| API
        F --> Y
    end
    subgraph "Maven: compile"
        L[Lombok] --> MS[MapStruct] --> G[CdmsProcessor]
        Y --> G
        G --> GEN["target/generated-sources/annotations/<br/>~20 Klassen je Modell"]
        G --> SC["src/main/java/…<br/>Scaffold, nur wenn nicht vorhanden"]
    end

Die Reihenfolge der Annotation-Processors ist verbindlich: Lombok → MapStruct → cdms-generator. Lombok erzeugt die Accessoren, auf die MapStruct aufsetzt; der CDMS-Generator kommt zuletzt.

KlasseZweck
{Model}EntityJPA-Entity mit @Table, @Column, Beziehungen
{Model}DtoAntwortmodell
{Model}CreatePayload / {Model}UpdatePayloadEingabemodelle
{Model}Payload2DtoMapperPayload → DTO
{Model}Entity2DtoMapperEntity → DTO
{Model}AbstractDto2EntityMapper / {Model}Dto2EntityMapperDTO → Entity
{Model}Map2AbstractEntityMapper / {Model}Map2EntityMapperMap<String,Object> → Entity (für PATCH)
{Model}MetaServiceFeldmetadaten, Regeln, Rollen
{Model}MapperServicezentraler Mapping-Einstieg
{Model}ApiREST-Controller mit den konfigurierten Endpunkten
{Model}SystemSystem-Layer (Rekursion, Hooks, Validierung)
{Model}DatabasePersistenz-Layer
{Model}AuthorizationLayerRollenprüfung
{Model}AttributeFilterattributbasierter Datenfilter
{Model}TupleMapperServiceTuple-Projektion für Abfragen
{Model}ApiHubRouter-Controller bei abstrakten Modellen
{Model}ApiSingleton / {Model}SystemSingletonbei @Singleton
KlasseZweck
com.codamai.cdms.EntityRegistryServiceordnet alle Entities den Gruppen System/Tenant/User zu
com.codamai.cdms.RoleRegistryServicesammelt alle Rollen aus den Endpunkt-Konfigurationen
com.codamai.cdms.config.JpaNativeHintsGraalVM-Hints für die Entity-Klassen
com.codamai.cdms.config.JacksonNativeHintsGraalVM-Hints für DTOs und Payloads

Start (Spring-Boot-Hauptklasse), OpenApiConfiguration, NativeHintsConfiguration. Diese Dateien landen in src/main/java und werden nie überschrieben – sie dürfen frei angepasst werden.

Aus den im Modell konfigurierten Endpunkt-Typen leitet der Generator ab, welche Methoden entstehen:

Endpoint im Modellaktiviert
CreateEndpointcreate
UpdateEndpointupdate und patch
ReadEndpointread und query
DeleteEndpointdelete
SearchEndpointsearch

Ohne Endpunkt-Konfiguration werden alle Endpunkte aktiviert.

Der Generator erzeugt nicht nur Java-Klassen, er hält auch die Abhängigkeiten der Anwendung aktuell. Dazu markiert er in der pom.xml zwei Bereiche:

<!-- cdms-managed:dependencies:start -->
<!-- cdms-managed:dependencies:end -->

Was zwischen den Markern steht, gehört dem Generator und wird bei jedem Lauf neu geschrieben. Alles außerhalb bleibt unangetastet – selbst hinzugefügte Abhängigkeiten, eigene Plugins und eigene Properties überstehen den Lauf.

Welche Abhängigkeiten das sind, ergibt sich aus system.yaml: der Datenbanktreiber aus database, das Speicher-Backend aus storage, die Authentifizierung aus authentication, dazu Envers, sobald ein Modell auditiert wird.

Eine abgewählte Abhängigkeit wird entfernt, nicht stehen gelassen. Wechselt ein System von MySQL auf PostgreSQL, verschwindet der MySQL-Treiber; wird ein Artefakt umbenannt, verschwindet der alte Name. Ohne das bliebe die alte Koordinate als vermeintlich handgepflegte Abhängigkeit liegen – und zwar ohne Version, weil der verwaltete Block seine Versionen vom Parent-POM bezieht. Genau diese Form kann Maven nicht lesen.

Eine Grenze hat das: Ist die pom.xml bereits unlesbar, kommt der Generator nicht mehr zum Zug – Maven bricht vor dem Build ab. Wird ein vom Parent verwaltetes Artefakt umbenannt, bleibt die alte Koordinate deshalb besser eine Release lang im dependencyManagement stehen; dann räumt der nächste Lauf sie selbst weg.

Die POM-Pflege hängt nicht am Netz: Sie arbeitet aus dem Cache und läuft auch im Offline-Modus. Abschalten lässt sie sich mit CODEGEN_POM_GENERATE=false.

Priorität absteigend: Umgebungsvariable → JVM-Property → cdms-generator.properties → Standardwert.

Variable / PropertyBedeutung
CODEGEN_KEYCLOAK_URL / cdms.generator.keycloakUrlKeycloak-Basis-URL (Pflicht)
CODEGEN_KEYCLOAK_REALM / …keycloakRealmRealm, Standard master
CODEGEN_CLIENT_ID / …clientIdOAuth2-Client des Generators (Pflicht)
CODEGEN_CLIENT_SECRET / …clientSecretSecret (Pflicht, nie ins Repo)
CODEGEN_CDMS_URL / …cdmsUrlBasis-URL der CDMS-API
CODEGEN_SYSTEM_ID / …systemIdUUID des zu generierenden Systems (Pflicht)
CODEGEN_CACHE_DIR / …cacheDirCache-Verzeichnis, Standard target/cache
CODEGEN_OFFLINE / …offlinetrue = kein Netzzugriff, vorhandenen Cache nutzen

Compiler-Argumente am maven-compiler-plugin:

ArgumentBedeutung
-Acdms.generator.cacheDirPfad zum YAML-Cache
-Acdms.generator.basePackageBasis-Package der generierten Klassen

Der generierte Code wird bei jedem Build neu erzeugt. Fachlogik gehört in Hooks und eigene Klassen unter src/main/java. Wer generierten Code editiert, verliert die Änderung beim nächsten Lauf.