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

Swaggerのテンプレートを魔改造した話 / Customize Swagger Templates

Hidetake Iwata
September 30, 2017

Swaggerのテンプレートを魔改造した話 / Customize Swagger Templates

第二十回 #渋谷java

Hidetake Iwata

September 30, 2017
Tweet

More Decks by Hidetake Iwata

Other Decks in Technology

Transcript

  1. Hidetake Iwata
    Software Engineer at NTT DATA
    第二十回 #渋谷java
    Swaggerのテンプレートを
    魔改造した話

    View Slide

  2. 2

    View Slide

  3. Agenda
    今日話すこと
    1. 複数チームによるAPI開発の課題
    2. What is OpenAPI?
    3. サービス開発におけるOpenAPIの利用
    今日話さないこと
    ● 大規模SI
    3

    View Slide

  4. 1. 複数チームによるAPI開発
    4

    View Slide

  5. 複数チームのAPI開発でよくある話(1/4)
    コンポーネントチームが並行開発を行う場合を考える。
    5
    フロント
    エンド
    サービスA
    サービスB
    フロントエンドチーム
    バックエンドチーム
    コンテンツプロバイダ

    View Slide

  6. 複数チームのAPI開発でよくある話(2/4)
    6
    フロント
    エンド
    サービスA
    サービスB このAPI仕様で
    提供します!
    OK、その仕様で
    クライアントコード書くね
    画面項目もバッチリ!
    {“yen”: 100}
    {“yen”: 100}
    100円

    View Slide

  7. 複数チームのAPI開発でよくある話(3/4)
    7
    API仕様に
    追加しておくね!
    Modelを直さなきゃ
    ごめん、ドル金額も
    追加で返してほしい
    フロント
    エンド
    サービスA
    サービスB
    {“yen”: 100,
    “dollar”: 1.0}
    {“yen”: 100}
    100円

    View Slide

  8. 複数チームのAPI開発でよくある話(4/4)
    8
    昨日リリースしたよ
    ごめん、古い版を見てた
    あれ、レスポンスに
    項目Bがないんだけど
    フロント
    エンド
    サービスA
    サービスB
    {“yen”: 100,
    “dollar”: 1.0}
    {“yen”: 100}
    100円
    (0ドル)

    View Slide

  9. ワラフォーさん(仮名)
    ● 手戻りのないようにレビューを徹底するのじゃ
    ● Excel様式でしっかり設計するのじゃ
    アージャイルさん(仮名)
    ● チーム横断のミーティングを設けよう!
    ● フィーチャーチームだ!
    Team
    解決策?
    9
    Team
    フロント
    エンド
    サービスA
    サービスB

    View Slide

  10. 複数チームによるAPI開発の課題
    目を背けてはいけない事実:
    ● 完全なAPI仕様を初期に決めることは不可能
    ● API仕様の変更には相応のコストがかかる
    ● 完全に独立したフィーチャーチームは作れない
    インクリメンタルなAPI設計に必要なもの:
    1. 複数のチームが安全にAPI仕様を変更できる仕組み
    2. 担当者やツールがボトルネックにならないこと
    10

    View Slide

  11. 解決策1:API仕様の共同所有
    API仕様を提供側チームと利用側チームで共有する。Pull Requestを通して変更やレ
    ビューを進めることで、共通認識を作る。
    11
    API仕様
    利用側
    チーム
    提供側
    チーム
    ● 提供側チームが主体的に管理
    ● Gitのバージョン管理やPull Requestによ
    るレビューに適したテキストファイルで記

    ● Excelは適さないのでダメ

    View Slide

  12. 解決策2:API Client, Serverのペア生成
    API仕様からAPI Client, Serverのコードを生成する。
    API Client Libraryは利用側チームに提供する。
    12
    利用側AP
    提供側AP
    Client
    Server
    API仕様
    利用側
    チーム
    提供側
    チーム
    Client
    Server
    必ず同一の
    仕様になる

    View Slide

  13. 解決策3:Semantic Versioning
    破壊的な仕様変更をインクリメンタルに取り込めるようにする。
    13
    利用側AP
    提供側AP
    Client
    Server
    API仕様 (1.1.0) Client
    Server
    API仕様 (1.0.0) Client
    Server
    1.1.0に上げて、
    コンパイル
    エラーを修正

    View Slide

  14. コード生成の光と影(1/2)
    14
    Pros.
    ● 同一の仕様からClient, Serverを生成するので等価性を保証できる
    ● 単純作業(量産体制)を排除してチームを小さく保つ
    Cons.
    ● 自動生成されたコードを修正すると、仕様変更がカオス化
    ● ツール職人がボトルネックになりがち

    View Slide

  15. コード生成の光と影(2/2)
    Good use cases
    ● 宣言の自動生成(Controller、モデル)
    ● ビルド時に動的にコードを生成する(Ephemeral)
    ● 汎用的なツール(オープンソース)
    Bad use cases
    ● ロジックの自動生成
    ● 仕様とソースコードの二重管理(Excel)
    ● 特定の場合にしか使えない
    15

    View Slide

  16. ビルドツールで自動的にコード生成を実行する。
    ● 自動生成されたコードを修正できない仕組みを強制する
    ● 開発者がコード生成を意識しない
    16
    解決策4:ビルドシステムにコード生成を組み込む
    Executable JAR
    API仕様 (YAML)
    Client (Java)
    Server (Java)
    アプリケーション
    Client JAR Nexus
    デプロイ
    APIドキュメント (HTML) S3
    中間生成物

    View Slide

  17. 2. What is OpenAPI?
    17

    View Slide

  18. OpenAPI Specification(Swagger)
    REST APIの仕様を記述するための規格
    ● OpenAPI Initiativeが策定
    ● 現在はOpenAPI 2.0
    主要なツールセット
    ● Swagger Editor(エディタ)
    ● Swagger UI(ビューア)
    ● Swagger Codegen(コード生成ツール)
    18

    View Slide

  19. paths:
    /pets:
    get:
    responses:
    "200":
    schema:
    type: "array"
    items:
    $ref: "#/definitions/Pet"
    definitions:
    Pet:
    type: "object"
    properties:
    id:
    type: "integer"
    format: "int64"
    name:
    type: "string"
    https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/petstore-minimal.yaml
    YAML Swagger Editor
    Swagger UI
    http://editor.swagger.io
    19

    View Slide

  20. Swagger Codegen
    OpenAPI仕様からソースコードを生成するツール
    ● 多くの言語やフレームワークに対応
    https://github.com/swagger-api/swagger-codegen
    API clients: ActionScript, Apex, Bash, C# (.net 2.0, 4.0 or later), C++ (cpprest, Qt5, Tizen), Clojure, Dart, Elixir, Go, Groovy, Haskell, Java (Jersey1.x, Jersey2.x,
    OkHttp, Retrofit1.x, Retrofit2.x, Feign), Kotlin, Node.js (ES5, ES6, AngularJS with Google Closure Compiler annotations) Objective-C, Perl, PHP, Python, Ruby,
    Scala, Swift (2.x, 3.x), Typescript (Angular1.x, Angular2.x, Fetch, jQuery, Node)
    Server stubs: C# (ASP.NET Core, NancyFx), C++ (Restbed), Erlang, Go, Haskell, Java (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play
    Framework), PHP (Lumen, Slim, Silex, Zend Expressive), Python (Flask), NodeJS, Ruby (Sinatra, Rails5), Scala (Finch, Scalatra)
    API documentation generators: HTML, Confluence Wiki
    Others: JMeter
    ● Executable JARが提供されている
    ● mustacheのテンプレートをカスタマイズ可能
    20

    View Slide

  21. 21
    Gradle Swagger Generator Plugin
    Gradleで各種ジェネレータを利用できるプラグイン
    ● OpenAPI YAMLのバリデーション
    ● Swagger Codegenによるコード生成
    ● Swagger UIの生成
    ● ReDocの生成
    https://github.com/int128/gradle-swagger-generator-plugin

    View Slide

  22. 3.
    サービス開発におけるOpenAPIの利用
    22

    View Slide

  23. サービス開発におけるOpenAPIの利用
    23
    ビュー
    API Client
    Controller
    ビジネスロジック
    API Client
    PHP7
    Spring
    (Java8)
    YAML
    フロントエンド
    チーム
    バックエンド
    チーム
    Swagger UI
    API連携でコード生成とAPIドキュメント生成を利用している
    YAML
    コンテンツ
    プロバイダ
    外部サービス

    View Slide

  24. Swagger Codegenテンプレートのカスタマイズ
    Spring MVCテンプレート(APIサーバ)
    1. リクエストモデルのバリデーションを追加
    2. 独自バリデータ対応
    3. サービスクラスをDIして呼び出すように変更
    Spring Cloudテンプレート(APIクライアント)
    1. API Proxyの生成
    24

    View Slide

  25. ★リクエストパラメータのチェック (GET)
    {{#allParams}}
    {{^isBodyParam}}
    {{#required}}
    if ("{{dataType}}".equals("Integer") ||
    "{{dataType}}".equals("Long")) {
    if ({{paramName}} == null) {
    throw new ValidationException("...");
    }
    }
    {{/required}}
    ★Bean Validatorのアノテーションを
    モデルクラスに付加
    @DecimalMin("{{minimum}}")
    @DecimalMax("{{maximum}}")
    @NotNull
    @Size(min={{minLength}}{{#maxLength}},
    max={{maxLength}}{{/maxLength}})
    @Size(max={{maxLength}})
    @Pattern(regexp = "{{pattern}}")
    @Valid
    Spring MVCテンプレートの改造(1/3)
    OpenAPIの型や制約に対応するバリデーション処理を追加
    25

    View Slide

  26. Spring MVCテンプレートの改造(2/3)
    definitions:
    Pet:
    properties:
    code:
    type: string
    x-validations:
    hiragana: true
    26
    public class Pet {
    @Hiragana
    @Valid
    private String code = null;
    }
    YAMLのVendor Extensionsで独自のバリデータを指定できるように拡張
    (TERASOLUNAが提供しているバリデータ*1を利用)
    YAML Java
    (*1) http://terasolunaorg.github.io/guideline/5.3.0.RELEASE/ja/ArchitectureInDetail/GeneralFuncDetail/StringProcessing.html#stringprocessinghowtousecodepoints

    View Slide

  27. 生成したコードを一切修正せずに利用するため、ControllerからServiceの呼び出しを追

    @RestController
    public class HelloController {
    @Autowired private HelloService helloService;
    @RequestMapping(“/foo/{id}”)
    public ResponseEntity foo(@PathVariable(“id”) int id) {
    return helloService.foo(id);
    }
    public interface HelloService { ... }
    }
    Spring MVCテンプレートの改造(3/3)
    27
    アプリケーション側でServiceを
    実装して実行時にDI

    View Slide

  28. API Proxyの自動生成
    フロントエンドと外部サービスをつなぐ一部のAPIはビジネスロジックが必要なかったた
    め、ControllerからAPIクライアントの呼び出しを自動生成
    Controller
    API Client
    28
    フロントエンド
    外部サービス
    YAML
    バリデーション
    インターセプタの共通処理
    (OAuth、トレースID等)

    View Slide

  29. ControllerからAPIクライアントの呼び出しを生成
    @RestController
    public class HelloController {
    @Autowired private final HelloClient helloClient;
    @RequestMapping(“/foo/{id}”)
    public ResponseEntity foo(@PathVariable(“id”) int id) {
    return helloClient.foo(id);
    }
    }
    Spring Cloudテンプレートの改造
    29
    実際にはレスポンスの取捨選択が必要
    ● Content-Lengthヘッダは返さない
    ● FeignExceptionのハンドリング

    View Slide

  30. (心の声)
    OpenAPIに対応したAPIゲートウェイでよ
    かったのかもしれない
    30

    View Slide

  31. まとめ
    複数チームの並行開発ではインクリメンタルなAPI設計を支える仕組みが必要
    ● OpenAPI YAMLでAPI仕様を記述し、Pull Requestでレビュー
    ● APIドキュメントを共有して共通認識を形成
    ● ControllerとAPIクライアントを自動生成してタイプセーフな呼び出し
    これらの仕組みを活用することで、継続的なサービス開発が可能になる
    31

    View Slide

  32. Thank You
    32

    View Slide