Filling entity links in custom @RepositoryRestController methods
Asked Answered
F

1

10

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.

Flameout answered 10/8, 2015 at 16:47 Comment(0)
P
15

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.

Puppet answered 10/8, 2015 at 19:29 Comment(4)
would this be a more detailed example of Gierke's option 3: https://mcmap.net/q/504414/-can-i-make-a-custom-controller-mirror-the-formatting-of-spring-data-rest-spring-hateoas-generated-classes ?Flameout
There are some important bits still missing: 1) how do you get from a "MyEntity" to a PersistentEntityResource. 2) The example targeted at a paginated collection, for a single entity the process is different. I will try by myself to solve these,.Flameout
Solved easily for a single resource and updated the answer. It is still counter-intuitive to have a resourceAssembler injected on the method and repetitive to call toResource for every handler. It would be nice if building a resource could happen automatically by returning just the entity. I'll wait a little before flagging as accepted, to see if improvements come up.Flameout
Since this is the way the lead developer of Spring Data described, I doubt it.Puppet

© 2022 - 2024 — McMap. All rights reserved.