SlideShare a Scribd company logo
Spring Data REST
と
Spring Cloud Contract
Tagbangers, Inc.
#sf_25 #アンケート
© Tagbangers, Inc. 1
自己紹介
小川岳史
Spring Lover 10 years
山﨑大
わさもん
© Tagbangers, Inc. 2
本日のメニュー
• 背景
• Spring Data REST
• HATEOAS
• Spring Cloud Contract
• CDC
• Pact
© Tagbangers, Inc. 3
背景
• SPA 時代
• よりリッチな UI 表現のために Thymeleaf から Angular などへ
• ビジネスロジックの実装が UI 側にも必要なり…
Browser
Application • ビジネスロジック
• CRUD
Browser
Application • ビジネスロジック
• CRUD
• ビジネスロジック
DB
DB
© Tagbangers, Inc. 4
工程やチーム構成の変化
BackendFrontend
ex. Angular ex. Spring Boot
Frontend Team Backend Team
User
repo repo
CI/CDCI/CD
code
push
code
push
artifactartifact
別々のデプロイ環境
別々のチーム
別々のレポジトリ
別々のリリースサイクル
© Tagbangers, Inc. 5
どの URI にアクセスすれば
いいの?
どんなフォーマットでデー
タが取得できるの?
更新できる条件ってなんな
の??
そこで発生してきた課題
開発初期段階
© Tagbangers, Inc. 6
API の仕様が変更されて UI がバグったんだけど〜
そこで発生してきた課題
リリース後のバージョンアップで
© Tagbangers, Inc. 7
解決策
どの URI にアクセスすればいいの?
どんなフォーマットでデータが
取得できるの?
更新できる条件ってなんなの??
API の仕様が変更されて
UI がバグったんだけど〜
Spring Data REST
Spring エコシステムをフル活用!
標準化 + 自動生成 別々に進化できる仕組み
Spring Cloud Contract
Spring Data REST
✓ 標準化 + 自動生成
© Tagbangers, Inc. 9
残念な実装
class ReservationService {
Reservation getReservation(long id) {
return this.reservationRepository.findById(id);
}
Reservation createReservation(Reservation reservation) {
return this.reservationRepository.save(reservation);
}
}
© Tagbangers, Inc. 10
Spring Data REST とは
Entity
GET /items
GET /items/search
GET / items/1
POST /items
PUT /items/1
PATCH /items/1
DELETE /items/1
…
Item ItemRepository
REST スタイルな API エンドポイント
URL 設計に迷わない
Repository
© Tagbangers, Inc. 11
Spring Data REST の始め方
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
© Tagbangers, Inc. 12
Entity
Repository
@Entity
public class Order {
private Long id;
private Location location;
private LocalDateTime orderedDate;
private Status status;
}
public interface OrderRepository
extends PagingAndSortingRepository<Order, Long> {
}
© Tagbangers, Inc. 13
. ____ _ __ _ _
/ / ___'_ __ _ _(_)_ __ __ _    
( ( )___ | '_ | '_| | '_ / _` |    
/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |___, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.6.RELEASE)
...
Mapped "{[/ || ],methods=[HEAD],produces=[application/hal+json || application/json]}" ...
Mapped "{[/ || ],methods=[GET],produces=[application/hal+json || application/json]}" ...
Mapped "{[/ || ],methods=[OPTIONS],produces=[application/hal+json || application/json]}" ...
Mapped "{[/{repository}],methods=[OPTIONS],produces=[application/hal+json || application/json]}" ...
Mapped "{[/{repository}],methods=[HEAD],produces=[application/hal+json || application/json]}" ...
Mapped "{[/{repository}],methods=[GET],produces=[application/hal+json || application/json]}" ...
Mapped "{[/{repository}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}" ...
Mapped "{[/{repository}],methods=[POST],produces=[application/hal+json || application/json]}" ...
Mapped "{[/{repository}/{id}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}],methods=[HEAD],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}],methods=[GET],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}],methods=[PUT],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}],methods=[PATCH],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}],methods=[DELETE],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}/{property}],methods=[GET],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}/{property}/{propertyId}],methods=[GET],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}/{property}],methods=[DELETE],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/{id}/{property}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}"
Mapped "{[/{repository}/{id}/{property}],methods=[PATCH || PUT || POST],consumes=[application/json || application/x-spring-data-compact+json || text/uri-list], ...
Mapped "{[/{repository}/{id}/{property}/{propertyId}],methods=[DELETE],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/search],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/search],methods=[HEAD],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/search],methods=[GET],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/search/{search}],methods=[GET],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/search/{search}],methods=[GET],produces=[application/x-spring-data-compact+json]}"
Mapped "{[/{repository}/search/{search}],methods=[OPTIONS],produces=[application/hal+json || application/json]}"
Mapped "{[/{repository}/search/{search}],methods=[HEAD],produces=[application/hal+json || application/json]}"
Mapped "{[/profile],methods=[OPTIONS]}"
Mapped "{[/profile],methods=[GET]}"
Mapped "{[/profile/{repository}],methods=[GET],produces=[application/alps+json || */*]}"
Mapped "{[/profile/{repository}],methods=[OPTIONS],produces=[application/alps+json]}"
Mapped "{[/profile/{repository}],methods=[GET],produces=[application/schema+json]}"
Mapped "{[/ || ],methods=[GET],produces=[text/html]}"
Mapped "{[/browser],methods=[GET]}"
自動的にエンドポイントが登録されている
/repository…
© Tagbangers, Inc. 14
{
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "http://localhost:8080/people/1"
}
}
}
$ curl http://localhost:8080/people/1
LINK 部
DATA 部
© Tagbangers, Inc. 15
HATEOAS
• Hypermedia as the Engine of Application State
• データ部の他にリンク情報が追加され、関連するリソースをたどることができる
• Spring Data REST のリクエスト・レスポンスボディ部のフォーマットは HATEOAS に準拠
• Spring HATEOAS は独立したライブラリでこれだけ使うこともできる
© Tagbangers, Inc. 16
フロント側で ID を取り出して個別に
URL を組み立てる必要がない
ページング情報も
$ curl http://localhost:8080/people
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/people{?page,size,sort}",
"templated" : true
},
"search" : {
"href" : "http://localhost:8080/people/search"
}
},
"_embedded" : {
"persons" : [ {
"firstName" : "Frodo",
"lastName" : "Baggins",
"_links" : {
"self" : {
"href" : "http://localhost:8080/people/1"
}
}
} ]
},
"page" : {
"size" : 20,
"totalElements" : 1,
"totalPages" : 1,
"number" : 0
}
}
HATEOAS にのっかることでボディ部の
フォーマットも悩まない
© Tagbangers, Inc. 17
{
"description": "iPhone",
"status": "IN_PROGRESS",
"_links": {
"self": {
"href": "http://localhost:8080/orders/4"
},
"orders": {
"href": "http://localhost:8080/orders"
},
"cancel": {
"href": "http://localhost:8080/orders/4/cancel"
},
"complete": {
"href": "http://localhost:8080/orders/4/complete"
}
}
if ( order.status == PENDING || order.status == PAID ) {
showCancelButton
}
© Tagbangers, Inc. 18
ビジネスロジックの流出を最小限
に
キャンセル判定
ロジック
キャンセル判定
ロジック
キャンセル判定
ロジック
© Tagbangers, Inc. 19
自動生成されて簡単!とはいえ…
• とにかく簡単だけど…
• Spring Data REST だけでは完成しない
• 基本的に CRUD のみ
• ビジネスロジックが必要な場合は拡張する
Controller
Service
Repository
Database
ここは自分で書く
Spring Data RESTが
よしなに
© Tagbangers, Inc. 20
Repository
Spring
Data
REST
@RepositoryRest
Controller
Service
@Controller
@RestController
Endpoint
Endpoint
Endpoint
Domain
Model
ビジネスロジックの実装パターン
EventHandler
© Tagbangers, Inc. 21
JSON Schema
• JSON Schema から TypeScript のコードの自動生成
TypescriptJson schema
自動生成
curl -H 'Accept:application/schema+json' http://localhost:8080/profile/reservations
{
"title" : "Reservation",
"properties" : {
"date" : {
"title" : "Date",
"readOnly" : false,
"type" : "string",
"format" : "date-time"
},
"name" : {
"title" : "Name",
"readOnly" : false,
"type" : "string"
}
},
"definitions" : { },
"type" : "object",
"$schema" : "http://json-schema.org/draft-04/schema#"
}
export type Date = string;
export type Name = string;
export interface Reservation {
date?: Date;
name?: Name;
[k: string]: any;
}
© Tagbangers, Inc. 22
Admin over Spring Data REST
User UI Admin UI
Spring
Data
REST
Manual
Impl
DB
© Tagbangers, Inc. 23
全文検索 over Spring Data REST
UI
Elastic
Search
Spring
Data
REST
Hibernate
Search
DB
Custom
Repository
Impl
© Tagbangers, Inc. 24
マルチテナント over Spring Data REST
UI
Spring
Data
REST
Repository DBHibernate
Spring
Security
Authentication
Event Listener
Filter
Tenant
© Tagbangers, Inc. 25
ポイント
 Spring Data REST を活用してボイラープレートコードを削減する
 REST や HATEOAS の流行りの仕様を活用する
チーム間のコミュニケーションをフォーマット的なことではなく、
よりビジネス的にフォーカスしたいポイントに絞る!!
© Tagbangers, Inc. 26
ポイント
BackendFrontend
ex. Angular ex. Spring Boot
Frontend Team Backend Team
User
repo repo
CI/CDCI/CD
code
push
code
push
artifactartifact
Spring Data REST
Spring HATEOAS
Spring Cloud Contract
でさくっと行う
Consumer Driven Contract
with Pact
別々に進化できる仕組み
© Tagbangers, Inc. 28
工程やチーム構成の変化
BackendFrontend
ex. Angular ex. Spring Boot
Frontend Team Backend Team
User
repo repo
CI/CDCI/CD
code
push
code
push
artifactartifact
別々のデプロイ環境
別々のチーム
別々のレポジトリ
別々のリリースサイクル
© Tagbangers, Inc. 29
Test Pyramid
https://martinfowler.com/bliki/TestPyramid.html
© Tagbangers, Inc. 30
モック に置き換える
HTTP
© Tagbangers, Inc. 31
モック に置き換える
その モック 意味がありますか?
• インターフェースは正しい??
• 連携するサービスが変更されたら?
• だれがメンテナンスするの?
© Tagbangers, Inc. 32
Micro service architecture
Microservice MicroserviceMicroservice
UI
Microservice
モックモックモックモックモックモックモックモック
© Tagbangers, Inc. 33
Spring Cloud Contract
Spring Cloud Contract is an
umbrella project holding
solutions that help users in
successfully implementing
the Consumer Driven
Contracts approach.
© Tagbangers, Inc. 34
Pact
Pact is a contract testing tool. Contract
testing is a way to ensure that services
(such as an API provider and a client) can
communicate with each other. Without
contract testing, the only way to know that
services can communicate is by using
expensive and brittle integration tests
© Tagbangers, Inc. 35
Contract
• 契約はインターフェース定義のようなもの
• API 仕様書の内容
• Provider が契約を守ることを約束する
Contract
Consumer
Consumer and provider are
both agreed with the sentence
below.. for example we agreed with
on the basis of the Provider’s REST
API, that is created hy
Provider
Test ✔
Test ✔
Spring Cloud Contract + Pact
で
Consumer Driven Contract
© Tagbangers, Inc. 37
CDC ステップ
1. テスト書く
2. Contract(Pact file) を自動生成
3. Pact Broker に Pact file を publish
Consumer
1. Pact Broker から Contract(Pact file) を取得
2. Test を自動生成(Spring Cloud Contract )
3. モック を自動生成(Spring Cloud Contract)
Provider
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
© Tagbangers, Inc. 38
1. テストを書く
beforeAll ((done) => {
provider = new PactWeb({
consumer: ‘sample-client-tenant',
provider: ‘sapmle-server-tenant',
port: 1234,
host: '127.0.0.1'
});
});
前準備 1
© Tagbangers, Inc. 39
1. テストを書く
beforeAll((done) => {
provider.addInteraction({
uponReceiving: 'a request for hello',
withRequest: {
method: 'GET',
path: '/hello'
},
willRespondWith: {
status: 200,
headers: {
'Content-Type': 'application/hal+json;charset=UTF-8'
},
body: {
reply: 'Hello'
}
}
}).then(done, done.fail);
});
前準備 2
© Tagbangers, Inc. 40
1. テストを書く
it('should', (done) => {
const greetingService: GreetingService =
TestBed.get(GreetingTypeService);
greetingService.hello().subscribe(response => {
expect(response).toEqual({reply: 'Hello'});
done();
}, error => {
done.fail(error);
});
});
テスト
/hello に Get リクエスト
© Tagbangers, Inc. 41
CDC ステップ
1. テスト書く
2. Contract(Pact file) を自動生成
3. Pact Broker に Pact file を publish
1. Pact Broker から Contract(Pact file) を取得
2. Test を自動生成(Spring Cloud Contract )
3. モック を自動生成(Spring Cloud Contract)
Consumer
Provider
© Tagbangers, Inc. 42
2. Pact file ( Contract )
Pact file
...
"interactions": [
{
"description": "a request for hello",
"request": {
"method": "GET",
"path": "/hello"
},
"response": {
"status": 200,
"headers": {
"Content-Type":
"application/hal+json;charset=UTF-8"
...
© Tagbangers, Inc. 43
CDC ステップ
1. テスト書く
2. Contract(Pact file) を自動生成
3. Pact Broker に Pact file を publish
1. Pact Broker から Contract(Pact file) を取得
2. Test を自動生成(Spring Cloud Contract )
3. モック を自動生成(Spring Cloud Contract)
Contract を共有するためのアプリ
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
Consumer
Provider
© Tagbangers, Inc. 44
Pact Broker
https://github.com/pact-foundation/pact_broker
© Tagbangers, Inc. 45
Pact Broker
https://github.com/pact-foundation/pact_broker
© Tagbangers, Inc. 46
CDC ステップ
1. テスト書く
2. Contract(Pact file) を自動生成
3. Pact Broker に Pact file を publish
1. Pact Broker から Contract(Pact file) を取得
2. Test を自動生成(Spring Cloud Contract )
3. モック を自動生成(Spring Cloud Contract)
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
Consumer
Provider
© Tagbangers, Inc. 47
CDC ステップ
1. テスト書く
2. Contract(Pact file) を自動生成
3. Pact Broker に Pact file を publish
1. Pact Broker から Contract(Pact file) を取得
2. Test を自動生成(Spring Cloud Contract )
3. モック を自動生成(Spring Cloud Contract)
ビルド時にテストを生成 + テスト実行
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
Consumer
Provider
© Tagbangers, Inc. 48
CDC ステップ
1. テスト書く
2. Contract(Pact file) を自動生成
3. Pact Broker に Pact file を publish
1. Pact Broker から Contract(Pact file) を取得
2. Test を自動生成(Spring Cloud Contract )
3. モック を自動生成(Spring Cloud Contract)
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
Consumer
Provider
© Tagbangers, Inc. 49
CDC ステップ
1. テスト書く
2. Contract(Pact file) を自動生成
3. Pact Broker に Pact file を publish
1. Pact Broker から Contract(Pact file) を取得
2. Test を自動生成(Spring Cloud Contract )
3. モック を自動生成(Spring Cloud Contract)
成果物としてWireMockの定義ファイルができる
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
Consumer
Provider
© Tagbangers, Inc. 50
APIが実装されたか知りたい
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
Broker のステータス確認で対応状況を把握
© Tagbangers, Inc. 51
Pact Broker
https://github.com/pact-foundation/pact_broker
© Tagbangers, Inc. 52
破壊的な API の実装の変更
https://github.com/pact-foundation/pact_broker/wiki/Webhooks
テストが通らないので破壊的な変更だとわかる!
© Tagbangers, Inc. 53
使用されている API がわかる!
https://github.com/pact-foundation/pact_broker
まとめ
© Tagbangers, Inc. 55
まとめ
BackendFrontend
ex. Angular ex. Spring Boot
Frontend Team Backend Team
User
repo repo
CI/CDCI/CD
code
push
code
push
artifactartifact
Spring Data REST
Spring HATEOAS
Spring Cloud Contract

More Related Content

What's hot (20)

PPTX
メールシステムのおはなし #Mailerstudy
Yasuhiro Araki, Ph.D
 
PDF
20210127 今日から始めるイベントドリブンアーキテクチャ AWS Expert Online #13
Amazon Web Services Japan
 
PPTX
Redisの特徴と活用方法について
Yuji Otani
 
PDF
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
Amazon Web Services Japan
 
PPTX
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
 
PDF
DynamoDBの初心者に伝えたい初めて触るときの勘所
Ryo Sasaki
 
PPTX
Redis勉強会資料(2015/06 update)
Yuji Otani
 
PDF
NetflixにおけるPresto/Spark活用事例
Amazon Web Services Japan
 
PDF
Keycloak拡張入門
Hiroyuki Wada
 
PDF
「なにをどこまでやれば?」OWASP SAMMが導く開発セキュリティ強化戦略
Riotaro OKADA
 
PDF
ゲームサーバ開発現場の考え方
Daisaku Mochizuki
 
PDF
SPA時代のOGPとの戦い方
Yoichi Toyota
 
PPTX
がっつりMongoDB事例紹介
Tetsutaro Watanabe
 
PDF
OpenID ConnectとAndroidアプリのログインサイクル
Masaru Kurahayashi
 
PDF
Active Directory 侵害と推奨対策
Yurika Kakiuchi
 
PDF
Akkaで分散システム入門
Shingo Omura
 
PDF
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
Yahoo!デベロッパーネットワーク
 
PDF
OpenTelemetryを用いたObservability基礎の実装 with AWS Distro for OpenTelemetry(Kuberne...
NTT DATA Technology & Innovation
 
PDF
Apache Sparkに手を出してヤケドしないための基本 ~「Apache Spark入門より」~ (デブサミ 2016 講演資料)
NTT DATA OSS Professional Services
 
PPTX
NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした
toshi_pp
 
メールシステムのおはなし #Mailerstudy
Yasuhiro Araki, Ph.D
 
20210127 今日から始めるイベントドリブンアーキテクチャ AWS Expert Online #13
Amazon Web Services Japan
 
Redisの特徴と活用方法について
Yuji Otani
 
ゲームアーキテクチャパターン (Aurora Serverless / DynamoDB)
Amazon Web Services Japan
 
SPAセキュリティ入門~PHP Conference Japan 2021
Hiroshi Tokumaru
 
DynamoDBの初心者に伝えたい初めて触るときの勘所
Ryo Sasaki
 
Redis勉強会資料(2015/06 update)
Yuji Otani
 
NetflixにおけるPresto/Spark活用事例
Amazon Web Services Japan
 
Keycloak拡張入門
Hiroyuki Wada
 
「なにをどこまでやれば?」OWASP SAMMが導く開発セキュリティ強化戦略
Riotaro OKADA
 
ゲームサーバ開発現場の考え方
Daisaku Mochizuki
 
SPA時代のOGPとの戦い方
Yoichi Toyota
 
がっつりMongoDB事例紹介
Tetsutaro Watanabe
 
OpenID ConnectとAndroidアプリのログインサイクル
Masaru Kurahayashi
 
Active Directory 侵害と推奨対策
Yurika Kakiuchi
 
Akkaで分散システム入門
Shingo Omura
 
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
Yahoo!デベロッパーネットワーク
 
OpenTelemetryを用いたObservability基礎の実装 with AWS Distro for OpenTelemetry(Kuberne...
NTT DATA Technology & Innovation
 
Apache Sparkに手を出してヤケドしないための基本 ~「Apache Spark入門より」~ (デブサミ 2016 講演資料)
NTT DATA OSS Professional Services
 
NginxとLuaを用いた動的なリバースプロキシでデプロイを 100 倍速くした
toshi_pp
 

Similar to Spring data-rest-and-spring-cloud-contract (20)

PDF
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Rakuten Group, Inc.
 
PDF
Spring Framework ふりかえりと4.3新機能
kimulla
 
PDF
REST with Spring Boot #jqfk
Toshiaki Maki
 
PDF
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Toshiaki Maki
 
PDF
Spring Fest 2018 Spring Bootで作るRESTful Web Service
WataruOhno
 
PPTX
JSUG SpringOnePlatform 2016報告会 Case study2 - feed back - springoneplatform
Takahiro Fujii
 
PPTX
Spring I/O 2015 報告
Takuya Iwatsuka
 
PDF
IntelliJ IDEAとKotlinで作るSpring 5アプリケーション
CASAREAL, Inc.
 
PPTX
Spring oneを経験してよりよいwebサービスを作るために僕らが取り組むこと(document編)(SpringRESTDocs)
Takahiro Fujii
 
PDF
Jjug springセッション
Yuichi Hasegawa
 
PDF
Spring Data in a Nutshell
Tsuyoshi Miyake
 
PDF
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
Toshiaki Maki
 
PDF
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
ssuser070fa9
 
PDF
Java クライント実装におけるAPIスタイル頂上決戦! 野良REST vs GraphQL vs OData vs OpenAPI (Swagger)
Kazuya Sugimoto
 
PDF
Spring Initializrをハックする-カスタマイズを通してその内部実装を覗く
apkiban
 
PPTX
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
Koichi Sakata
 
PDF
Spring3.1概要x di
Yuichi Hasegawa
 
PDF
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Toru Kawamura
 
PDF
SpringOneでの3⽇間とSpring 5.1最新情報
CASAREAL, Inc.
 
PDF
Spring I/O 2018 報告 RESTDocs RAML, Cloud Contract
Takuya Iwatsuka
 
Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり
Rakuten Group, Inc.
 
Spring Framework ふりかえりと4.3新機能
kimulla
 
REST with Spring Boot #jqfk
Toshiaki Maki
 
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Toshiaki Maki
 
Spring Fest 2018 Spring Bootで作るRESTful Web Service
WataruOhno
 
JSUG SpringOnePlatform 2016報告会 Case study2 - feed back - springoneplatform
Takahiro Fujii
 
Spring I/O 2015 報告
Takuya Iwatsuka
 
IntelliJ IDEAとKotlinで作るSpring 5アプリケーション
CASAREAL, Inc.
 
Spring oneを経験してよりよいwebサービスを作るために僕らが取り組むこと(document編)(SpringRESTDocs)
Takahiro Fujii
 
Jjug springセッション
Yuichi Hasegawa
 
Spring Data in a Nutshell
Tsuyoshi Miyake
 
SpringOne 2GX 2014 参加報告 & Spring 4.1について #jsug
Toshiaki Maki
 
【Spring fest 2019】徹底解剖Spring MVCアーキテクチャー
ssuser070fa9
 
Java クライント実装におけるAPIスタイル頂上決戦! 野良REST vs GraphQL vs OData vs OpenAPI (Swagger)
Kazuya Sugimoto
 
Spring Initializrをハックする-カスタマイズを通してその内部実装を覗く
apkiban
 
JJUG CCC 2017 Spring Seasar2からSpringへ移行した俺たちのアプリケーションがマイクロサービスアーキテクチャへ歩み始めた
Koichi Sakata
 
Spring3.1概要x di
Yuichi Hasegawa
 
Hypermedia: The Missing Element to Building Adaptable Web APIs in Rails (増補日本語版)
Toru Kawamura
 
SpringOneでの3⽇間とSpring 5.1最新情報
CASAREAL, Inc.
 
Spring I/O 2018 報告 RESTDocs RAML, Cloud Contract
Takuya Iwatsuka
 
Ad

More from Takeshi Ogawa (6)

PDF
今こそ知りたい Spring Data
Takeshi Ogawa
 
PPTX
Spring Cloud Gateway on Kubernetes
Takeshi Ogawa
 
PDF
Spring I/O 2019 Recap - Moduliths
Takeshi Ogawa
 
PPTX
さくっと作るSpring入門 with Google Home
Takeshi Ogawa
 
PPTX
Spring と TDD
Takeshi Ogawa
 
PPTX
さくっと理解するSpring bootの仕組み
Takeshi Ogawa
 
今こそ知りたい Spring Data
Takeshi Ogawa
 
Spring Cloud Gateway on Kubernetes
Takeshi Ogawa
 
Spring I/O 2019 Recap - Moduliths
Takeshi Ogawa
 
さくっと作るSpring入門 with Google Home
Takeshi Ogawa
 
Spring と TDD
Takeshi Ogawa
 
さくっと理解するSpring bootの仕組み
Takeshi Ogawa
 
Ad

Recently uploaded (9)

PDF
安尾 萌, 藤代 裕之, 松下 光範. 協調的情報トリアージにおけるコミュニケーションの影響についての検討, 第11回データ工学と情報マネジメントに関する...
Matsushita Laboratory
 
PDF
論文紹介:AutoPrompt: Eliciting Knowledge from Language Models with Automatically ...
Toru Tamaki
 
PDF
安尾 萌, 松下 光範. 環境馴致を計量可能にするための試み,人工知能学会第4回仕掛学研究会, 2018.
Matsushita Laboratory
 
PDF
SIG-AUDIO 2025 Vol.02 オンラインセミナー 「GDC2025 オーディオ報告会」SIG-Audio_GDC2025_報告会資料_渡辺さ...
IGDA Japan SIG-Audio
 
PDF
API認可を支えるKeycloakの基本と設計の考え方 ~ OAuth/OIDCによるAPI保護のベストプラクティス ~
Hitachi, Ltd. OSS Solution Center.
 
PDF
安尾 萌, 北村 茂生, 松下 光範. 災害発生時における被害状況把握を目的とした情報共有システムの基礎検討, 電子情報通信学会HCGシンポジウム2018...
Matsushita Laboratory
 
PDF
SIG-AUDIO 2025 Vol.02 オンラインセミナー 「GDC2025 オーディオ報告会」SIG-Audio_GDC2024_報告会資料_増野さ...
IGDA Japan SIG-Audio
 
PDF
マルチAIエージェントの産業界での実践に向けたオープンソース活動の展望 - Japan Regional User Group (RUG) Meet-Up
Kosaku Kimura
 
PDF
論文紹介:Unbiasing through Textual Descriptions: Mitigating Representation Bias i...
Toru Tamaki
 
安尾 萌, 藤代 裕之, 松下 光範. 協調的情報トリアージにおけるコミュニケーションの影響についての検討, 第11回データ工学と情報マネジメントに関する...
Matsushita Laboratory
 
論文紹介:AutoPrompt: Eliciting Knowledge from Language Models with Automatically ...
Toru Tamaki
 
安尾 萌, 松下 光範. 環境馴致を計量可能にするための試み,人工知能学会第4回仕掛学研究会, 2018.
Matsushita Laboratory
 
SIG-AUDIO 2025 Vol.02 オンラインセミナー 「GDC2025 オーディオ報告会」SIG-Audio_GDC2025_報告会資料_渡辺さ...
IGDA Japan SIG-Audio
 
API認可を支えるKeycloakの基本と設計の考え方 ~ OAuth/OIDCによるAPI保護のベストプラクティス ~
Hitachi, Ltd. OSS Solution Center.
 
安尾 萌, 北村 茂生, 松下 光範. 災害発生時における被害状況把握を目的とした情報共有システムの基礎検討, 電子情報通信学会HCGシンポジウム2018...
Matsushita Laboratory
 
SIG-AUDIO 2025 Vol.02 オンラインセミナー 「GDC2025 オーディオ報告会」SIG-Audio_GDC2024_報告会資料_増野さ...
IGDA Japan SIG-Audio
 
マルチAIエージェントの産業界での実践に向けたオープンソース活動の展望 - Japan Regional User Group (RUG) Meet-Up
Kosaku Kimura
 
論文紹介:Unbiasing through Textual Descriptions: Mitigating Representation Bias i...
Toru Tamaki
 

Spring data-rest-and-spring-cloud-contract

  • 1. Spring Data REST と Spring Cloud Contract Tagbangers, Inc. #sf_25 #アンケート
  • 2. © Tagbangers, Inc. 1 自己紹介 小川岳史 Spring Lover 10 years 山﨑大 わさもん
  • 3. © Tagbangers, Inc. 2 本日のメニュー • 背景 • Spring Data REST • HATEOAS • Spring Cloud Contract • CDC • Pact
  • 4. © Tagbangers, Inc. 3 背景 • SPA 時代 • よりリッチな UI 表現のために Thymeleaf から Angular などへ • ビジネスロジックの実装が UI 側にも必要なり… Browser Application • ビジネスロジック • CRUD Browser Application • ビジネスロジック • CRUD • ビジネスロジック DB DB
  • 5. © Tagbangers, Inc. 4 工程やチーム構成の変化 BackendFrontend ex. Angular ex. Spring Boot Frontend Team Backend Team User repo repo CI/CDCI/CD code push code push artifactartifact 別々のデプロイ環境 別々のチーム 別々のレポジトリ 別々のリリースサイクル
  • 6. © Tagbangers, Inc. 5 どの URI にアクセスすれば いいの? どんなフォーマットでデー タが取得できるの? 更新できる条件ってなんな の?? そこで発生してきた課題 開発初期段階
  • 7. © Tagbangers, Inc. 6 API の仕様が変更されて UI がバグったんだけど〜 そこで発生してきた課題 リリース後のバージョンアップで
  • 8. © Tagbangers, Inc. 7 解決策 どの URI にアクセスすればいいの? どんなフォーマットでデータが 取得できるの? 更新できる条件ってなんなの?? API の仕様が変更されて UI がバグったんだけど〜 Spring Data REST Spring エコシステムをフル活用! 標準化 + 自動生成 別々に進化できる仕組み Spring Cloud Contract
  • 9. Spring Data REST ✓ 標準化 + 自動生成
  • 10. © Tagbangers, Inc. 9 残念な実装 class ReservationService { Reservation getReservation(long id) { return this.reservationRepository.findById(id); } Reservation createReservation(Reservation reservation) { return this.reservationRepository.save(reservation); } }
  • 11. © Tagbangers, Inc. 10 Spring Data REST とは Entity GET /items GET /items/search GET / items/1 POST /items PUT /items/1 PATCH /items/1 DELETE /items/1 … Item ItemRepository REST スタイルな API エンドポイント URL 設計に迷わない Repository
  • 12. © Tagbangers, Inc. 11 Spring Data REST の始め方 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
  • 13. © Tagbangers, Inc. 12 Entity Repository @Entity public class Order { private Long id; private Location location; private LocalDateTime orderedDate; private Status status; } public interface OrderRepository extends PagingAndSortingRepository<Order, Long> { }
  • 14. © Tagbangers, Inc. 13 . ____ _ __ _ _ / / ___'_ __ _ _(_)_ __ __ _ ( ( )___ | '_ | '_| | '_ / _` | / ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |___, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.6.RELEASE) ... Mapped "{[/ || ],methods=[HEAD],produces=[application/hal+json || application/json]}" ... Mapped "{[/ || ],methods=[GET],produces=[application/hal+json || application/json]}" ... Mapped "{[/ || ],methods=[OPTIONS],produces=[application/hal+json || application/json]}" ... Mapped "{[/{repository}],methods=[OPTIONS],produces=[application/hal+json || application/json]}" ... Mapped "{[/{repository}],methods=[HEAD],produces=[application/hal+json || application/json]}" ... Mapped "{[/{repository}],methods=[GET],produces=[application/hal+json || application/json]}" ... Mapped "{[/{repository}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}" ... Mapped "{[/{repository}],methods=[POST],produces=[application/hal+json || application/json]}" ... Mapped "{[/{repository}/{id}],methods=[OPTIONS],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}],methods=[HEAD],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}],methods=[GET],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}],methods=[PUT],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}],methods=[PATCH],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}],methods=[DELETE],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}/{property}],methods=[GET],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}/{property}/{propertyId}],methods=[GET],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}/{property}],methods=[DELETE],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/{id}/{property}],methods=[GET],produces=[application/x-spring-data-compact+json || text/uri-list]}" Mapped "{[/{repository}/{id}/{property}],methods=[PATCH || PUT || POST],consumes=[application/json || application/x-spring-data-compact+json || text/uri-list], ... Mapped "{[/{repository}/{id}/{property}/{propertyId}],methods=[DELETE],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/search],methods=[OPTIONS],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/search],methods=[HEAD],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/search],methods=[GET],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/search/{search}],methods=[GET],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/search/{search}],methods=[GET],produces=[application/x-spring-data-compact+json]}" Mapped "{[/{repository}/search/{search}],methods=[OPTIONS],produces=[application/hal+json || application/json]}" Mapped "{[/{repository}/search/{search}],methods=[HEAD],produces=[application/hal+json || application/json]}" Mapped "{[/profile],methods=[OPTIONS]}" Mapped "{[/profile],methods=[GET]}" Mapped "{[/profile/{repository}],methods=[GET],produces=[application/alps+json || */*]}" Mapped "{[/profile/{repository}],methods=[OPTIONS],produces=[application/alps+json]}" Mapped "{[/profile/{repository}],methods=[GET],produces=[application/schema+json]}" Mapped "{[/ || ],methods=[GET],produces=[text/html]}" Mapped "{[/browser],methods=[GET]}" 自動的にエンドポイントが登録されている /repository…
  • 15. © Tagbangers, Inc. 14 { "firstName" : "Frodo", "lastName" : "Baggins", "_links" : { "self" : { "href" : "http://localhost:8080/people/1" } } } $ curl http://localhost:8080/people/1 LINK 部 DATA 部
  • 16. © Tagbangers, Inc. 15 HATEOAS • Hypermedia as the Engine of Application State • データ部の他にリンク情報が追加され、関連するリソースをたどることができる • Spring Data REST のリクエスト・レスポンスボディ部のフォーマットは HATEOAS に準拠 • Spring HATEOAS は独立したライブラリでこれだけ使うこともできる
  • 17. © Tagbangers, Inc. 16 フロント側で ID を取り出して個別に URL を組み立てる必要がない ページング情報も $ curl http://localhost:8080/people { "_links" : { "self" : { "href" : "http://localhost:8080/people{?page,size,sort}", "templated" : true }, "search" : { "href" : "http://localhost:8080/people/search" } }, "_embedded" : { "persons" : [ { "firstName" : "Frodo", "lastName" : "Baggins", "_links" : { "self" : { "href" : "http://localhost:8080/people/1" } } } ] }, "page" : { "size" : 20, "totalElements" : 1, "totalPages" : 1, "number" : 0 } } HATEOAS にのっかることでボディ部の フォーマットも悩まない
  • 18. © Tagbangers, Inc. 17 { "description": "iPhone", "status": "IN_PROGRESS", "_links": { "self": { "href": "http://localhost:8080/orders/4" }, "orders": { "href": "http://localhost:8080/orders" }, "cancel": { "href": "http://localhost:8080/orders/4/cancel" }, "complete": { "href": "http://localhost:8080/orders/4/complete" } }
  • 19. if ( order.status == PENDING || order.status == PAID ) { showCancelButton } © Tagbangers, Inc. 18 ビジネスロジックの流出を最小限 に キャンセル判定 ロジック キャンセル判定 ロジック キャンセル判定 ロジック
  • 20. © Tagbangers, Inc. 19 自動生成されて簡単!とはいえ… • とにかく簡単だけど… • Spring Data REST だけでは完成しない • 基本的に CRUD のみ • ビジネスロジックが必要な場合は拡張する Controller Service Repository Database ここは自分で書く Spring Data RESTが よしなに
  • 21. © Tagbangers, Inc. 20 Repository Spring Data REST @RepositoryRest Controller Service @Controller @RestController Endpoint Endpoint Endpoint Domain Model ビジネスロジックの実装パターン EventHandler
  • 22. © Tagbangers, Inc. 21 JSON Schema • JSON Schema から TypeScript のコードの自動生成 TypescriptJson schema 自動生成 curl -H 'Accept:application/schema+json' http://localhost:8080/profile/reservations { "title" : "Reservation", "properties" : { "date" : { "title" : "Date", "readOnly" : false, "type" : "string", "format" : "date-time" }, "name" : { "title" : "Name", "readOnly" : false, "type" : "string" } }, "definitions" : { }, "type" : "object", "$schema" : "http://json-schema.org/draft-04/schema#" } export type Date = string; export type Name = string; export interface Reservation { date?: Date; name?: Name; [k: string]: any; }
  • 23. © Tagbangers, Inc. 22 Admin over Spring Data REST User UI Admin UI Spring Data REST Manual Impl DB
  • 24. © Tagbangers, Inc. 23 全文検索 over Spring Data REST UI Elastic Search Spring Data REST Hibernate Search DB Custom Repository Impl
  • 25. © Tagbangers, Inc. 24 マルチテナント over Spring Data REST UI Spring Data REST Repository DBHibernate Spring Security Authentication Event Listener Filter Tenant
  • 26. © Tagbangers, Inc. 25 ポイント  Spring Data REST を活用してボイラープレートコードを削減する  REST や HATEOAS の流行りの仕様を活用する チーム間のコミュニケーションをフォーマット的なことではなく、 よりビジネス的にフォーカスしたいポイントに絞る!!
  • 27. © Tagbangers, Inc. 26 ポイント BackendFrontend ex. Angular ex. Spring Boot Frontend Team Backend Team User repo repo CI/CDCI/CD code push code push artifactartifact Spring Data REST Spring HATEOAS
  • 28. Spring Cloud Contract でさくっと行う Consumer Driven Contract with Pact 別々に進化できる仕組み
  • 29. © Tagbangers, Inc. 28 工程やチーム構成の変化 BackendFrontend ex. Angular ex. Spring Boot Frontend Team Backend Team User repo repo CI/CDCI/CD code push code push artifactartifact 別々のデプロイ環境 別々のチーム 別々のレポジトリ 別々のリリースサイクル
  • 30. © Tagbangers, Inc. 29 Test Pyramid https://martinfowler.com/bliki/TestPyramid.html
  • 31. © Tagbangers, Inc. 30 モック に置き換える HTTP
  • 32. © Tagbangers, Inc. 31 モック に置き換える その モック 意味がありますか? • インターフェースは正しい?? • 連携するサービスが変更されたら? • だれがメンテナンスするの?
  • 33. © Tagbangers, Inc. 32 Micro service architecture Microservice MicroserviceMicroservice UI Microservice モックモックモックモックモックモックモックモック
  • 34. © Tagbangers, Inc. 33 Spring Cloud Contract Spring Cloud Contract is an umbrella project holding solutions that help users in successfully implementing the Consumer Driven Contracts approach.
  • 35. © Tagbangers, Inc. 34 Pact Pact is a contract testing tool. Contract testing is a way to ensure that services (such as an API provider and a client) can communicate with each other. Without contract testing, the only way to know that services can communicate is by using expensive and brittle integration tests
  • 36. © Tagbangers, Inc. 35 Contract • 契約はインターフェース定義のようなもの • API 仕様書の内容 • Provider が契約を守ることを約束する Contract Consumer Consumer and provider are both agreed with the sentence below.. for example we agreed with on the basis of the Provider’s REST API, that is created hy Provider Test ✔ Test ✔
  • 37. Spring Cloud Contract + Pact で Consumer Driven Contract
  • 38. © Tagbangers, Inc. 37 CDC ステップ 1. テスト書く 2. Contract(Pact file) を自動生成 3. Pact Broker に Pact file を publish Consumer 1. Pact Broker から Contract(Pact file) を取得 2. Test を自動生成(Spring Cloud Contract ) 3. モック を自動生成(Spring Cloud Contract) Provider https://github.com/pact-foundation/pact_broker/wiki/Webhooks
  • 39. © Tagbangers, Inc. 38 1. テストを書く beforeAll ((done) => { provider = new PactWeb({ consumer: ‘sample-client-tenant', provider: ‘sapmle-server-tenant', port: 1234, host: '127.0.0.1' }); }); 前準備 1
  • 40. © Tagbangers, Inc. 39 1. テストを書く beforeAll((done) => { provider.addInteraction({ uponReceiving: 'a request for hello', withRequest: { method: 'GET', path: '/hello' }, willRespondWith: { status: 200, headers: { 'Content-Type': 'application/hal+json;charset=UTF-8' }, body: { reply: 'Hello' } } }).then(done, done.fail); }); 前準備 2
  • 41. © Tagbangers, Inc. 40 1. テストを書く it('should', (done) => { const greetingService: GreetingService = TestBed.get(GreetingTypeService); greetingService.hello().subscribe(response => { expect(response).toEqual({reply: 'Hello'}); done(); }, error => { done.fail(error); }); }); テスト /hello に Get リクエスト
  • 42. © Tagbangers, Inc. 41 CDC ステップ 1. テスト書く 2. Contract(Pact file) を自動生成 3. Pact Broker に Pact file を publish 1. Pact Broker から Contract(Pact file) を取得 2. Test を自動生成(Spring Cloud Contract ) 3. モック を自動生成(Spring Cloud Contract) Consumer Provider
  • 43. © Tagbangers, Inc. 42 2. Pact file ( Contract ) Pact file ... "interactions": [ { "description": "a request for hello", "request": { "method": "GET", "path": "/hello" }, "response": { "status": 200, "headers": { "Content-Type": "application/hal+json;charset=UTF-8" ...
  • 44. © Tagbangers, Inc. 43 CDC ステップ 1. テスト書く 2. Contract(Pact file) を自動生成 3. Pact Broker に Pact file を publish 1. Pact Broker から Contract(Pact file) を取得 2. Test を自動生成(Spring Cloud Contract ) 3. モック を自動生成(Spring Cloud Contract) Contract を共有するためのアプリ https://github.com/pact-foundation/pact_broker/wiki/Webhooks Consumer Provider
  • 45. © Tagbangers, Inc. 44 Pact Broker https://github.com/pact-foundation/pact_broker
  • 46. © Tagbangers, Inc. 45 Pact Broker https://github.com/pact-foundation/pact_broker
  • 47. © Tagbangers, Inc. 46 CDC ステップ 1. テスト書く 2. Contract(Pact file) を自動生成 3. Pact Broker に Pact file を publish 1. Pact Broker から Contract(Pact file) を取得 2. Test を自動生成(Spring Cloud Contract ) 3. モック を自動生成(Spring Cloud Contract) https://github.com/pact-foundation/pact_broker/wiki/Webhooks Consumer Provider
  • 48. © Tagbangers, Inc. 47 CDC ステップ 1. テスト書く 2. Contract(Pact file) を自動生成 3. Pact Broker に Pact file を publish 1. Pact Broker から Contract(Pact file) を取得 2. Test を自動生成(Spring Cloud Contract ) 3. モック を自動生成(Spring Cloud Contract) ビルド時にテストを生成 + テスト実行 https://github.com/pact-foundation/pact_broker/wiki/Webhooks Consumer Provider
  • 49. © Tagbangers, Inc. 48 CDC ステップ 1. テスト書く 2. Contract(Pact file) を自動生成 3. Pact Broker に Pact file を publish 1. Pact Broker から Contract(Pact file) を取得 2. Test を自動生成(Spring Cloud Contract ) 3. モック を自動生成(Spring Cloud Contract) https://github.com/pact-foundation/pact_broker/wiki/Webhooks Consumer Provider
  • 50. © Tagbangers, Inc. 49 CDC ステップ 1. テスト書く 2. Contract(Pact file) を自動生成 3. Pact Broker に Pact file を publish 1. Pact Broker から Contract(Pact file) を取得 2. Test を自動生成(Spring Cloud Contract ) 3. モック を自動生成(Spring Cloud Contract) 成果物としてWireMockの定義ファイルができる https://github.com/pact-foundation/pact_broker/wiki/Webhooks Consumer Provider
  • 51. © Tagbangers, Inc. 50 APIが実装されたか知りたい https://github.com/pact-foundation/pact_broker/wiki/Webhooks Broker のステータス確認で対応状況を把握
  • 52. © Tagbangers, Inc. 51 Pact Broker https://github.com/pact-foundation/pact_broker
  • 53. © Tagbangers, Inc. 52 破壊的な API の実装の変更 https://github.com/pact-foundation/pact_broker/wiki/Webhooks テストが通らないので破壊的な変更だとわかる!
  • 54. © Tagbangers, Inc. 53 使用されている API がわかる! https://github.com/pact-foundation/pact_broker
  • 56. © Tagbangers, Inc. 55 まとめ BackendFrontend ex. Angular ex. Spring Boot Frontend Team Backend Team User repo repo CI/CDCI/CD code push code push artifactartifact Spring Data REST Spring HATEOAS Spring Cloud Contract

Editor's Notes

  • #7: スタンダードな API 設計で・・・ Affordance
  • #21: Spring Data REST の話に戻して Spring Data REST のマッピングの優先順位は最低
  • #23: ビジネスロジックがフロントエンド側にも必要になり、モデルオブジェクトなど冗長なコードが発生していないでしょうか Spring Data REST はエンティティの情報から自動的に JSON Schema を作る機能もあります。 この JSON Schema の情報を使って例えば Angular でしたら Typescript の型をコード生成することも可能です。
  • #29: Spring Cloud Contract Consumer Driven Contract Contract Testing
  • #30: チームを分割したことにより ・ お互いのチームの開発進捗に関係なく開発を進めたい ・ 独自に進化していきたい 変更を加えても壊れないシステムにしたいですよね。 壊れてしまうのであればデプロイ前に知ることができると安心して開発を進めることが出来ます。 アプリケーションをバージョンアップし、自身をもってデプロイしたい
  • #31: テストの自動化にも課題はたくさんあります。 テストピラミッドが表すように、e2e、integration test と呼ばれるようなテストは ・コストがかかる ・時間がかかる →エラーの検知に時間がかかる ・環境構築が複雑 → 環境起因のエラーに悩まされる せっかくチームを分割して専門性を高め、独自に進化していきたいのにテストに足を引っ張られてしまっては意味がありません。 e2e、 integration test を代替する方法を考えなければいけません。 もっとも簡単な方法は integration する相手を モック に置き換えてしまうことです。 モック、スタブ、テストダブルなど言葉はいろいろとありますが、今日はモックという言葉で統一させてもらう
  • #32: モック に置き換えると ・テストのための環境構築がらく ・速い というメリットがありますが
  • #33: モック に置き換えると ・テストのための環境構築がらく ・速い というメリットがありますが インターフェースは正しい?? 連携するサービスが変更されたら? だれがメンテナンスするの? メリットも大きいですが、さらなる問題点が出てきてしまいます。 意味のある モック を維持するのはとても大変です
  • #34: UI と API を分けただけなのに、はやりの Architecture はもっと大変なは・・・・
  • #35: ありますよ。 Spring Cloud Contract。 Spring Cloud とついているので一見 UI + API くらいの分割では意味のないものに思えますが、 ちゃんと使えます。 Consumer Driven Contract の実装を手助け Spring Cloud Contract はとても雑にいうと 意味のある モック を簡単に準備する便利ツールです
  • #36: ありますよ。 Spring Cloud Contract。 Spring Cloud とついているので一見 UI + API くらいの分割では意味のないものに思えますが、 ちゃんと使えます。 Spring Cloud Contract はとても雑にいうと 意味のある モック を簡単に準備する便利ツールです
  • #37: 契約というのは現実世界の契約とそれほど違いはなくて、 例えば携帯電話の契約みたいなもんです。 契約書の内容を確認して問題なければ、サインしますよね。 サインしたら契約完了で、端末だったり通信サービスを受けることが出来ます。 Spring Cloud Contract、 CDC の Contract も同じようなもので 契約の内容をそれぞれのアプリケーションが確認して、間違いなければサインする すると、mock や e2e を補完してくれような恩恵を受けることができるということです。
  • #39: ここからは Consumer と Provider という言葉を使います
  • #41: 期待するレスポンス
  • #42: 期待するレスポンス
  • #44: 期待するレスポンス
  • #46: Pact ファイル と呼ばれる Contract を共有するための web application Docker などで自分で用意することもできるし Hostされているフリーの Broker service もあるよ 自前で準備するのも面倒なのであるプロジェクトではフリーの Broker を使ったりもしています
  • #47: 今回の例は 1 対 1 の 連携ですが Micro service のように多数のサービスが存在するばいいに便利な Service の連携を可視化する機能もあります HAL Browser もあるよ API ドキュメントも参照できる かなり便利なアプリケーション
  • #50: Consumer 側では テストを検証することで アプリケーションが実際にAPIを使用していることを Provider 側では 自動生成Contract が守られる
  • #51: モックを自動生成とかいておりますが、実際には Spring Cloud Contract が対応している WireMock という モックサーバー の定義ファイルが出来ます。 WireMock は 定義ファイルを元に動作するモックサーバーです
  • #53: Pact ファイルを共有するための web application Docker などで自分で用意することもできるし HostされているフリーのBroker もあるよ
  • #55: Pact ファイルを共有するための web application Docker などで自分で用意することもできるし HostされているフリーのBroker もあるよ
  • #57: Spring Data REST でをフル活用することで「いつもの」(単純なCRUDとか)作業は自動生成! HATEOAS を採用してらくに設計をしよう! → フォーカスしたいポイントに集中しよう! コストの高い Integration Test を CDC に置き換えて有効なテストを! →別々に進化できる仕組み