Skip to main content

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

PathRole
lumie-backend/AGENTS.mdBackend repo rules and commands
lumie-backend/build.gradle.ktsShared Java, test, Spotless, Error Prone, JaCoCo, and integration-test wiring
lumie-backend/app/build.gradle.ktsRuntime dependencies and snapshotOpenApi task
lumie-backend/settings.gradle.ktsCurrent module list
lumie-backend/app/src/main/resources/application*.ymlRuntime and profile-specific configuration

Project Layout

PathPurpose
app/Spring Boot entrypoint and shared runtime configuration
libs/commonTenant context, base entities, exceptions, idempotency, logging, auth helpers
libs/internal-apiCross-module interfaces and events
libs/messagingShared 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:

  1. run the shared dev environment through Tilt
  2. keep the frontend local with HMR
  3. 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
CommandUse it forNotes
./gradlew buildFull compile plus default verificationIncludes check, which depends on spotlessCheck and license checks
./gradlew testFast default test passExcludes @Tag("integration") tests
./gradlew integrationTestTestContainers-backed integration testsRequires Docker access
./gradlew -Pintegration testSingle combined run of default plus integration testsSlower, but useful before major backend merges
./gradlew :modules:student:testModule-scoped verificationReplace student with the module you touched
./gradlew :app:testShared runtime wiring and OpenAPI snapshot testsGood for security, RLS, data-source, and migration work
./gradlew bootRunStart the backend locallyExpects PostgreSQL, RabbitMQ, Redis, and MinIO to be reachable
./gradlew snapshotOpenApiPull live /v3/api-docs into lumie-frontend/openapi.jsonReads 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 test excludes @Tag("integration")
  • integrationTest includes only @Tag("integration")
  • spotlessCheck is part of check
  • 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-api for synchronous module-to-module access.
  • Publish Spring Modulith events for after-commit cross-module follow-up.
  • Keep external HTTP outside long @Transactional boundaries.
  • 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:

  1. reaches into the running backend pod with kubectl exec
  2. downloads http://localhost:8080/v3/api-docs
  3. 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.
  • snapshotOpenApi assumes a running backend pod and working kubectl context; it does not boot the backend for you.
  • bootRun is available, but the default dev topology is still cluster-backed because several backend paths expect live infrastructure services.