Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Spring HATEOAS
Search
Dai Yamasaki
November 15, 2019
Programming
0
890
Spring HATEOAS
JSUG勉強会 2019その10 SpringOne Platform 2019報告会
Dai Yamasaki
November 15, 2019
Tweet
Share
Other Decks in Programming
See All in Programming
document.write再考
brn
5
2.5k
オブジェクト指向は必要なのか / Is object-oriented needed?
kishida
27
19k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
170
RubyVM を PHP で実装する 〜Hello World を出力するまで〜
memory1994
PRO
1
490
上手な探索的テストとその上達方法について
matsu802
4
660
マイ隙間家具OSSたちのご紹介
karupanerura
2
160
Cloud RunとCloud PubSubでサーバレスなデータ基盤2024 with Terraform / Cloud Run and PubSub with Terraform
shinyorke
7
1.9k
Kotlinを用いたDSL的な設計手法と使用上の注意
kohii00
3
530
Open Source Swift Workshop - Foundation and first party libraries
ikesyo
0
270
PHPerKaigi 2024〜10年以上動いているレガシーなバッチシステムを Kubernetes(Amazon EKS) に移行する取り組み〜
tshinowpub
1
220
Building a Smaller App Binary
kateinoigakukun
2
220
AppDeveloperCon 2024 EU: Building polyglot developer experiences in 2024
salaboy
0
380
Featured
See All Featured
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
1
1.2k
Become a Pro
speakerdeck
PRO
8
4.4k
Writing Fast Ruby
sferik
619
59k
The Brand Is Dead. Long Live the Brand.
mthomps
48
22k
Documentation Writing (for coders)
carmenintech
59
3.8k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
19
1.6k
Why Our Code Smells
bkeepers
PRO
330
56k
RailsConf 2023
tenderlove
0
510
Clear Off the Table
cherdarchuk
82
310k
StorybookのUI Testing Handbookを読んだ
zakiyama
10
4.5k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
657
120k
A Modern Web Designer's Workflow
chriscoyier
689
190k
Transcript
4QSJOH)"5&0"4 %BJ:BNBTBLJ 5BHCBOHFST *OD
Who am I •Dai Yamasaki •Born to develop •I k6o
dislike Tokyo
r,BNFIBNFIB*** ΧΠέΞΦϦ l6B.BVLF&BPLBb⒖JOBJLB1POP ʢʮͷੜ໋ʢ㲈ओݖʣਖ਼ٛʹΑͬͯӬଓ͢Δʯʣz
Spring HATEOAS - Hypermedia APIs with Spring https://www.youtube.com/watch?v=o4cc6KzNrpI&list=PLAdzTan_eSPRlQ8t4TU5c-AB4SHV939M6&index=46
Who use HATEOAS
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
Hypermedia -JOL -JOL -JOL -JOL
REST ख़ • Level 0 ҰͭͷURLͱҰͭͷHTTPϝιου • Level 1 ҟͳΔURLͱҰͭͷHTTPϝιου
• Level 2 ҟͳΔURLͱҟͳΔHTTPϝιου • Level 3 APIͷϨεϙϯεʹϋΠύʔϦϯΫใΛ࣋ͭ
Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {
"rel":"customer", "href":"...", }, { "rel":"self", "href":"...", }] }
Hypermedia As The Engine Of Application State H A T
E O A S HATEOAS
Hypermedia + REST { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ {
“rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
Why HATEOAS • ϦϯΫ͕Θ͔Ε CRUD ͕Ͱ͖Δ • ϏδωεϩδοΫͷྲྀग़Λආ͚Δ ΫϥΠΞϯτϦϯΫͷ༗ແͰஅ •
ϖʔδϯάͷදݱʹ໎Θͳ͍ { "orderID":…, "productID”:…, "quantity":…, "orderValue":…, "_links":[ { “rel":"cancel", "href":"...", }, { "rel":"self", "href":"...", }] }
Spring HATEOAS
Representation Model
Representation Model
Links & Affordance
ΞϑΥʔμϯεʢaffordanceʣͱɺ ڥ͕ಈʹରͯ͠༩͑Δʮҙຯʯͷ͜ͱͰ͋Δɻ ΞϝϦΧͷ֮৺ཧֶऀδΣʔϜζɾJɾΪϒιϯʹΑΔޠͰ͋Γɺ ੜଶޫֶɺੜଶ৺ཧֶͷجఈత֓೦Ͱ͋Δɻ ʮ༩͑Δɺఏڙ͢Δʯͱ͍͏ҙຯͷӳޠ afford ͔ΒΒΕͨɻ Affordances
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
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" } …
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)))); }
4FQBSBUFSFTPVSDF Links & Affordances { "_links": { "my-app:payment": {...}, "curies":
[ { "name": "my-app", "href": "http://hoge.com/docs/{rel}", "templated": true }] } } IUUQNZBQQDPNEPDTQBZNFOU
*OMJOFSFTPVSDF { ... "_templates": { "default": { "method": "put", "properties":
[{ "name": "number", "regex": "[0-9]{16}" }] } } } Links & Affordances
.FEJB5ZQFT
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"); }
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
0UIFS • RepresentationModelAssembler • I18N support • LinkRelationProvider
5IBOLT