spring-rest-repositories

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);
    }
}