Development
This page is a backend-focused how-to reference. It covers how the project is
laid out, which Gradle tasks are meaningful, and what "normal" verification
looks like for the current modular-monolith runtime.
Source Paths
| Path | Role |
|---|---|
lumie-backend/AGENTS.md | Backend repo rules and commands |
lumie-backend/build.gradle.kts | Shared Java, test, Spotless, Error Prone, JaCoCo, and integration-test wiring |
lumie-backend/app/build.gradle.kts | Runtime dependencies and snapshotOpenApi task |
lumie-backend/settings.gradle.kts | Current module list |
lumie-backend/app/src/main/resources/application*.yml | Runtime and profile-specific configuration |
Project Layout
| Path | Purpose |
|---|---|
app/ | Spring Boot entrypoint and shared runtime configuration |
libs/common | Tenant context, base entities, exceptions, idempotency, logging, auth helpers |
libs/internal-api | Cross-module interfaces and events |
libs/messaging | Shared AMQP constants |
modules/* | Product modules loaded into the monolith |
Module code normally follows the boundary shape documented in Architecture.
Normal Local Workflow
The backend can run with bootRun, but the usual team workflow is:
- run the shared dev environment through Tilt
- keep the frontend local with HMR
- use the cluster-backed backend, workers, PostgreSQL, RabbitMQ, Redis, and MinIO
That matches the workspace guidance in the root AGENTS.md: frontend local,
backend and stateful services in the dev cluster.
Use bootRun when you intentionally want a local JVM and already have the
required dependencies available.
Common Commands
cd /Users/bluemayne/Projects/Lumie/lumie-backend
| Command | Use it for | Notes |
|---|---|---|
./gradlew build | Full compile plus default verification | Includes check, which depends on spotlessCheck and license checks |
./gradlew test | Fast default test pass | Excludes @Tag("integration") tests |
./gradlew integrationTest | TestContainers-backed integration tests | Requires Docker access |
./gradlew -Pintegration test | Single combined run of default plus integration tests | Slower, but useful before major backend merges |
./gradlew :modules:student:test | Module-scoped verification | Replace student with the module you touched |
./gradlew :app:test | Shared runtime wiring and OpenAPI snapshot tests | Good for security, RLS, data-source, and migration work |
./gradlew bootRun | Start the backend locally | Expects PostgreSQL, RabbitMQ, Redis, and MinIO to be reachable |
./gradlew snapshotOpenApi | Pull live /v3/api-docs into lumie-frontend/openapi.json | Reads from the running dev backend pod via kubectl exec |
What The Build Is Actually Enforcing
From build.gradle.kts and app/build.gradle.kts:
- Java toolchain: 21
- Default
testexcludes@Tag("integration") integrationTestincludes only@Tag("integration")spotlessCheckis part ofcheck- Error Prone runs in warning mode, not fail-the-build mode
- JaCoCo reports are generated after tests, but coverage verification is not yet
wired into
check - license compliance is part of the root
check
Backend-Specific Conventions To Follow
- Use
libs/internal-apifor synchronous module-to-module access. - Publish Spring Modulith events for after-commit cross-module follow-up.
- Keep external HTTP outside long
@Transactionalboundaries. - Use records for DTOs and
@Transactional(readOnly = true)on query services. - Remember that tenant-safe reads and writes require both a tenant ID in context and an actual transaction so RLS can bind.
OpenAPI Contract Workflow
The backend exposes:
/v3/api-docs/swagger-ui.html
./gradlew snapshotOpenApi is the documented contract handoff to the frontend.
The task:
- reaches into the running backend pod with
kubectl exec - downloads
http://localhost:8080/v3/api-docs - writes the result to
../lumie-frontend/openapi.json
That file is the frontend codegen source of truth. For the shared response, error, pagination, idempotency, and long-job envelopes that keep the exported spec stable for orval, see API Contract.
Verification Playbooks By Change Type
| If you changed... | Minimum useful verification |
|---|---|
| controller, security, filters | ./gradlew :app:test plus the affected module test task |
| RLS, migrations, or data sources | ./gradlew integrationTest |
| one module's application or domain logic | ./gradlew :modules:<name>:test |
| queue, outbox, or worker integration code | ./gradlew :modules:exam:test and usually ./gradlew :app:test |
shared library code in libs/common | ./gradlew :libs:common:test |
Common Development Constraints
- TestContainers-backed integration tests need Docker access. They are
intentionally excluded from default
test. snapshotOpenApiassumes a running backend pod and workingkubectlcontext; it does not boot the backend for you.bootRunis available, but the default dev topology is still cluster-backed because several backend paths expect live infrastructure services.