Spring Rest Repositories
Motivation
REST - APIs 95% Boilerplate
@RestController
@AllArgsConstructor
public class Api {
private final Repository repository;
private final Service service;
@GetMapping
public Optional<Entity> findById() { ... }
@GetMapping
public List<Entity> getAll() { ... }
@GetMapping
public List<Entity> query(condition) {
return repository.query(condition);
}
@PostMapping
public Entity save() { ... }
Repository
public interface StudentRepository
extends CrudRepository<Student, Long> { ...
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
= GET /students ⟹
{
"_embedded": {
"students": [
...
Customization
@RepositoryRestResource(
collectionResourceRel = "students-rel",
path = "students-path")
public interface StudentRepository
extends CrudRepository<Student, Long> { ...
}
"_links": {
"students-rel": {
"href": "http://localhost:8080/students-path",
"templated": true
}
...
public interface StudentRepository
extends CrudRepository<Student, Long> {
@Override
@RestResource(exported = false) // internal use only -> 405
void deleteById(Long id);
List<Student> findAllByName(String name);
}
GET /students
{
"_embedded": {
"students": [
...
],
"_links": {
...,
"search": {
"href": "http://localhost:8080/students/search"
}
GET /students/search
"_links": {
"findAllByName": {
"href": "http://localhost:8080/students/search/findAllByName{?name}",
"templated": true
},
"self": {
"href": "http://localhost:8080/students/search"
}
GET /students/search/findAllByName?name=Alfred
"_embedded": {
"students": [
{
"name": "Alfred",
...
}
]
},
...
@Override
@RepositoryRestController // nicht RestController
@AllArgsConstructor
public class StudentController {
private final StudentRepository studentRepository;
@GetMapping("students/{id}")
@ResponseBody
ResponseEntity<EntityModel<Student>> serveId1(@PathVariable Long id) {
var student = studentRepository
.findById(1L)
.orElseThrow();
var resource = EntityModel.of(student);
var link = linkTo(methodOn(StudentController.class).serveId1(1L));
resource.add(link.withSelfRel());
return ResponseEntity.ok(resource);
}
}