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

Swagger Codegenで APIクライアントgem 自動生成 #m3kt

De059f612e2f68589831e4bde0f15c83?s=47 Jumpei Takiyasu
September 28, 2017

Swagger Codegenで APIクライアントgem 自動生成 #m3kt

De059f612e2f68589831e4bde0f15c83?s=128

Jumpei Takiyasu

September 28, 2017
Tweet

Transcript

  1. Swagger Codegenで APIクライアントgem 自動生成 2017-09-28 どこでもKotlin #2 @Speee 滝安純平 (@juntaki)

  2. 自己紹介 滝安 純平 (@juntaki) エムスリー株式会社エンジニア (2017/8-) 前職はファイルシステムの人 https://juntaki.com

  3. もくじ 1. gemを自動生成したい背景 2. Swagger Codegenの仕組みと使い方 3. Swagger Codegen w/

    Springfoxのハマりポイント 4. Springfennecの紹介
  4. gemを自動生成したい背景

  5. サーバーサイドKotlinでリニューアル! サーバーサイド(API) フロント API呼び出し API呼び出しをどう実装するか?

  6. まじめに全部実装すると 1. Kotlinで新しいAPIを作る 2. APIクライアントgemを作る 3. Railsでフロントを作る gemはHTTPの呼び出しをWrapしているだけ

  7. gemは自動生成できる 1. Kotlinで新しいAPIを作る 2. Swagger Codegenでgem自動生成 3. Railsでフロントを作る 重要な実装に注力できる!

  8. Swagger Codegenの仕組みと使い方

  9. Swagger https://swagger.io/

  10. Swagger Tools Swagger Definition(spec file)を生成・パースするツール群 Swagger definition (spec file) API

    ドキュメント サーバ スタブ サーバ実装 クライアント ライブラリ Swagger Core Swagger UI Swagger Codegen Swagger Editor 手入力 今回説明したいのは下半分のフロー
  11. Spring bootと使うには? Spring Boot サーバ実装 クライアント ライブラリ Swagger Core Swagger

    Codegen Springfox Springの実装とSwagger Coreを使い、spec fileを生成する Swagger definition (spec file)
  12. Docket = APIのグループを定義して、タイトルや属性などを追加 Springfoxの使い方 @EnableSwagger2 class SpringfoxConfig { @Bean fun

    demoApiDocument(): Docket { return Docket(DocumentationType.SWAGGER_2) .groupName("springfox") .select() .paths(PathSelectors.ant("/demo/**")) .build() } ...
  13. Ruby gemを生成するには? ruby用テンプレート デフォルトで含まれているテンプレートを使うか mustacheで独自テンプレートを作成する Spring Boot サーバ実装 クライアント gem

    Swagger Core Swagger Codegen Springfox Swagger definition (spec file)
  14. config.json 独自テンプレートを使う場合 コマンド例 java -jar swagger-codegen-cli.jar generate \ --api-package package-name

    \ -o /path/to/outputdir \ -l ruby \ -i http://localhost:8080/v2/api-docs?group=target-api \ -c config.json \ -t /path/to/template { "gemName": "api-client", "moduleName": "ApiClient", "gemVersion": "1.0.0" }
  15. Swagger Codegen w/ Springfoxの ハマりポイント

  16. ハマりポイント:もくじ SpringfoxはAPI自動生成のことを考えていない(ように見える) 1. OperationIdにsuffixがつく 2. Nested Class名が重複すると静かに壊れる 3. spec fileがサーバを起動しないと取り出せない

  17. OperationIdにsuffixがつく OperationId:クライアントgemの関数名になるパラメータ • 複数Docketから参照されている • 別クラスにが同名の定義ある Kotlin spec file "paths":

    { "/demo/user/{id}": { "get": { "tags": [ "demo-controller" ], "summary": "getUser", "operationId": "getUserUsingGET_1", … } @RestController @RequestMapping("/demo") class DemoController { @GetMapping("/user/{id}") fun getUser(@PathVariable id: Int): userApiParam { … }
  18. 対策:OperationIdにsuffixがつく 1. ユニークなIDになるようにアノテーションをつける  @ApiOperaitonのnicknameが設定してあれば、使われる 2. 出力前に削る  同一Docket内で重複したときに例外を出すなどの工夫が必要 詳細は→https://github.com/springfox/springfox/issues/1224#issuecomment-229491446 val newOperationId

    = it.replace(Regex("_[0-9]+$"), "")
  19. Nested Class名が重複すると静かに壊れる "AdminApiParam": { "type": "object", "properties": { "info": {

    "$ref": "#/definitions/Info" } } }, "UserApiParam": { "type": "object", "properties": { "info": { "$ref": "#/definitions/Info" } } } class AdminApiParam( val info: Info ) { class Info( val secretInfo: String, val region: String ) } class UserApiParam( val info: Info ) { class Info(val region: String) } Kotlin spec file ビルドが通ってgemも生成されるが、動かなくなる
  20. 対策:Nested Class名が重複すると静かに壊れる Nested ClassにFQCNっぽいユニークな名前をつける (現状は運用でなんとかするしかない・・・) 気づけた場合は、@ApiModelでリネームも可能 詳細は→https://github.com/springfox/springfox/issues/182

  21. spec fileがサーバを起動しないと取り出せない SpringfoxはBeanとして登録されるように実装されている → spec fileの生成だけを単独で動かせない 1. localhostでサーバ立ち上げ 2. サーバが起動したら、spec

    fileをダウンロード jsonのURLはここに書いてある
  22. 対策:spec fileがサーバを起動しないと取り出せない DBへのアクセスが必要な処理はすべてlazyにする DBのMockがある環境で動かす、など ユニットテストに書いて、生成する方法もある 詳細は→https://github.com/springfox/springfox/issues/2038

  23. まとめ:Swagger Codegen w/ Springfox やればできるが、注意が必要 紹介したコードが含まれるサンプルプロジェクト → https://github.com/juntaki/springfennec-demo

  24. サーバーサイド”Kotlin”特集とは・・? Javaでやってもだいたい同じことがおきると思います

  25. Springfennecの紹介

  26. Springfennec Swagger spec generator from Spring annotations, written in Kotlin

    https://github.com/juntaki/springfennec Springの実装とSwagger annotationから、 Annotation processorでビルド時にspec fileを生成する つくりました
  27. ハマりポイントは対策済み • OperationIdにsuffixなし、重複したらビルド失敗 • Model名はFQCNベースなので重複しない • Annotation processingでビルド時にspec fileを生成 APIクライアント生成に向いている

    すごーい
  28. 使い方 @ApiGroup annotationと、dependenciesを書き足す。 build.gradle Kotlin dependencies { ... // Springfennec

    def springfennecVersion = 'x.x.x' compile('io.swagger:swagger-core:1.5.16') compile("com.juntaki:springfennec:${springfennecVersion}") kapt("com.juntaki:springfennec:${springfennecVersion}") ... } @ApiGroup(value="^/pet/.*", // regex for path (not include basePath) name = "pet_api", // output will be spec_${name}.json, e.g. spec_pet_api.json apiInfo = @SwaggerDefinition(...))
  29. springfennec-demo https://github.com/juntaki/springfennec-demo Springfoxと同時使用可能 生成されるspec fileもリポジトリに入っています

  30. まとめ swagger-codegenでAPIクライアントgemを自動生成できる Springbootを使っているなら、 • Springfox + ハマり回避策 • Springfennec つかってみて!

    Follow me! https://juntaki.com