AGENTS.spring.md — Spring Boot (Java or Kotlin)
Additive to ../AGENTS.md plus AGENTS.java.md or AGENTS.kotlin.md.
Build and check
./gradlew check # or: ./mvnw -B -ntp verify
./gradlew bootRun # only if you touched config or wiring: it must start
Spring rules
- Constructor injection only. No field
@Autowired, no setter injection. In Kotlin, primary-constructorvals. - Controllers are thin: validate (
@Validon the request DTO), call one service, map the result. No repository calls or business logic in a@RestController. - Never return JPA entities from a controller. Map to response DTOs (records or
data classes). The DTO is the wire contract: name JSON fields explicitly
(
@JsonProperty/@SerialName) on public APIs, so a rename is not a break. @Transactionalgoes on public service methods. Not on controllers, and never on private methods (the proxy ignores them).- Configuration binds to
@ConfigurationPropertiesrecords, not scattered@Value. Secrets come from the environment or a secret manager, never a committedapplication*.yml. - Schema changes are Flyway or Liquibase migrations. No
ddl-auto=updateoutside local. A shipped migration is never edited; add a new one. Migrations are Kitchen. - One
@RestControllerAdvicemaps exceptions toProblemDetail. No try/catch returning 500 inside controllers. - Security config (
SecurityFilterChain, token handling) is Kitchen. Keep it in a pathrooms.config.jsmaps to Kitchen. - Actuator exposes only
healthandinfopublicly. - Kotlin: use the
kotlin-springandkotlin-jpacompiler plugins. Do not call blocking JDBC from asuspendhandler withoutDispatchers.IO. - One HTTP client (base rule). New code uses the repo’s choice,
RestClientorWebClient, not a newRestTemplate.
Testing
- Slice tests (
@WebMvcTest,@DataJpaTest) for one layer.@SpringBootTestfor a few end-to-end paths, not every test. - Size the test JVM heap before blaming slow Spring context loads.
Anti-patterns seen in this repo
- Lombok
@Dataon JPA entities: breaksequals/hashCodeand lazy loading. - A
@Servicethat only forwards to a repository.