CodamAIDocs
Topicdone

The project scaffold

What a new project gets the first time (POM, main class, configuration) and which branches exist, for example CIAS embedded or removed.

Variants
Authentication OIDC or NONECIAS EMBEDDED / REMOTE / NONEDatabase MYSQL / MARIADBStorage FILESYSTEM or NONEMonitoring ACTUATOR or NONEAuditing (derived)first download, later build

What this is about

You do not start a new CDMS project with an empty folder. The hub gives you a project scaffold: a ZIP with a POM, a main class, configuration and the current model. You unpack it, build once, and the application runs.

What exactly is in the scaffold depends on a few settings of the system in the hub: Which database does it use? Does it need login? Does CIAS run in the same process? Each setting is a branch that adds dependencies, configuration and sometimes classes.

How you get the scaffold

  1. 1
    Developer→Hub
    opens the system in the hub and clicks Project scaffold
  2. 2
    Hub
    reads the settings of the system and the model
  3. 3
    Hub→Developer
    delivers <id>-project.zip
    Behind this is GET /api/rest/cms/system/{id}/scaffold. So you can also fetch the scaffold with a script.
  4. 4
    Developer
    unpacks it, enters the client secret in cdms-generator.properties, creates .env
  5. 5
    Build
    mvn clean compile: fetches the metadata, maintains the POM, generates the code
    Result: A project that runs

What is in the ZIP

katalog/
├── pom.xml                         ← parent cdms-app-parent, dependencies per branch
├── README.md                       ← building, starting, all environment variables
├── cdms-generator.properties       ← access to the hub for the build (secret empty)
├── .env.example                    ← runtime variables: database, tenant mode, CIAS …
├── .gitignore
├── .cache/                         ← the model as YAML, so the first build works offline
│   ├── system.yaml
│   └── models.yaml …
└── src/
    ├── main/java/com/codamai/shop/katalog/
    │   ├── Start.java              ← Spring Boot main class
    │   └── config/                 ← only with CIAS EMBEDDED: three wiring classes
    ├── main/resources/application.yaml
    └── test/java/…/TenantContextArchitectureTest.java   ← only with login (OIDC)
Filewhat for
pom.xmlThe parent is cdms-app-parent. It brings the whole build: fetching metadata, code generator, Spring Boot packaging, native image. Your POM only contains coordinates, a few properties and the dependencies.
Start.java@SpringBootApplication for the package com.codamai. Without it there would be no source file, and without a source file no annotation processors run, so no generator either.
application.yamlyour configuration. Database, tenant mode and identity provider are not here on purpose. They come from the environment.
.env.exampleTemplate for the environment variables. Always included: CODAMAI_PERSISTENCE_TENANT_MODE=SINGLE and the database access settings CODAMAI_PERSISTENCE_DATABASE_*.
cdms-generator.propertiesSystem ID, hub address, Keycloak address, realm, client ID and cacheDir=.cache. You enter the clientSecret yourself. The file is listed in .gitignore.
.cache/the model at the time of the download, see Code generation in the build

The hub derives the Maven coordinates from the names. The project “Shop” and the system “Katalog” become groupId com.codamai.shop, artifactId katalog and the base package com.codamai.shop.katalog.

The branches

The settings are on the system in the hub. The build reads them later from .cache/system.yaml. Maven or Spring properties do not switch the branches.

flowchart TD
    A{"authentication"} -- "NONE" --> N["no login<br/>CIAS is always NONE"]
    A -- "OIDC" --> O["+ cias-authentication<br/>+ architecture test<br/>+ CIAS_ISSUER, CIAS_CLIENT …"]
    O --> C{"cias"}
    C -- "REMOTE" --> R["+ cias-tenancy-client<br/>CIAS runs as a separate service"]
    C -- "EMBEDDED" --> E["+ cias-tenancy, cias-user,<br/>cias-authorization, cias-iam-keycloak<br/>+ block codamai.cias<br/>+ 3 classes under config/"]
    C -- "NONE" --> X["no CIAS tenant service"]
    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["no files"]
    M{"monitoring"} -- "ACTUATOR" --> M1["+ Prometheus, AOP<br/>+ metrics and probes on 8081"]
    M -- "NONE" --> M0["basic Actuator setup only<br/>on 8081"]
    U{"a model audited?"} -- "yes" --> U1["+ hibernate-envers"]
