Spring Boot Course · Reference

Glossary

The vocabulary of Spring Boot, grouped by the lesson that introduces each term. Terms here are used consistently across every lesson. Bookmark this; it grows over time.

Lesson 1 · Your First Running Endpoint

Spring Framework
The large, foundational Java framework Spring Boot is built on. Its core idea is inversion of control: you describe the objects your app needs and Spring creates and wires them together for you.
Spring Boot
An opinionated layer on top of Spring that removes boilerplate. It gives you sensible defaults, an embedded web server, and auto-configuration so you can run a real app with almost no manual setup.
Dependency Injection (DI)
The pattern where an object receives the things it depends on from the outside (Spring supplies them) instead of creating them itself. Makes code loosely coupled and easy to test.
Bean
Any object that Spring creates, configures, and manages for you inside its application context. Your controllers, services, and repositories all become beans.
Application Context
Spring's container — the registry that holds all the beans and knows how to wire them together.
Auto-configuration
Spring Boot inspects the libraries (starters) on your classpath and automatically configures sensible beans for them. Add the web starter → it configures a web server and JSON handling, no XML required.
Starter
A curated bundle of dependencies for one job, named spring-boot-starter-*. E.g. spring-boot-starter-webmvc (called spring-boot-starter-web before Spring Boot 4) pulls in everything needed to build a web/REST app, at compatible versions.
SDKMAN!
A version manager for the JVM ecosystem (Java, and tools like the Spring Boot CLI) on macOS/Linux. Install a JDK with sdk install java 21-tem and switch versions per project with sdk use — no manual PATH/JAVA_HOME editing.
JDK (Java Development Kit)
The toolkit that compiles and runs Java code (compiler + runtime + libraries). Spring Boot needs one installed; we get it via SDKMAN.
Spring Boot CLI
A command-line tool (installable via sdk install springboot) whose spring init command generates a project from the terminal — the CLI front-end to Spring Initializr.
Maven
A build tool for Java that compiles your code, runs tests, manages dependencies, and packages the app — all driven by a pom.xml file. (Gradle is the common alternative.)
Maven Wrapper (mvnw)
A script committed inside the project (mvnw / mvnw.cmd) that downloads and runs the exact Maven version the project needs, so contributors don't have to install Maven themselves. Run goals with it, e.g. ./mvnw spring-boot:run.
Spring Initializr
The official project generator at start.spring.io. You pick your build tool, language, Spring Boot version, and starters; it hands you a ready-to-run project.
@SpringBootApplication
The single annotation on your main class that switches on auto-configuration, component scanning, and configuration. The entry point of every Spring Boot app.
@RestController
Marks a class as a web controller whose method return values are written directly to the HTTP response body (as JSON), rather than treated as view names.
@GetMapping (and friends)
Maps an HTTP request to a method. @GetMapping("/books") handles GET /books; siblings are @PostMapping, @PutMapping, @DeleteMapping.
Embedded server
Spring Boot ships a web server (Tomcat by default) inside your application JAR. You run a plain Java program and it serves HTTP — no separate server to install or deploy to.

Lesson 2 · Returning JSON & Modelling a Book

