Architecture
flowchart LR
Console[React Vite management console] --> ReactClient[React client library]
ReactClient --> Api[Spring Boot API /api/v1/domaintemplate]
JavaClient[Java client library] --> Api
DartClient[Dart client library] --> Api
Api --> Service[DomainTemplateService]
Service --> Repository[DomainTemplateRepository]
Repository --> Database[(PostgreSQL domain_templates)]
Docs[MkDocs] -. documents .-> Api
Slides[Marp presentation] -. explains .-> Docs
The repository demonstrates one vertical CRUD feature. HTTP controllers validate transport requests and delegate business operations to DomainTemplateService. The service owns timestamps and upsert behavior, while DomainTemplateRepository isolates Spring Data JPA access. The Java, TypeScript, and Dart clients depend on the public HTTP contract, not on persistence classes.
Public Object and Persistence Entity
DomainTemplate is the public business object returned by controllers and represented by each client. It is an immutable Java record with id, code, label, description, createdDate, and lastModifiedDate. This is the model API consumers should understand.
DomainTemplateEntity is the internal mutable JPA representation. It maps to the PostgreSQL table domain_templates and exists to satisfy persistence concerns such as a protected no-argument constructor, generated identity, column constraints, and dirty tracking. Controllers never expose the JPA entity.
The service maps between these types. This boundary keeps the public contract stable when persistence details change and prevents JPA behavior from leaking into client code.
Invariants and Ownership
| Concern | Owner | Behavior |
|---|---|---|
| Persistent identity | Server and database | id is a generated Long. |
| Business identity | Service and database | code is required, unique, and immutable. |
| Mutable business data | Client request | label is required; description may be null. |
| Audit timestamps | Service | Both dates are Instant values assigned by the server. |
| Bulk reconciliation | Service | Seed and import upsert by code and ignore imported IDs and dates. |
Schema Evolution
Hibernate is configured with spring.jpa.hibernate.ddl-auto: update for this runnable application. It can add or adjust the domain_templates schema, but it does not remove tables that are no longer mapped. In particular, an existing demo volume may retain the obsolete domain_records table. The application does not use that table.
This convenience setting is not a migration strategy for production. Use versioned database migrations in a real service. For the demo, reset the Compose volume when a clean schema is required, as described in the deployment guide.