What each branch changes in the scaffold

When: authentication: OIDC or NONE

OIDC: The POM gets cias-authentication (checks every token) and, for tests, cias-test-support. .env.example contains CIAS_ISSUER (the issuer as the token carries it), CIAS_CLIENT and CIAS_CLIENT_SECRET, plus CIAS_BACKCHANNEL_URL commented out. On top of that you get the test TenantContextArchitectureTest. It checks that the tenant only comes from the tenant gate. NONE: none of this. Without login there is no CIAS either.

Result: With OIDC every request is logged in, see Token check

When: cias: EMBEDDED (only with OIDC)

CIAS runs in the same process as CDMS. The POM gets cias-tenancy, cias-user, cias-authorization and cias-iam-keycloak. application.yaml gets a block codamai.cias (tenant management on, tenants are looked up locally). Under config/ there are three classes that wire up CIAS: CiasEmbeddedConfiguration, CiasIdentityConfiguration, CiasRepositoryTransactionsPostProcessor. User and permission management are prepared, and you turn them on with CIAS_USER and CIAS_AUTHORIZATION.

Result: A single unit, see Embedded

When: cias: REMOTE (only with OIDC, default)

CIAS runs as a separate service. The POM only gets cias-tenancy-client. It asks CIAS for the tenants. .env.example contains CODAMAI_CIAS_TENANCY_CLIENT_BASE_URL, the address of the CIAS service.

Result: Two services, see Standalone

When: cias: NONE

No CIAS module in the scaffold. The application checks tokens but does not ask a tenant service.

When: database: MYSQL or MARIADB

The POM gets the matching JDBC driver. .env.example gets CODAMAI_PERSISTENCE_DATABASE_DRIVER and an example URL like jdbc:mysql://localhost:3306/{tenant}. At runtime CDMS replaces {tenant} with the tenant, see Which database?

When: storage: FILESYSTEM or NONE

FILESYSTEM: The POM gets cdms-localfs-storage, and application.yaml gets the storage location codamai.cdms.persistence.file.basePath (default /files/, can be changed with CODAMAI_CDMS_PERSISTENCE_FILE_BASE_PATH). NONE: no file storage.

Result: See Storage backends

When: monitoring: ACTUATOR or NONE

Every application has the Spring Boot Actuator, always on the separate management port 8081, which is not reachable from outside. ACTUATOR adds more: micrometer-registry-prometheus and spring-boot-starter-aop in the POM, and in application.yaml the endpoints health, info, metrics, prometheus and health probes for Kubernetes.

When: at least one model is audited

There is no switch for this. As soon as a model is audited in the hub, hibernate-envers is added to the POM.

Result: See What is audited

Whether the application serves one tenant or many is not a branch of the scaffold. CODAMAI_PERSISTENCE_TENANT_MODE (SINGLE or MULTI) decides this at runtime, see Single- or multi-tenant.

An example

Scaffold for OIDC, CIAS REMOTE, MySQL, files, Actuator, one model audited
pom.xml (shortened)
<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 -->
  … core: 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 (shortened)
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

Created once, then yours

What happens to the files when you build later or download the scaffold again?

Who writes which file after the first time?
FileWhat happens on every build
pom.xml: parent, managed properties, section between the cdms-managed markersis rewritten from the hub
pom.xml: coordinates, your own dependencies, plugins, your own propertiesstays as it is
Start.java, OpenApiConfiguration, NativeHintsConfigurationthe generator creates them if they are missing, otherwise never touched
application.yaml, .env.example, CIAS classes under config/never touched
generated code in target/generated-sources/new on every build

Two consequences:

  • Changing a branch later (for example storage to FILESYSTEM) affects the POM on the next build: the dependency is added, and deselected ones are removed. You add the matching configuration in application.yaml and .env yourself. The README of a fresh scaffold shows you what has to go there.
  • A new download is a new ZIP. Nothing is merged with your project. Take from it what you need.

You turn off POM maintenance with CODEGEN_POM_GENERATE=false.

Pitfalls

Sources in the code and the knowledge base
  • 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 (profile 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
Search