Read models over HTTP
Spring Data REST
Add spring-boot-starter-data-rest to the application, and its projection repositories are exported read-only, under the application’s own Spring Data REST detection strategy (with annotated, a repository without @RepositoryRestResource is not exported):
-
GETreads; every write answers405 Method Not Allowed, for an in-memory or query repository and for the application’s own JPA repository over a read model alike; -
a sort the store cannot run, or an id in a link that makes no id of the repository, answers
400 Bad Request; -
a repository carrying
@RepositoryRestResource(exported = false)is not exported; -
an in-memory or query repository whose read model has no
@ReadModelKeyown id with a backing field is never exported, since Spring Data REST links an item by its id; see The read model’s own id.
These answers come from exception advice for Spring Data REST’s controllers, ordered just before Spring Data REST’s own; an advice of the application ordered earlier wins.
Spring MVC
An in-memory or query repository’s id that wraps a single value, such as AccountId(val value: UUID), a value class or a class of one scalar or enum property, is made from text in a path variable or a request parameter, and in a Spring Data REST link.
A String-to-id Converter the application registers itself is used instead of the framework’s.
It is a Converter bean for Spring MVC, and for a Spring Data REST link it is also added in a RepositoryRestConfigurer’s `configureConversionService.
The application’s own JPA repositories follow Spring Data JPA’s rules.
With Spring Data web support, a controller parameter typed as the read model resolves through the repository’s findById, and is null when no read model has that id.
Spring Boot sets the support up in a Spring MVC application with a Spring Data starter, such as spring-boot-starter-data-jpa or spring-boot-starter-data-rest; otherwise declare @EnableSpringDataWebSupport on a configuration class.
@RestController
class AccountSummaryController {
@GetMapping("/accounts/{id}")
fun summary(@PathVariable("id") summary: AccountSummary?): AccountSummary =
summary ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
}
The read model is that of an in-memory projection with an AccountSummaryRepository, as in In-memory store.
The path variable is read as the repository’s id, AccountId, and the summary is looked up by it.