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

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

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. 2

  2. 解決策1:API仕様の共同所有 API仕様を提供側チームと利用側チームで共有する。Pull Requestを通して変更やレ ビューを進めることで、共通認識を作る。 11 API仕様 利用側 チーム 提供側 チーム

    • 提供側チームが主体的に管理 • Gitのバージョン管理やPull Requestによ るレビューに適したテキストファイルで記 述 • Excelは適さないのでダメ
  3. 解決策2:API Client, Serverのペア生成 API仕様からAPI Client, Serverのコードを生成する。 API Client Libraryは利用側チームに提供する。 12

    利用側AP 提供側AP Client Server API仕様 利用側 チーム 提供側 チーム Client Server 必ず同一の 仕様になる
  4. OpenAPI Specification(Swagger) REST APIの仕様を記述するための規格 • OpenAPI Initiativeが策定 • 現在はOpenAPI 2.0

    主要なツールセット • Swagger Editor(エディタ) • Swagger UI(ビューア) • Swagger Codegen(コード生成ツール) 18
  5. 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
  6. 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
  7. 21 Gradle Swagger Generator Plugin Gradleで各種ジェネレータを利用できるプラグイン • OpenAPI YAMLのバリデーション •

    Swagger Codegenによるコード生成 • Swagger UIの生成 • ReDocの生成 https://github.com/int128/gradle-swagger-generator-plugin
  8. サービス開発におけるOpenAPIの利用 23 ビュー API Client Controller ビジネスロジック API Client PHP7

    Spring (Java8) YAML フロントエンド チーム バックエンド チーム Swagger UI API連携でコード生成とAPIドキュメント生成を利用している YAML コンテンツ プロバイダ 外部サービス
  9. ★リクエストパラメータのチェック (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
  10. 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
  11. 生成したコードを一切修正せずに利用するため、ControllerからServiceの呼び出しを追 加 @RestController public class HelloController { @Autowired private HelloService

    helloService; @RequestMapping(“/foo/{id}”) public ResponseEntity<FooRequest> foo(@PathVariable(“id”) int id) { return helloService.foo(id); } public interface HelloService { ... } } Spring MVCテンプレートの改造(3/3) 27 アプリケーション側でServiceを 実装して実行時にDI
  12. ControllerからAPIクライアントの呼び出しを生成 @RestController public class HelloController { @Autowired private final HelloClient

    helloClient; @RequestMapping(“/foo/{id}”) public ResponseEntity<FooRequest> foo(@PathVariable(“id”) int id) { return helloClient.foo(id); } } Spring Cloudテンプレートの改造 29 実際にはレスポンスの取捨選択が必要 • Content-Lengthヘッダは返さない • FeignExceptionのハンドリング