3

What is the best practice for obtaining an entity from a link in spring-hateoas?

I have two independent entities, author and document, where documents have can have multiple authors, but authors can exist without being linked to any documents.

To fetch the authors for a given document, there is an endpoint at /documents/{id}/authors which returns a list of the authors and their links.

An author is added to a document by issuing a POST of a link entity to /documents/{id}/authors where the entity contents are the same as a org.springframework.hateoas.Link, that is to say a rel and an href:

{
 "rel": "author", 
 "href": "http://localhost:8081/authors/50"
}

I want to be able to do a service call like:

service.addAuthor(documentId, authorId);

documentId is provided as a @PathVariable, while authorId is embedded in the href.

In order to get authorId, I currently use spring's RequestMappingHandlerMapping and the controller class for the entity type (author in this case) to fetch the RequestMapping for the entity's GET method and fetch the id uri template variable for the href provided in the link. Finally, I have to parse this as a number.

Is there some better/built-in way of doing this?

Using spring-hateoas 0.17.0, if that is relevant.

beerbajay
  • 19,652
  • 6
  • 58
  • 75
  • I would generally create an additional `key` property of the `AuthorResource` (or whatever you called it). That tends to be useful if you want a simple POST endpoint taking a couple of IDs. However, if you have just retrieved the JSON for an author resource, then you can always just PUT it to the `documents/{id}/authors` endpoint. That endpoint can take a `@RequestBody AuthorResource` argument, from which you can get the author ID. – Steve Mar 18 '15 at 10:56
  • Regarding your last point; I don't serialize the ID or the URL as a part of the entity, so although I would be able to deserialize an `AuthorDTO`, I don't see how I would be able to fetch the actual entity from this information. Or am I missing something? – beerbajay Mar 18 '15 at 11:03
  • I'm assuming that by making a GET to `authors/{id}`, you would get a JSON representation of that author (your `AuthorDTO`?). In which case you should be able to PUT that to an endpoint. If that endpoint accepts an author as a `@RequestBody`, then you can get the ID from the author and call your service. btw - Am I right in thinking that you're using Spring Data REST, rather than using Spring HATEOAS directly? If you were using Spring HATEOAS directly, you could easily add links to resources. – Steve Mar 18 '15 at 11:41
  • No, I am not using `spring-data-rest`. "get the ID from the author" <-- how would I do this when ID is not serialized as a part of the DTO? Is there some magic I am missing? – beerbajay Mar 18 '15 at 12:12
  • How are you generating a URL such as `http://localhost:8081/authors/50`, if the resource assembler has no way to see that the ID is 50? – Steve Mar 18 '15 at 12:17
  • The entity has an ID, generated by the DB upon creation. The DTO has no id field; the user of the API saves the entire link rather than just the numeric id. The assembler is working with the entity, where it always has access to the id. – beerbajay Mar 18 '15 at 12:46
  • If you add the ID to the `ResourceSupport` object (the DTO you refer to?) you are returning from your controller, then it's available for you to play with. Is there a particular constraint of your application, that you haven't told us about, preventing you from including the ID as a property of the resource? – Steve Mar 18 '15 at 14:31
  • It is a design decision to not expose the ID as a field to the client; they should only care about the URI of the entity. I don't really see why PUTing the entire author entity to `documents/{id}/authors/` is a better solution than extracting the id from an URI. – beerbajay Mar 20 '15 at 08:28
  • Take a look at [this](http://stackoverflow.com/a/26348463/2151351) answer. – a better oliver Apr 01 '15 at 10:41
  • @zeroflagL This is essentially what I am already doing. – beerbajay Apr 01 '15 at 11:25
  • Spring Data REST does essentially the same, except that it uses `UriTemplate.match`. So no, there isn't a better built-in way. Btw: It's preferable to post a uri list. – a better oliver Apr 01 '15 at 11:55

0 Answers0