This document is the canonical development guide for the Grimmory backend. It covers the local command
surface, setup expectations, build and test workflows, and backend-specific conventions.
For repository-wide contribution policy, branch strategy, PR requirements, and release semantics, start with ../CONTRIBUTING.md. For repo-level environment setup and Docker workflows, see ../DEVELOPMENT.md.
The backend project is the Spring Boot backend for Grimmory. It owns the HTTP API, database
migrations, background processing, authentication, and the packaged runtime jar used by the production
container.
- Java 25
- Spring Boot 4
- Gradle Wrapper
- Spring Data JPA + Flyway
- MariaDB in production, H2 for selected tests
- JUnit 5, Mockito, AssertJ, JaCoCo
Use Justfile when possible:
just # List backend recipes
just run # Start the backend with the dev profile
just test # Run backend tests
just coverage # Generate JaCoCo coverage output
just check # Run the Gradle check lifecycle
just build # Build the backend jar
just tasks # Show available Gradle tasksFrom the repository root, the same recipes are available through the api namespace:
just api run
just api test
just api coverage
just api checkThe backend expects a MariaDB instance plus environment or local configuration for your database and storage paths. The common backend loop is:
cd backend
just runIf you need a different Spring profile:
just run profile=localUse the repo-level guide in ../DEVELOPMENT.md for the full Docker stack, MariaDB setup, and cross-project local workflows.
just build
just test
just coverage
just checkThe frontend bundle is consumed during packaging when the UI build output exists. For normal backend-only development and test runs, frontend resources are optional.
application.yamlbindsapp.api-docs.enabledtoAPI_DOCS_ENABLED(defaultfalse).application.yamlbindsspringdoc.api-docs.enabledtoapp.api-docs.enabled.- For runtime or container profiles, set
API_DOCS_ENABLED=trueto expose:/api/openapi.json/api/docs
- To export a release-ready spec without running the full container stack, use:
just openapi-export- The production container image is built from the repository root
Dockerfile. - That Docker build compiles the UI first and passes the resolved frontend dist path into the backend build.
- The backend jar remains the packaged application artifact for the current all-in-one runtime model.
- Use Spring Data JPA repository methods or JPQL. Do not introduce native queries unless a maintainer has explicitly approved them.
- Prefer constructor injection via Lombok
@AllArgsConstructor. Do not add@Autowired. - Use Lombok
@Slf4jfor logging. Do not instantiate loggers manually. - Throw API-facing errors via
ApiErrorhelpers instead of rawRuntimeException. - Entities use the
*Entitysuffix. DTOs and API models do not. - Use MapStruct for entity-to-DTO mapping instead of hand-written mapping code.
- Security checks should use the existing project patterns such as
@PreAuthorize("@securityUtil.isAdmin()")or@CheckBookAccess. - Use modern Java language features where they clarify the code.
- Keep imports explicit. Do not inline fully-qualified class names.
- Flyway migrations live in
src/main/resources/db/migration/. - Name migrations
V<number>__<Description>.sql. - Never modify a released migration. Add a new migration instead.
- Prefer idempotent guards such as
IF EXISTSandIF NOT EXISTSwhen the SQL dialect allows them.
- Unit tests should normally use JUnit 6 + Mockito + AssertJ.
- Use
@ExtendWith(MockitoExtension.class)for unit tests. - Use
@SpringBootTestonly when you need a real Spring integration context. - Keep tests behavior-oriented. Avoid shallow tests that only exercise getters, setters, or mocks without asserting meaningful outcomes.
Run the backend checks locally before sending a PR:
just test
just checkIf your change affects migrations, persistence, or API behavior, also run the full stack locally and verify the behavior manually.