JSON
JavaScript Object Notation — a compact, language-neutral text format for structured data. The default body format for REST APIs; what your endpoints return.
Resource
The "noun" a REST API exposes and lets clients act on — e.g. a book at /api/books. Endpoints are organised around resources.
Package-by-feature
Organising code so all classes for one feature live in one package (com.example.library.book holds the book's controller, service, repository, model). The alternative is package-by-layer (separate controller/service/… packages). Either way, keep everything under the main class's package so component scanning finds it.
UUID
A 128-bit globally-unique identifier (e.g. 11111111-1111-1111-1111-111111111111). We use it as the Book id: it can be generated by the app, isn't sequentially guessable, and stays unique across systems. The common alternative is an auto-incremented numeric Long. Jackson serialises a UUID as a JSON string.
Serialization / Deserialization
Serialization turns a Java object into JSON (on the way out); deserialization turns incoming JSON back into a Java object (on the way in).
Jackson
The JSON library bundled by spring-boot-starter-webmvc. It reads an object's accessors to serialise it to JSON, and builds objects from incoming JSON. You rarely call it directly — Spring does.
HTTP message converter
The Spring MVC component that writes a method's return value to the response body (and reads request bodies into objects). The Jackson-backed converter is what produces your JSON and sets Content-Type: application/json.
Content negotiation
How Spring decides which format to send (e.g. JSON) based on the return type and what the client asks for, then picks the matching message converter.
@ResponseBody
Marks a return value as the HTTP response body itself (not a view name to render). It's folded into @RestController, which is why every method there returns data.
@RequestMapping
Maps requests to a controller or method. On a class it sets a base path prepended to every method's mapping; the HTTP-verb shortcuts (@GetMapping, etc.) are specialised forms of it.

Lesson 3 · Layered Architecture & Dependency Injection

Layered architecture
Organising an app as a thin stack of single-purpose layers, each talking only to the one below: controller (HTTP) → service (business logic) → repository (data). Keeps each concern isolated so a change in one layer barely touches the others.
Separation of concerns
The design principle behind the layers: each class does one job. The controller speaks HTTP, the service holds business logic, the repository handles data — none of them does another's work.
Service (@Service)
The business-logic layer, sitting between the controller and the data layer. @Service marks the class as a Spring-managed bean. The controller delegates the real work to it.
Stereotype annotation
An annotation that registers a class as a Spring bean via component scanning. @Component is the base; @Service, @Repository, and @Controller/@RestController are specialised forms that also document the class's architectural role.
Constructor injection
Supplying a class's dependencies through its constructor (Spring passes them in at startup). The recommended DI style: the field can be final, missing dependencies fail fast, the dependencies are explicit, and the class can be instantiated in a plain test without Spring. With a single constructor, no @Autowired is needed.
Inversion of Control (IoC)
The principle that the framework, not your code, is in charge of creating objects and wiring them together. Spring's container constructs your beans and supplies their collaborators; dependency injection is how it does so.
@Autowired
Marks a constructor, field, or setter for Spring to inject a dependency into. Redundant on a class's single constructor (Spring uses it automatically since 4.3) — needed only to pick among multiple constructors or for field/setter injection.

Lesson 4 · Full CRUD: POST, PUT, DELETE & Status Codes

CRUD
Create, Read, Update, Delete — the four basic operations on a resource. In REST they map to HTTP methods: POST (create), GET (read), PUT (update/replace), DELETE (delete).
@RequestBody
Binds a method parameter to the HTTP request body: Spring (via Jackson) deserializes the incoming JSON into that Java object. The inbound counterpart of the JSON serialization you saw in L2.
@PathVariable
Binds a placeholder in the URL template to a method parameter. With @GetMapping("/{id}"), @PathVariable UUID id captures the {id} segment and converts it to the declared type.
ResponseEntity
A wrapper that lets a controller method control the whole HTTP response — status code, headers, and body — instead of just the body. Use it when the status isn't always the default 200 OK (e.g. 201 Created, 204 No Content, 404 Not Found).
HTTP status code
The three-digit code that says how a request went: 2xx success (200 OK, 201 Created, 204 No Content), 4xx client error (400 Bad Request, 404 Not Found, 415 Unsupported Media Type), 5xx server error. Choosing the right one is part of designing a good API.
Location header
A response header carrying the URL of a resource. By convention a 201 Created response sets it to the newly created resource's address; ResponseEntity.created(uri) sets both the status and this header.
Idempotency
A property of an operation: performing it once or many times leaves the server in the same state. GET, PUT, and DELETE are idempotent; POST is not (each call creates another resource). A key reason create is POST and replace is PUT.

Lesson 5 · Persistence with Spring Data JPA

JPA (Jakarta Persistence API)
A specification — interfaces and annotations (@Entity, @Id, …) describing how Java objects map to database rows. It defines the contract; it doesn't run any SQL itself.
Hibernate
The most common implementation of JPA, and Spring Boot's default. It does the real work: generating SQL, mapping rows to objects, and tracking entity changes.
ORM (Object-Relational Mapping)
The technique of mapping objects in your code to rows in relational tables (and back), so you work with Java objects instead of hand-written SQL. Hibernate is an ORM.
Spring Data JPA
A Spring layer on top of Hibernate that eliminates repository boilerplate: you declare an interface extending JpaRepository and Spring Data generates the implementation at runtime.
@Entity
Marks a class as a persistent JPA entity — one mapped to a database table, with each instance a row. Entities are mutable classes (not records) with a no-arg constructor, because Hibernate needs to construct and populate them.
@Id
Marks the field that is the entity's primary key — the column that uniquely identifies each row. In this course it's a UUID.
Repository
The data-access layer (the bottom of the controller → service → repository stack). It hides how data is stored and retrieved behind a clean interface so the service doesn't care whether it's an in-memory map or a Postgres database.
JpaRepository
The Spring Data interface you extend to get a ready-made repository. JpaRepository<Book, UUID> supplies save, findById, findAll, deleteById, count, and more, with no implementation written by you.
Derived query method
A repository method whose name is parsed into a query: findByAuthor becomes WHERE author = ?. Keywords like Containing, IgnoreCase, GreaterThanEqual, and OrderBy…Desc compose into the SQL — no method body required.
PostgreSQL (Postgres)
A robust, open-source relational database widely used in production. Unlike an in-memory store it's a separate server process that keeps your data across restarts, and it has a native uuid column type that maps cleanly to the entity's UUID id.
Docker Compose
A tool that defines and runs containers from a YAML file (compose.yaml). Here it declares the Postgres container the app needs. With spring-boot-docker-compose on the classpath, Spring Boot starts that container on boot, reads its credentials, and auto-configures the datasource — no JDBC URL to write by hand.
ddl-auto
The Hibernate setting (spring.jpa.hibernate.ddl-auto) controlling how the schema is managed at startup: create-drop/update (dev convenience), or validate/none (production). We use validate — Hibernate only checks the entities match the schema; Liquibase owns the schema itself. Never let Hibernate rewrite a production schema.
Database migration
A versioned, ordered change to the database schema, applied automatically and tracked so it runs exactly once. Replacing implicit auto-DDL, migrations make schema changes explicit, reviewable, and replayable from an empty database — the production-grade way to evolve a schema.
Liquibase
A database-migration tool. Spring Boot auto-runs it on startup from a master changelog (default path db/changelog/db.changelog-master.yaml), applying any not-yet-run changesets. The common alternative is Flyway.
Changelog / changeset
A changelog is the ordered list of migrations; a changeset is one unit of change (e.g. "create the book table"), identified by id + author. Liquibase records applied changesets in a tracking table and never re-runs them — so an applied changeset is immutable: to change the schema you append a new one.
Lombok
A library that generates boilerplate (getters, constructors, equals/hashCode) from annotations at compile time. Safe on entities: @Getter, @Setter, @NoArgsConstructor, id-only @EqualsAndHashCode. Avoid on entities: @Data, all-fields @EqualsAndHashCode, and unguarded @ToString.
@RequestParam
Binds a query-string value (the part after ?, e.g. ?author=Bloch) to a method parameter. Use it for filtering, sorting, or paging a collection — as opposed to @PathVariable, which identifies a single resource in the path.
UUIDv7
A time-ordered UUID: its leading bits are a millisecond timestamp, so values sort by creation time. This gives the database index locality of an auto-increment key while keeping a UUID's global uniqueness and app-side generation. The older UUID.randomUUID() is v4 (fully random, poor index locality).

Lesson 6 · Relationships & DTOs

Expand / migrate / contract
The order a schema change with live data follows: expand (create the new tables or columns), migrate (copy the existing data into them, e.g. with an INSERT … SELECT in a sql change), contract (drop the old ones). Dropping first loses data on every environment the migration reaches — fine on a laptop, an incident in production. A migration copies what it finds; anything that needs a human decision is done afterwards through the API.
Entity relationship
A link between two entities mirroring a foreign key between their tables. The cardinalities are one-to-many / many-to-one (one publisher, many books), one-to-one, and many-to-many (a book has many authors, an author has many books — our case). A bidirectional relationship is navigable from both sides (author → books and book → author). A many-to-many needs a join table.
Foreign key (FK)
A column whose value references a primary key in another table, enforcing that the reference points to a real row. book_author.book_id is a foreign key into book.id, and book_author.author_id into author.id.
@ManyToMany
Maps a many-to-many association as a collection on the entity that declares it: Book.authors is Set<Author>. Needs a join table (@JoinTable) rather than a foreign-key column, and defaults to lazy fetching.
Join table
A table whose rows are pairs of foreign keys, one per link: book_author(book_id, author_id). Its composite primary key is the pair, so a link can't be recorded twice.
@JoinTable / @JoinColumn
@JoinTable names the join table and, through joinColumns and inverseJoinColumns, which column points back at this entity and which at the other. The side carrying it writes the rows.
Set vs. List for associations
Use Set for a to-many association: the links are unique and unordered, Hibernate treats an unordered List as a bag (changes rewrite the whole collection; fetching two bags together fails), and id-based equals/hashCode make a HashSet of entities safe. Impose order at the API edge, not on the entity.
Cascade / orphanRemoval
Cascade propagates an operation from the side that declares the association to the entities it references — with CascadeType.ALL on Book.authors, deleting one book would delete its authors, including a co-author still attached to other books. orphanRemoval deletes a child once it's removed from the parent's collection. Powerful but sharp: this course leaves cascade off, so authors and books keep independent lifecycles and the database's foreign key guards against accidental deletes. Reach for cascade only when you've deliberately decided a child should share its parent's lifecycle.
DTO (Data Transfer Object)
A plain object — here an immutable record — that shapes data crossing the API boundary, separate from your entities. A request DTO (e.g. CreateBookRequest, no id) defines what you accept; a response DTO (e.g. BookResponse) defines what you send. A related entity is nested as its own response DTO, never as the entity — a book's authors are AuthorResponse records (id + name) — which keeps lazy collections and other persistence details off the wire. A request DTO with no id field leaves nothing for a client to smuggle. DTOs decouple the wire format from the schema.
Open Session in View (OSIV)
A Spring Boot default (spring.jpa.open-in-view=true) that keeps the persistence session open for the whole request, so lazy associations can load during JSON rendering. Convenient — it's why mapping an entity to a DTO in the controller "just works" — but it can hide N+1 queries; many teams disable it.
N+1 query problem
Loading N parent rows and then firing one extra query per parent to fetch its children — N+1 queries where one join would do. It's the most common JPA performance trap; fixes include a JOIN FETCH query or an entity graph.

Lesson 7 · Validation & Error Handling

Bean Validation (Jakarta Validation)
A Java standard for declaring input rules as field annotations and having them checked automatically. Hibernate Validator is the reference implementation; Spring Boot wires it in via spring-boot-starter-validation.
Constraint annotation
An annotation declaring a validation rule on a field: @NotNull, @NotBlank (non-null and non-whitespace), @Size(min,max), @Positive, @Min/@Max, @Email, @Pattern. Placed on the request DTO — the boundary shape — not the entity.
@Valid
The switch that triggers validation. On a @RequestBody parameter it tells Spring to check the object's constraints before the handler runs; a violation throws MethodArgumentNotValidException. Without it, constraints are ignored.
MethodArgumentNotValidException
The exception Spring throws when a @Valid body fails its constraints. Its BindingResult holds the per-field errors; a handler reads them to build a response. Maps naturally to 400 Bad Request.
@ControllerAdvice / @RestControllerAdvice
A class whose @ExceptionHandler methods apply across every controller — one central place to turn exceptions into HTTP responses. The @RestController variant writes return values to the response body (as JSON), like @RestController does.
@ExceptionHandler
Marks a method that handles a given exception type. In a @RestControllerAdvice it catches that exception from any controller and returns the error response to send. Spring picks the most specific handler, so a method for a precise type out-ranks a catch-all @ExceptionHandler(Exception.class).
ResponseEntityExceptionHandler
Spring's base class for a global exception handler. Extending it inherits ready-made, ProblemDetail-shaped handling for every standard Spring MVC exception (malformed JSON, type mismatch, unsupported method/media type, validation, …). You override individual methods (e.g. handleMethodArgumentNotValid) to customize, add @ExceptionHandlers for your own exceptions, and rely on specificity so a catch-all only fires for the truly unexpected.
Problem Detail (RFC 9457)
The standard JSON format for HTTP error bodies — fields type, title, status, detail, instance, plus custom members. Spring's ProblemDetail class produces it; returning one sets the application/problem+json content type and the status. A single consistent error shape across the whole API.
409 Conflict
The status for a request that is well-formed and addresses something that exists, but that the current state of the data forbids — here, deleting an author who still has books. Unlike a 404, the client can fix it: change the state (delete or re-author the books) and the same request succeeds. The service checks and throws a ConflictException; the foreign key underneath remains the real guarantee.

Lesson 8 · Pagination & Sorting

Pagination
Returning a large collection one fixed-size page at a time instead of all at once, by pushing a LIMIT and OFFSET down to the database. Bounds the work done by the database, server, and client regardless of table size. Pages are zero-based (page 0 is the first).
Pageable
Spring Data's request for a page: which page number, how many rows, and the sort order. Declared as a controller method parameter, it is built automatically from the page, size, and sort query parameters — no @RequestParam needed — and handed to a repository method.
Page / Slice
What a paged repository method returns. Page<T> holds the slice of rows plus metadata (totalElements, totalPages, current number, size) — it runs an extra COUNT query to know the totals. Slice<T> skips the count and only knows whether a next page exists (cheaper; good for "load more"). Page.map(...) transforms each element to a DTO while preserving the metadata.
@PageableDefault
Sets the default page size and sort applied when a request omits them, e.g. @PageableDefault(size = 20, sort = "title"). Without it, an unparameterized request falls back to Spring's global default (20 rows, unsorted).
PagedModel / serialization-mode=via_dto
PagedModel is Spring Data's small, stable representation of a page (content plus a page object with size, number, totalElements, totalPages). Turn it on with the property spring.data.web.pageable.serialization-mode=via_dto. The reference docs also show @EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO), but on Spring Boot that annotation replaces Boot's auto-configuration and silently disables the spring.data.web.pageable.* properties (including max-page-size) — so the property is the form this course uses.

Lesson 9 · The N+1 Query Problem

Lazy vs. eager fetching
Whether an association loads with its owner (eager) or only when first accessed (lazy, via a proxy that fires a query on touch). @ManyToMany defaults to lazy fetching, which is the right default for a collection — but every lazy touch is a potential query, which is how the N+1 problem arises.
@EntityGraph
A fetch hint on a Spring Data repository method naming the associations to load in the same query: @EntityGraph(attributePaths = "authors"). The go-to fix for N+1 — the association is LEFT JOINed in rather than lazily loaded per row. Safe with pagination for to-one associations (a join adds columns, not rows); for to-many collections the query is more involved (modern Hibernate paginates the parents in a subquery first).
Fetch join (JOIN FETCH)
An explicit JPQL clause that loads an association alongside its owner in one query: select b from Book b join fetch b.authors. The hand-written equivalent of @EntityGraph — reach for it inside a custom @Query.
LazyInitializationException
Thrown when code touches a lazy association after its persistence session has closed (Could not initialize proxy … no session). Common once spring.jpa.open-in-view=false: it turns a hidden lazy load into a loud failure, signalling exactly where you must fetch the association deliberately (a fetch join or @EntityGraph).
@BatchSize / batch fetching
An alternative to join-fetching: keep associations lazy but load them in batches. hibernate.default_batch_fetch_size = N (or @BatchSize(size = N)) collapses N per-row lazy loads into a few WHERE id IN (?, ?, …) queries — turning 1 + N into roughly 1 + (N / batchSize). Needs an open session when the collection is accessed.

Lesson 10 · Unit-Testing the Service Layer

Unit test
A test of one class in isolation, with its collaborators replaced by test doubles — no framework, no database, no network. Fast (milliseconds) and precise: a failure points straight at the class under test. The broad base of the test pyramid.
Test pyramid
A guideline for the mix of tests: many fast unit tests at the base, fewer slice tests in the middle (one layer with a little framework), and a few slow end-to-end tests at the top. Push coverage down toward the fast base where you can.
Test double (mock / stub)
A stand-in for a real dependency in a test. A stub is scripted to return canned answers (when(repo.findById(id)).thenReturn(...)); a mock also records interactions so you can assert they happened (verify(repo).save(...)). In Mockito a single @Mock object does both jobs: it implements the type but runs none of its code, returns defaults (null, 0/false, an empty Optional or collection) until stubbed, and records every call. @ExtendWith(MockitoExtension.class) puts a new one in each @Mock field before every test.
JUnit 5
The standard Java test framework: @Test methods, lifecycle hooks (@BeforeEach), @DisplayName, and an extension model (@ExtendWith) that plugs in tools like Mockito. Ships with Spring Boot's test starter.
Mockito
The de-facto Java mocking library. @Mock creates a test double; when(...).thenReturn(...) stubs its answers; verify(...) asserts it was (or, with never(), wasn't) called; an ArgumentCaptor grabs the exact argument passed to a mock so you can assert on it. Enabled in JUnit 5 via @ExtendWith(MockitoExtension.class), which runs in strict-stubbing mode.
AssertJ
A fluent assertion library: assertThat(x).isEqualTo(y), isSameAs, assertThatThrownBy(() -> …).isInstanceOf(...).hasMessageContaining(...). Reads left-to-right and gives rich failure messages. The assertion style used throughout this course.
Arrange–Act–Assert (AAA)
The three-beat shape of a good test: Arrange the data and stub the doubles, Act by calling the one method under test, Assert the outcome. One action, one behaviour, per test.

Lesson 11 · Testing the Web Layer

Test slice
A test that starts only one layer of the application in Spring — the web layer, or the persistence layer — instead of the whole context. The middle of the test pyramid: real framework behaviour, a fraction of the start-up cost.
@WebMvcTest
The web-layer slice. Loads the named controller, @ControllerAdvice beans, converters, filters and Spring MVC's configuration; leaves out @Service, @Repository and other @Component beans, so no database is needed. Auto-configures MockMvc and, with AssertJ present, MockMvcTester.
@MockitoBean
The Spring counterpart of @Mock, for when Spring builds the class under test. Creates a Mockito mock and registers it in the test's Spring context as the bean of that type — replacing the real bean, or creating it if the context has none — so it is injected wherever that type is needed: in a @WebMvcTest, into the controller. Reset after each test. Replaces Spring Boot's @MockBean, removed in Spring Boot 4.0.
MockMvc / MockMvcTester
Spring's way to send requests through DispatcherServlet without starting a server: routing, conversion, validation, exception handling and JSON all run, on in-memory requests and responses. MockMvcTester is its AssertJ face — assertThat(mvc.get().uri(...)).hasStatusOk() — and the one this course uses; the older style is mockMvc.perform(...).andExpect(...).
Strict vs lenient JSON comparison
Two ways to compare a JSON body with an expected document. Strict fails on any extra field and requires arrays in the same order; lenient allows extra fields and any array order. The course compares every response body strictly, so a test shows the whole response; lenient is for bodies with values a test can't know in advance, such as server-generated timestamps.
JSONPath
An expression language for picking values out of a JSON document: $ is the root, $.title a field, $.errors.name a nested field, $.content[0] an array element. Used in tests with extractingPath(...).

Lesson 12 · Testing the Data Layer

@DataJpaTest
The persistence-layer test slice. Loads entities, Spring Data repositories, JPA, the DataSource and Liquibase; leaves out services, controllers and other @Component beans. Every test runs in a transaction that is rolled back at the end.
Testcontainers
A Java library that starts real services — databases, message brokers — in throwaway Docker containers for tests, and removes them afterwards. Its PostgreSQL module gives a PostgreSQLContainer.
@ServiceConnection
Marks a Testcontainers container (a field or a @Bean) as the connection for a Spring Boot service: Boot reads the address, user and password from the running container and configures, for a database, the DataSource from them. No spring.datasource.* properties needed.
Persistence context (first-level cache)
The set of entities a JPA session has loaded or saved, at most one object per id. A query still runs its SQL, but a row whose entity is already in the context comes back as that same object. clear() empties it, so later reads go to the database.
TestEntityManager
A test-friendly wrapper around JPA's EntityManager, available in @DataJpaTest: persist to queue fixtures, flush to send the inserts, clear to empty the persistence context.
Hibernate statistics
Counters Hibernate keeps for a SessionFactory when hibernate.generate_statistics=true — among them getPrepareStatementCount(), the number of SQL statements prepared. Reached with entityManagerFactory.unwrap(SessionFactory.class).getStatistics().
JdbcTemplate
Spring's thin layer over JDBC: give it SQL and parameters, and it runs them and maps the result (queryForObject for one value, queryForList for a column of rows). No JPA involved, so in a test it shows what the tables really hold. Doesn't flush the persistence context — flush first.

Lesson 13 · Integration Tests with @SpringBootTest

Integration test
A test that runs several parts of the application together — here all of them: the whole Spring context, the real database and the HTTP server, called the way a client calls them. Slower than a slice and less precise about where a failure is, so kept few.
@SpringBootTest
Builds the application's whole context for a test, found through the @SpringBootApplication class: every bean, application.properties, Liquibase, DataSeeder. Its webEnvironment is a mock by default; RANDOM_PORT starts the embedded server on a free port.
RestTestClient
Spring's HTTP client for tests: build a request, exchange() it, chain expectations on the status, headers and body (json(…, JsonCompareMode.STRICT)). @AutoConfigureRestTestClient points it at the server a RANDOM_PORT test started.
Context caching
Spring's test framework keeps each application context it builds and reuses it for every test class with the same configuration, so the context — and a container bean in it — starts once. A different configuration gets a context, and a container, of its own.

Lesson 14 · Documenting the API with OpenAPI

OpenAPI
The standard description format for HTTP APIs: one JSON or YAML document with every path and operation, its parameters, request and response bodies and their schemas. Read by tools such as Swagger UI and client generators.
springdoc-openapi
A library that generates an OpenAPI spec from a Spring application's MVC mappings, records and validation constraints, and serves it at /v3/api-docs; its UI modules serve a docs page for it (Scalar at /scalar, or Swagger UI at /swagger-ui.html). Annotations (@Operation, @ApiResponse, @Schema…) add what the code can't say, and are read from interfaces too.
Scalar
A web page that renders an OpenAPI spec as an API reference: operations grouped by tag, their parameters, bodies and responses, a ready-made request (such as curl) for each, and a "Test Request" button that sends it. Swagger UI is the older, widespread alternative.
Components (OpenAPI)
The reusable parts of an OpenAPI spec — schemas, responses, examples — each under a name in components, and used elsewhere through a $ref such as #/components/responses/BookNotFound. In springdoc, @ApiResponse(ref = "BookNotFound") points an operation at one.
@ParameterObject
springdoc's annotation for a method parameter whose fields are bound from separate query parameters — on a Pageable, it documents page, size and sort instead of one object.