DomainTemplate CRUD Solution

One business object, implemented from PostgreSQL to reusable clients and management console.

Purpose

  • Demonstrate a complete Spring Boot CRUD feature.
  • Keep the public object separate from JPA persistence.
  • Share one HTTP contract across Java, TypeScript, and Dart.
  • Include a practical React console and bulk data workflows.

Runtime

  • Spring Boot API under /api/v1/domaintemplate.
  • PostgreSQL table domain_templates through Spring Data JPA.
  • Java, TypeScript, and Dart clients.
  • React, Vite, and MUI management console.
  • MkDocs documentation and Marp presentation in the same repo.

Public Contract

Field Rule
id Server-generated Long
code Required, unique, immutable string
label Required string
description Nullable string
Dates Server-owned Instant values

DomainTemplate

{
  "id": 42,
  "code": "CUSTOMER",
  "label": "Customer",
  "description": "Customer master data",
  "createdDate": "2026-08-30T17:00:00Z",
  "lastModifiedDate": "2026-08-30T17:05:00Z"
}

API

Method Path
CRUD /api/v1/domaintemplate[/{id}]
POST /api/v1/domaintemplate/seed
POST /api/v1/domaintemplate/import.{json,csv}
GET /api/v1/domaintemplate/export.{json,csv}

Seed and import upsert by code and ignore imported IDs and dates.

Model Boundary

  • DomainTemplate: immutable public business object.
  • DomainTemplateEntity: internal mutable JPA model.
  • domain_templates: PostgreSQL persistence table.
  • The service maps between public and persistence models.

Demo Database

ddl-auto: update initializes the current schema but does not drop the obsolete domain_records table.

docker compose -f docker/compose.yml down --volumes
make docker-up

Resetting the demo volume removes all stored data.

Deploy Quickly

make docker-up

Take Away

Presenter note: Start by framing the demo as a complete, reusable CRUD pattern: one domain object, one contract, several clients, and a working console.

Presenter note: This is a reference implementation for a real CRUD feature: small enough to explain, complete enough to show how the stack fits together.

Presenter note: Walk through the runtime stack from API to database, then to clients and console. Emphasize this is not just backend-only work.

Presenter note: Explain the contract first. The important design decision is that the public model is stable and intentionally different from the database entity.

Presenter note: Use this example to show the actual JSON response and call out the immutable code value and timestamp semantics.

Presenter note: This is the main API surface. Highlight that seed and import are operational shortcuts, while the CRUD endpoints expose the standard model lifecycle.

Presenter note: Reinforce the architectural boundary: public domain model vs persistence model. This keeps the API honest and prevents leaking JPA details.

Presenter note: Mention the demo database setup and the known caveat that the old table is not auto-dropped, so a full volume reset is the cleanest way to start fresh.

Presenter note: End on the operational path: start the stack, open API, console, docs, and show that the repo is designed for quick local validation.

Presenter note: The container serves the interactive Bespoke deck plus the exported PDF and PPTX built at image build time.