Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spring HATEOAS

Avatar for Dai Yamasaki Dai Yamasaki
November 15, 2019

Spring HATEOAS

JSUG勉強会 2019その10 SpringOne Platform 2019報告会

Avatar for Dai Yamasaki

Dai Yamasaki

November 15, 2019
Tweet

Other Decks in Programming

Transcript

  1. Migration script 0.x $ ./migrate-to-1.0.sh Migrating Spring HATEOAS references to

    1.0 for files : *.java Adapting ./src/main/java/… … Done! https://github.com/spring-projects/spring-hateoas/tree/master/etc
  2. REST ੒ख़౓ • Level 0
 ҰͭͷURLͱҰͭͷHTTPϝιου • Level 1
 ҟͳΔURLͱҰͭͷHTTPϝιου

    • Level 2
 ҟͳΔURLͱҟͳΔHTTPϝιου • Level 3
 APIͷϨεϙϯεʹϋΠύʔϦϯΫ৘ใΛ࣋ͭ
  3. Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {

    "rel":"customer", "href":"...", }, { "rel":"self", "href":"...", }] }
  4. Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {

    “rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
  5. Why HATEOAS • ϦϯΫ͕Θ͔Ε͹ CRUD ͕Ͱ͖Δ • ϏδωεϩδοΫͷྲྀग़Λආ͚Δ
 ΫϥΠΞϯτ͸ϦϯΫͷ༗ແͰ൑அ •

    ϖʔδϯάͷදݱʹ໎Θͳ͍ { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ { “rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
  6. Links & Affordances { "name": "Dai Yamasaki", "role": "Developer", "_links":

    { "self": { "href": “/employees/0" }, "employees": { "href": "/employees" } }, "_templates": { "default": { "method": "put", "properties": [ { "name": "name", "required": true }, { "name": "role" } ] }, "partiallyUpdateEmployee": { "method": "patch", "properties": [ { "name": "name" }, { "name": "role" } …
  7. Links & Affordances @GetMapping("/employees/{id}") public EntityModel<Employee> findOne(@PathVariable Integer id) {

    Employee employee = employeeRepository.findOneById(id); // ࣗ෼ࣗ਎ "self" ͷϦϯΫΛ࡞੒ WebMvcEmployeeController controller = methodOn(WebMvcEmployeeController.class); Link findOneLink = linkTo(controller.findOne(id)).withSelfRel(); // Affordance ΛؚΊͨ৘ใΛฦ͢ return new EntityModel<>( employee, findOneLink .andAffordance( afford(controller.updateEmployee(null, id))) .andAffordance( afford(controller.partiallyUpdateEmployee(null, id)))); }
  8. 4FQBSBUFSFTPVSDF Links & Affordances { "_links": { "my-app:payment": {...}, "curies":

    [ { "name": "my-app", "href": "http://hoge.com/docs/{rel}", "templated": true }] } } IUUQNZBQQDPNEPDTQBZNFOU
  9. *OMJOFSFTPVSDF { ... "_templates": { "default": { "method": "put", "properties":

    [{ "name": "number", "regex": "[0-9]{16}" }] } } } Links & Affordances
  10. 5SBWFSTPO @Test void traverson() { Traverson traverson = new Traverson(baseUri,

    MediaTypes.HAL_JSON); ParameterizedTypeReference<EntityModel<Actor>> typeReference = new ParameterizedTypeReference<EntityModel<Actor>>() {}; EntityModel<Actor> result = traverson.follow("movies", "movie", “actor") .toObject(typeReference); assertThat(result.getContent().name) .isEqualTo("Dwayne Douglas Johnson"); }
  11. 5SBWFSTPO { "_links": { "movie": { "href": "http://localhost:8080/movies/63e0c973-1606-4fe7-b4e3-0de03d2e0c06" } }

    } { "title": "Fast & Furious Presents: Hobbs & Shaw", "_links": { "actor": { "href": "http://localhost:8080/actors/f58ebb17-abd8-48fb-b06c-5a912251631c" } } } { "name": "Dwayne Douglas Johnson" } NPWJFT EntityModel<Actor> result = traverson.follow("movies", "movie", “actor") .toObject(typeReference); NPWJF BDUPS