REST API Conventions
1. Purpose
The one page to read before adding or changing a REST endpoint in admin-service. It states each rule briefly and links to the page that owns the detail. It exists because these conventions were, until now, implicit — and an endpoint that quietly diverged (GET /api/race-numbers/stock returning a Spring Page instead of a bare array) shipped a broken stock list and an empty UNFIT report to stage before anyone noticed.
This is a hub, not a re-explanation: where a rule has an authoritative page it links, rather than restating it.
2. Collections and pagination
-
A list endpoint returns a bare JSON array of the DTO as its body; the handler signature is
ResponseEntity<List<DTO>>. Pagination metadata travels in headers —X-Total-CountandLink— viaPaginationUtil.generatePaginationHttpHeaders. -
Never return
Page<T>, or any envelope object, as the response body. This is the ruling and rationale of ADR-0013, enforced by an ArchUnit test. -
Reference implementation:
RaceNumberResource.getAllRaceNumbers. Anti-pattern:RaceNumberResourceEx.stockView(returns aPage— under remediation).
3. Filtering, sorting, paging
-
Filters use the JHipster criteria grammar —
?field.equals=/.in=/.contains=/.greaterThanOrEqual=/.lessThanOrEqual=/.specified=— pluspage/size/sort=field,dir. -
Each criterion resolves through a JPA
Specificationin a query service. See Filterable List Pattern (the URL contract) and Query Services (where resolution lives). -
Expose only the filters you intend. Each criterion is a queryable — and potentially unindexed — surface; do not blanket-expose every entity field.
4. Enums on the wire
-
Responses carry the constant name; the database column and an accepted filter value carry the short code; filter values resolve strictly — accept the code or the name, reject anything else with
400, never a silent default. Full rules and the resolver pattern: Enum Modelling. -
Because responses serialise the name, renaming a constant is a breaking wire change for consumers, even though it is database-safe.
5. HTTP status contracts
-
Declare every reachable non-2xx response with
@ApiResponses, and restate the success code — Javadoc does not reach the published spec, and@ApiResponsesreplaces springdoc’s default rather than merging with it. See OpenAPI Contract Flow → Response Contracts.
6. DTOs and errors
-
Endpoints expose MapStruct DTOs, never entities; enums cross as identity copies (see Enum Modelling).
-
Errors are RFC-7807
problem+jsonrendered byExceptionTranslator. RaiseServiceBadRequestExceptionfrom the service layer (not the web-layerBadRequestAlertException, whichArchTestforbids the service package from importing) for a structured400.
7. Related
-
ADR-0013 — the collection-contract decision and its alternatives.
-
JHipster — Keep & Drop · Filterable List Pattern · Enum Modelling · OpenAPI Contract Flow.