Slide 1

Slide 1 text

4QSJOH)"5&0"4 %BJ:BNBTBLJ 5BHCBOHFST *OD

Slide 2

Slide 2 text

Who am I •Dai Yamasaki •Born to develop •I k6o
 dislike Tokyo

Slide 3

Slide 3 text

r,BNFIBNFIB*** Χ΢ΠέΞΦ΢Ϧ l6B.BVLF&BPLBb⒖JOBJLB1POP
 ʢʮ౔஍ͷੜ໋ʢ㲈ओݖʣ͸ਖ਼ٛʹΑͬͯӬଓ͢Δʯʣz

Slide 4

Slide 4 text

Spring HATEOAS - Hypermedia APIs with Spring https://www.youtube.com/watch?v=o4cc6KzNrpI&list=PLAdzTan_eSPRlQ8t4TU5c-AB4SHV939M6&index=46

Slide 5

Slide 5 text

Who use HATEOAS

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Hypermedia -JOL -JOL -JOL -JOL

Slide 8

Slide 8 text

REST ੒ख़౓ • Level 0
 ҰͭͷURLͱҰͭͷHTTPϝιου • Level 1
 ҟͳΔURLͱҰͭͷHTTPϝιου • Level 2
 ҟͳΔURLͱҟͳΔHTTPϝιου • Level 3
 APIͷϨεϙϯεʹϋΠύʔϦϯΫ৘ใΛ࣋ͭ

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

Hypermedia
 As
 The
 Engine
 Of
 Application
 State H
 A
 T
 E
 O
 A
 S HATEOAS

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Why HATEOAS • ϦϯΫ͕Θ͔Ε͹ CRUD ͕Ͱ͖Δ • ϏδωεϩδοΫͷྲྀग़Λආ͚Δ
 ΫϥΠΞϯτ͸ϦϯΫͷ༗ແͰ൑அ • ϖʔδϯάͷදݱʹ໎Θͳ͍ { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ { “rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }

Slide 13

Slide 13 text

Spring HATEOAS

Slide 14

Slide 14 text

Representation Model

Slide 15

Slide 15 text

Representation Model

Slide 16

Slide 16 text

Links & Affordance

Slide 17

Slide 17 text

ΞϑΥʔμϯεʢaffordanceʣͱ͸ɺ ؀ڥ͕ಈ෺ʹରͯ͠༩͑Δʮҙຯʯͷ͜ͱͰ͋Δɻ ΞϝϦΧͷ஌֮৺ཧֶऀδΣʔϜζɾJɾΪϒιϯʹΑΔ଄ޠͰ͋Γɺ ੜଶޫֶɺੜଶ৺ཧֶͷجఈత֓೦Ͱ͋Δɻ ʮ༩͑Δɺఏڙ͢Δʯͱ͍͏ҙຯͷӳޠ afford ͔Β଄ΒΕͨɻ Affordances

Slide 18

Slide 18 text

Affordance https://www.amazon.co.jp/%E3%82%B5%E3%83%B3%E3%82%A2%E3%83%BC%E3%83%88-%E3%81%8A%E3%82%82%E3%81%97%E3%82%8D%E9%A3%9F%E5%99%A8-4%E6%96%87%E5%AD%97%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC- %E3%83%9E%E3%82%B0%E3%82%AB%E3%83%83%E3%83%97-SAN1858/dp/B003NEPOTW

Slide 19

Slide 19 text

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" } …

Slide 20

Slide 20 text

Links & Affordances @GetMapping("/employees/{id}") public EntityModel 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)))); }

Slide 21

Slide 21 text

4FQBSBUFSFTPVSDF Links & Affordances { "_links": { "my-app:payment": {...}, "curies": [ { "name": "my-app", "href": "http://hoge.com/docs/{rel}", "templated": true }] } } IUUQNZBQQDPNEPDTQBZNFOU

Slide 22

Slide 22 text

*OMJOFSFTPVSDF { ... "_templates": { "default": { "method": "put", "properties": [{ "name": "number", "regex": "[0-9]{16}" }] } } } Links & Affordances

Slide 23

Slide 23 text

.FEJB5ZQFT

Slide 24

Slide 24 text

5SBWFSTPO @Test void traverson() { Traverson traverson = new Traverson(baseUri, MediaTypes.HAL_JSON); ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() {}; EntityModel result = traverson.follow("movies", "movie", “actor") .toObject(typeReference); assertThat(result.getContent().name) .isEqualTo("Dwayne Douglas Johnson"); }

Slide 25

Slide 25 text

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 result = traverson.follow("movies", "movie", “actor") .toObject(typeReference); NPWJF BDUPS

Slide 26

Slide 26 text

0UIFS • RepresentationModelAssembler • I18N support • LinkRelationProvider

Slide 27

Slide 27 text

5IBOLT