Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filling entity links in custom @RepositoryRestController methods

I am using Spring-data-rest to provide read APIs over some JPA entities. For writes I need to issue Command objects rather than directly write to the DB, so I added a custom controller using @RepositoryRestController and various command handling methods:

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody MyEntity post(@RequestBody MyEntity entity) {
  String createdId = commands.sendAndWait(new MyCreateCommand(entity));
  return repo.findOne(createdId);
}

I would like the output to be enriched just like any other response by the spring-data-rest controller, in particular I want it to add HATEOAS links to itself and its relations.

like image 401
Andrea Ratto Avatar asked Aug 10 '15 16:08

Andrea Ratto


People also ask

What does the @RepositoryRestResource annotation do?

The @RepositoryRestResource annotation is optional and is used to customize the REST endpoint. If we decided to omit it, Spring would automatically create an endpoint at “/websiteUsers” instead of “/users“. That's it! We now have a fully-functional REST API.

Why is Spring Data REST not recommended in real world applications?

It is not recommended in real-world applications as you are exposing your database entities directly as REST Services. While designing RESTful services, the two most important things that we consider are the domain model and the consumers. But, while using Spring Data REST, none of these parameters are considered.

What is @RepositoryRestController?

Annotation Type RepositoryRestControllerAnnotation to demarcate Spring MVC controllers provided by Spring Data REST. Allows to easily detect them and exclude them from standard Spring MVC handling.

What is used for exposing spring data repositories over REST using Spring Data REST?

Spring Data REST can be used to expose HATEOAS RESTful resources around Spring Data repositories. Without writing a lot of code, we can expose RESTful API around Spring Data Repositories.


1 Answers

This has recently been answered (see point 3.) by Oliver Gierke himself (the question used quite different keywords though, so I won't flag this as duplicate).

The example for a single entity would become:

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody PersistentEntityResource post(@RequestBody MyEntity entity,
    PersistentEntityResourceAssembler resourceAssembler)) {
  String createdId = commands.sendAndWait(new MyCreateCommand(entity));
  return resourceAssembler.toResource(repo.findOne(createdId));
}

The example for a non-paginated listing:

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Resources<PersistentEntityResource> post(
    @RequestBody MyEntity entity,
    PersistentEntityResourceAssembler resourceAssembler)) {
  List<MyEntity> myEntities = ...
  List<> resources = myEntities
      .stream()
      .map(resourceAssembler::toResource)
      .collect(Collectors.toList());
  return new Resources<PersistentEntityResource>(resources);
}

Finally, for a paged response one should use an injected PagedResourcesAssembler, passing in the method-injected ResourceAssembler and the Page, rather than instantiating Resources. More details about how to use PersistentEntityResourceAssembler and PagedResourcesAssembler can be found in this answer. Note that at the moment this requires to use raw types and unchecked casts.

There is room for automation maybe, better solutions are welcome.

P.S.: I also created a JIRA ticket to add this to Spring Data's documentation.

like image 147
hzpz Avatar answered Sep 28 '22 17:09

hzpz