SpringFoxで吐き出したSwaggerのjsonを使ってswagger-codegenでAPIのclientを吐き出す

# この資料について
* swagger-codegenを使ってRestTemplateを使ったClientを吐き出すやり方をまとめた
* [SpringFoxの内容](https://qiita.com/mitsuya/items/16b0284372b3f8e340af)と合わせて見てほしい
* あくまで自分が使いそうって思ったものしかまとめてないです


# swagger-codegenについて
* 公式はこちら [Swagger Codegen | API Development Tools | Swagger ](https://swagger.io/tools/swagger-codegen/)
* スタブやClientを吐き出してくれるジェネレーター
* いろんな言語やライブラリに対応していて、RestTemplate以外にもretrofitとかにも対応してるし、そもそもjava以外にもswiftとかnodeとか結構いろいろ対応している
* コードは一つのプロジェクトとして吐き出されて、jarにまとめてmavenリポジトリとかに上げてdependencyに追加して利用するとかできる
* 出力されたコードはライセンスとか気にせず自分が作ったものとして利用できる



# とりあえず使ってみる
#### swaggerのjsonを準備する
* 今回はSpringFoxで出力されたjsonを利用する。そのためアプリケーションを起動してjsonを読み取れるようにすればOK。一応json置いとく(人が読み取れるものではないのでフォーマットとか無視)
* localでSpringFoxに対応したアプリケーションを立ち上げている場合は http://localhost:8080/v2/api-docs をアクセスすれば見れる

```json
{"swagger":"2.0","info":{"description":"Api Documentation","version":"1.0","title":"Api Documentation","termsOfService":"urn:tos","contact":{},"license":{"name":"Apache 2.0","url":"http://www.apache.org/licenses/LICENSE-2.0"}},"host":"localhost:8080","basePath":"/","tags":[{"name":"families","description":"families info"}],"schemes":["http","https"],"paths":{"/families":{"post":{"tags":["families"],"summary":"create","operationId":"createUsingPOST","consumes":["application/json"],"produces":["*/*"],"parameters":[{"in":"body","name":"familyRequest","description":"familyRequest","required":true,"schema":{"$ref":"#/definitions/FamilyRequest"}}],"responses":{"200":{"description":"OK","schema":{"type":"object"}},"400":{"description":"Parameter is invalid"},"401":{"description":"認証エラー"},"500":{"description":"Internel server error"}},"deprecated":false}},"/families/list":{"get":{"tags":["families"],"summary":"list","operationId":"listUsingGET","produces":["*/*"],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/FamiliesListResponse"}},"400":{"description":"Parameter is invalid"},"500":{"description":"Internel server error"}},"deprecated":false}},"/families/{familyId}":{"get":{"tags":["families"],"summary":"findFamily","operationId":"findFamilyUsingGET","produces":["*/*"],"parameters":[{"name":"familyId","in":"path","description":"familyId","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/Family"}},"400":{"description":"Parameter is invalid"},"500":{"description":"Internel server error"}},"deprecated":false}},"/families/{familyId}/members/list":{"get":{"tags":["families"],"summary":"findMembersByFamilyId","operationId":"findMembersByFamilyIdUsingGET","produces":["*/*"],"parameters":[{"name":"familyId","in":"path","description":"familyId","required":true,"type":"integer","format":"int32"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/MembersResponse"}},"400":{"description":"Parameter is invalid"},"500":{"description":"Internel server error"}},"deprecated":false}}},"definitions":{"FamiliesListResponse":{"type":"object","properties":{"families":{"type":"array","items":{"$ref":"#/definitions/Family"}}},"title":"FamiliesListResponse"},"Family":{"type":"object","properties":{"familyId":{"type":"integer","format":"int32"},"familyName":{"type":"string"},"updatetime":{"type":"string","format":"date-time"}},"title":"Family"},"FamilyRequest":{"type":"object","properties":{"familyId":{"type":"integer","format":"int32"},"familyName":{"type":"string"},"members":{"type":"array","items":{"$ref":"#/definitions/MemberRequest"}},"updatetime":{"type":"string","format":"date-time"}},"title":"FamilyRequest"},"Member":{"type":"object","properties":{"birthday":{"type":"string","format":"date"},"gender":{"type":"string","enum":["MALE","FEMALE","ETC","NONE"]},"givenName":{"type":"string"},"memberId":{"type":"integer","format":"int32"},"updatetime":{"type":"string","format":"date-time"}},"title":"Member"},"MemberRequest":{"type":"object","properties":{"birthday":{"type":"string","format":"date"},"gender":{"type":"string","enum":["MALE","FEMALE","ETC"]},"givenName":{"type":"string"},"memberId":{"type":"integer","format":"int32"}},"title":"MemberRequest"},"MembersResponse":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/definitions/Member"}}},"title":"MembersResponse"}}}
```

#### configファイルをつくる
* 名前は適当でいいのでconfigファイルをつくる。今回はswagger-codegen-config.jsonとした

```json
{
  "java8" : true,
  "dateLibrary": "java8-localdatetime",
  "apiPackage": "com.example.tryspringfox.client",
  "modelPackage": "com.example.tryspringfox.model",
  "library": "resttemplate",
  "hideGenerationTimestamp": true
}

```

#### configの解説
* 詳しくは下記コマンドを実行して確認すること。今回指定したものだけさらっと書いとく
* けっこういろいろ指定できる。BigDecimalを文字列として扱う、とかそういう細かいのもある

```bash
$ swagger-codegen config-help -l java
```


|設定|設定値|内容|
|---|---|---|
|java8|true,false|3rdパーティのライブラリを使うかjava8のものを使うか|
|dataLibrary|joda,legacy,java8-localdate,java8,threetenbp|Dateクラスで何使うか指定|
|apiPackage|パッケージのパス(com.exampleとか)|生成されるAPIクラスのパッケージを指定|
|modelPackage|パッケージのパス(com.exampleとか)|生成されるModelクラスのパッケージを指定|
|library|restTemplateとか|生成されるクライアントが依存するライブラリを指定|
|hideGenerationTimestamp|true,false|生成されるコードに生成日を記載するか|



#### オプションを指定して生成してみる
* 下記のオプションを指定して動かす

```bash
$ swagger-codegen generate \
-i http://localhost:8080/v2/api-docs \
-l java \
-c ./swagger-codegen-config.json \
-o ../try-swagger-codegen-client
```

#### オプションの解説
* 今回指定したものだけ解説する。詳細はここを見ること [GitHub - swagger-api/swagger-codegen: swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition. ](https://github.com/swagger-api/swagger-codegen)


|オプション|内容|
|---|---|
|-i|swaggerのjsonへのパス|
|-l|言語の指定。javaとか|
|-c|configファイルへのパス|
|-o|出力先のパス|

#### 生成したものを使う
* jarをdependencyに登録する(ローカルでやる場合は適当な場所に設置して下記みたいなかんじでやる)
* 下記のようにDIに登録してあげればあとはよしなに使える

```gradle
dependencies {
   ...
	compile files("jarのパス")
	...
}
```

```java
@Configuration
public class ApiClientConfig {

    @Autowired
    RestTemplateBuilder restTemplateBuilder;

    @Bean
    public FamiliesApi familiesApi(){
        return new FamiliesApi(apiClient());
    }

    @Bean
    public ApiClient apiClient() {
        RestTemplate restTemplate = restTemplateBuilder.setReadTimeout(1000).setConnectTimeout(1000).build();
        ApiClient apiClient = new ApiClient(restTemplate);
        apiClient.setBasePath("http://prod.hostname.com");
        return apiClient;
    }
}

```

# 使ってみて雑感
* ホストがswaggerの仕様だと固定されてしまうが、上記のように変更できる
* RestTemplateをApiClientクラスをインスタンス化するときに引数として渡せるので、やりたいことはたいてい自前でいろいろ設定できそう
* クライアントクラスのテストは生成されないが仕様通りにリクエストはできるので、生成されるコードに関してはテストをやらないっていう選択肢はありだと思う
* 普通にインターセプターとかも使えるので、共通でヘッダを追加したい、とかも問題なく可能
* jarとしてmavenリポジトリに登録できるので、いろいろなところで同じクライアントクラスをつくる、っていうことにはならなそうなので、マイクロサービス化しているシステムを開発している場合は利用してみても良いと思う

# 参考にした資料
* [Generate Spring Boot Project with Swagger | Baeldung ](https://www.baeldung.com/spring-boot-rest-client-swagger-codegen)
* [Swagger Codegen | API Development Tools | Swagger ](https://swagger.io/tools/swagger-codegen/)
* [GitHub - swagger-api/swagger-codegen: swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition. ](https://github.com/swagger-api/swagger-codegen)

# 関連記事
[SpringFoxを使ってSwaggerのjsonを吐き出す](https://qiita.com/mitsuya/items/16b0284372b3f8e340af)