Save 37% off PRO during our Black Friday Sale! »

Hello REST API: What can I do next?

A0aae1297a0593c1316abdcdb4131e3a?s=47 Kai Toedter
November 07, 2019

Hello REST API: What can I do next?

In this presentation, Kai shows how to use hypermedia to create REST APIs that do not only provide data but also information about what to do next. This can be in the form of hyperlinks for navigating and describing actions that can be performed on the REST resources. As an example representation, HAL-Forms is used, an extension of the popular HAL format. Another topic is the Affordances API of the current Spring HATEOAS (Hypermedia as the Engine of Application State).

A0aae1297a0593c1316abdcdb4131e3a?s=128

Kai Toedter

November 07, 2019
Tweet

Transcript

  1. None
  2. Who am I?  Principal Key Expert at Siemens Smart

    Infrastructure  Web Technology Fan  Open Source Lover  E-mail: kai@toedter.com  Twitter: @kaitoedter 11/9/2019 2 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  3. Show Hands! 11/9/2019 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 3
  4. Outline  HATEOAS?  Links  Affordances  Demos &

    Live Coding  Conclusion 11/9/2019 4 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License.
  5. HATEOAS  Is for “Hypermedia As The Engine Of Application

    State”  Very hard to pronounce   Key concept of REST 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 5
  6. “With HATEOAS, a client interacts with a network application whose

    application servers provide information dynamically through hypermedia. A REST client needs little to no prior knowledge about how to interact with an application or server beyond a generic understanding of hypermedia.” 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 6 Wikipedia Source: https://en.wikipedia.org/wiki/HATEOAS
  7. “When I say Hypertext, I mean … The simultaneous presentation

    of information and controls such that the information becomes the affordance through which the user obtains choices and selects actions.” 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 7 Roy Fielding Source: http://roy.gbiv.com/talks/200711_REST_ApacheCon.pdf
  8. Richardson Maturity Model Level 3: Hypermedia Controls Level 2: HTTP

    Verbs Level 1: Resources Level 0: The Swamp of POX 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 8 Source: http://martinfowler.com/articles/richardsonMaturityModel.html
  9. Spring HATEOAS  Spring basic framework for REST with Hypermedia

    support  Overhaul in version 1.0.0  Supports generic Hypermedia API  Supports Representations like HAL, HAL-FORMS, UBER, Collection+JSON, …  https://docs.spring.io/spring-hateoas/docs/current- SNAPSHOT/reference/html/ 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 9
  10. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 10 Links
  11. Links  Essential for hypermedia  In REST: How to

    navigate to a REST resource  Link semantic/name is called link relation  The relation between a REST resource and the target REST resource  Links are well known from HTML, like <a href="url">link text</a> 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 11
  12. Links in Spring HATEOAS Link link = new Link("/my-url"); 

    A link automatically has a self relation Link link = new Link("/my-url", "my-rel");  A link with my-rel relation 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 12
  13. Link Relations  Many Link relations are standardized by IANA

     IANA = Internet Assigned Numbers Authority  https://www.iana.org/assignments/link- relations/link-relations.xhtml  Examples: self, item, next, last, …  Recommendation: Before creating a custom name for a link relation, look up the IANA list! 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 13
  14. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 14 Root API
  15. api.github.com 11/9/2019 © Kai Tödter, Licensed under a Creative Commons

    Attribution 4.0 International License. 15 { "current_user_url": "https://api.github.com/user", "current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}", "authorizations_url": "https://api.github.com/authorizations", "code_search_url": "https://api.github.com/search/code?q={query}{&page,per_page,sort,order}", "commit_search_url": "https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}", "emails_url": "https://api.github.com/user/emails", "emojis_url": "https://api.github.com/emojis", "events_url": "https://api.github.com/events", "feeds_url": "https://api.github.com/feeds", "followers_url": "https://api.github.com/user/followers", "following_url": "https://api.github.com/user/following{/target}", "gists_url": "https://api.github.com/gists{/gist_id}", "hub_url": "https://api.github.com/hub", "issue_search_url": "https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}", "issues_url": "https://api.github.com/issues", "keys_url": "https://api.github.com/user/keys", "notifications_url": "https://api.github.com/notifications", "organization_repositories_url": "https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}", … }
  16. Movies Root API { "_links": { "self": { "href": "http://localhost:8080/api"

    }, "movies": { "href": "http://localhost:8080/api/movies{?size,page}", "templated": true }, "directors": { "href": "http://localhost:8080/api/directors{?size,page}", "templated": true } } } 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 16
  17. Links are Great  For providing navigation to useful other

    REST resources  For providing domain knowledge to the REST clients, so that they don’t have to compute domain state on there own 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 17
  18. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 18 Representation Models
  19. Representation Models  REST => Representational State Transfer  Manipulation

    of resources through their representations  Domain Model != Representation Model  Spring HATEOAS provides RepresentationModel abstraction 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 19
  20. Spring HATEOAS RepresentationModel  RepresentationModel  Root class, for REST

    item resourses  CollectionModel  For REST collection resources  EntityModel  Convenient wrapper for converting a domain model into a representation model  PagedModel  Addition to CollectionModel for paged collections 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 20
  21. Domain Model Example @Data @Entity @NoArgsConstructor public class Director {

    @Id @GeneratedValue private Long id; private String name; @ManyToMany(fetch = FetchType.EAGER) private List<Movie> movies = new ArrayList<>(); public Director(String name) { this.name = name; } … } 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 21
  22. Representation Model Example @Data public class DirectorRepresentationModel extends RepresentationModel<DirectorRepresentationModel> {

    private String name; public DirectorRepresentationModel(Director director) { this.name = director.getName(); add(linkTo(methodOn(DirectorController.class) .findOne(director.getId())).withSelfRel()); for (Movie movie : director.getMovies()) { add(linkTo(methodOn(MovieController.class) .findOne(movie.getId())) .withRel("movies") .withTitle(movie.getTitle())); } } } 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 22
  23. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 23 HAL Image Source: http://wallpoper.com/images/00/26/43/92/hal-9000_00264392.jpg
  24. HAL  Is for Hypertext Application Language  Created by

    Mike Kelly  Representations for both JSON and XML  Very popular & very simple  Spec: https://tools.ietf.org/html/draft-kelly- json-hal-08 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 24
  25. HAL Structure 11/9/2019 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 25 Plain old JSON Properties Links Plain old JSON Properties Links Plain old JSON Properties Links … Embedded Resources Embedded Resources Embedded Resources
  26. HAL Example { "name": "Ridley Scott", "_links": { "self": {

    "href": "https://movies-demo.org/api/directors/89", }, "movies": [ { "href": "https://movies-demo.org/api/movies/93", "title": "Alien" }, … ] } } 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 26
  27. URI Templates  A URI Template is used for describing

    a range of URIs through variable expansion  Defined in https://tools.ietf.org/html/rfc6570  Example: https://mymovies.org/api/movies{?size,page} 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 27
  28. URI Templates in Spring HATEOAS UriTemplate template = UriTemplate.of("/movies") .with(new

    TemplateVariable("page", REQUEST_PARAM)) .with(new TemplateVariable("size", REQUEST_PARAM)); => /movies{?page,size} 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 28
  29. HAL URI Templates Example { "_links": { "self": { "href":

    "https://movies-demo.org/api" }, "movies": { "href": "https://movies-demo.org/api/movies{?size,page}", "templated": true }, "directors": { "href": "https://movies-demo.org/api/directors{?size,page}", "templated": true } } } 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 29
  30. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 30 Paging Image Source: https://de.freeimages.com/photo/open-book-1417485
  31. Example: Paging (1)  Paging is useful to partition large

    result sets  If you had to write a frontend for paging, you need information about:  Number of all pages  Current page  Page size  Info about first, previous, next, last page URLs 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 31
  32. Example: Paging (2)  If a (frontend) client only gets

     current page, page size, number of all pages  It has to decide  when to enable/disable First, Prev, Next, Last buttons  It has to compute  all the data fetching URLs for above buttons 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 32
  33. Example: Server-side Paging with Links "_links": { "next": { "href":

    "http://movie-demo.org/api/movies?page=1&size=10" }, "last": { "href": "http://movie-demo.org/api/movies?page=14&size=10" } } Important: NO links for first and prev => extra semantics! Client has just to interpret the links to create the UI 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 33
  34. Movies Paging Demo 11/9/2019 © Kai Tödter, Licensed under a

    Creative Commons Attribution 4.0 International License. 34
  35. Paging Client with Vue.js <ul class="pagination"> <li :class="{'page-item':true, 'disabled':!links.first}"> <a

    class="page-link" href="#" aria-label="First" v-on:click="getMovies(links.first.href)"> <span aria-hidden="true">&laquo;</span> <span class="sr-only">First</span> </a> </li> <li :class="{'page-item':true, 'disabled':!links.prev}"> <a class="page-link" href="#" aria-label="Previous" v-on:click="getMovies(links.prev.href)"> <span aria-hidden="true">&lsaquo;</span> <span class="sr-only">Previous</span> </a> </li> 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 35
  36. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 36 Affordances
  37. “ The affordances of the environment are what it offers

    …​ what it provides or furnishes, either for good or ill. The verb 'to afford' is found in the dictionary, but the noun 'affordance' is not. I have made it up.” James J. Gibson The Ecological Approach to Visual Perception (1986) 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 37
  38. Affordances  With Affordances, possible actions on a REST resource

    (or Link relation) can be described in more detail, e.g.  What can you do with a REST resource?  Create, Update, Delete, …  Which parameters are mandatory or optional  How would (internationalized) labels be displayed in a user interface  … 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 38
  39. Spring HATEOAS Affordances Example public MovieRepresentationModel toModel(Movie movie) { Link

    selfLink = linkTo(methodOn(MovieController.class) .findOne(movie.getId())).withSelfRel(); final Affordance updateAffordance = afford(methodOn(MovieController.class) .updateMovie(null, movie.getId())); final Affordance deleteAffordance = afford(methodOn(MovieController.class) .deleteMovie(movie.getId())); return new MovieRepresentationModel(movie, selfLink .andAffordance(updateAffordance) .andAffordance(deleteAffordance)); } © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 39
  40. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 40 HAL-FORMS Image Source: http://wallpoper.com/images/00/26/43/92/hal-9000_00264392.jpg Shutdown! Restart
  41. HAL-FORMS  Designed to provide forms support for HAL 

    Created by Mike Amundsen  _templates for possible actions on self link  Spec: https://rwcbook.github.io/hal-forms/ 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 41
  42. “The HAL-FORMS media type design follows many of the HAL

    media type conventions. For this reason, HAL-FORMS "looks like HAL." However, it is important to keep in mind that HAL-FORMS is not the same as HAL — the two should not be thought of as interchangeable in any way.” 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 42 Mike Amundsen Source: https://rwcbook.github.io/hal-forms/
  43. Rendering with HAL-FORMS (1) "_templates": { "default": { "title": null,

    "method": "put", "contentType": "", "properties": [ { "name": "imdbId", "prompt": "IMDB Id", "required": true }, … © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 43
  44. Rendering with HAL-FORMS (2) "_templates": { "default": { … },

    "deleteMovie": { "title": null, "method": "delete", "contentType": "", "properties": [] } } © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 44
  45. HAL Explorer  https://github.com/toedter/hal-explorer  Easily integratable through WebJar and

    spring-data-rest-hal-explorer dependency  Supports HAL, HAL-FORMS and Spring JSON Schema  Supports custom request headers  Supports theming and responsive design 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 45
  46. HAL Explorer 11/9/2019 © Kai Tödter, Licensed under a Creative

    Commons Attribution 4.0 International License. 46
  47. Spring HATEOAS Internationalization  Resource bundle: rest-messages.properties  Examples 

    Movie._templates.updateMovie.title=Change Movie  Movie.year._prompt=Release Year  Reacts on Accept-Language HTTP header  Accept-Language: de-DE,de;q=0.9,en;q=0.8,en-US;q=0.7  Would return German if there is a _de resource bundle 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 47
  48. Movie Details with Affordances (EN) 11/9/2019 © Kai Tödter, Licensed

    under a Creative Commons Attribution 4.0 International License. 48
  49. Movie Details with Affordances (DE) 11/9/2019 © Kai Tödter, Licensed

    under a Creative Commons Attribution 4.0 International License. 49
  50. Client “Domain vs Protocol” Knowledge No Hypermedia Links Affordances 11/9/2019

    © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 50 Domain Knowledge Protocol Knowledge Client Effort & Robustness
  51. Demo + Live Coding 11/9/2019 © Kai Tödter, Licensed under

    a Creative Commons Attribution 4.0 International License. 51
  52. 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution

    4.0 International License. 52 Discussion
  53. Links  Movies Hypermedia Demo: https://github.com/toedter/movies-demo  Spring HATEOAS: https://github.com/spring-projects/spring-

    hateoas 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 53
  54. License  This work is licensed under a Creative Commons

    Attribution 4.0 International License.  See http://creativecommons.org/licenses/by/4.0/ 11/9/2019 © Kai Tödter, Licensed under a Creative Commons Attribution 4.0 International License. 54