こんにちは、技研のブルマンです。
社内の諸事情により、しばらくブログを書けてなかったのですが久しぶりの執筆です。
今回は開発で最近取り扱っている「Swagger」の活用方法について紹介したいと思います。
※ちなみにこの記事は社内の「CRESCO Advent Calendar 2016」の12/15分の記事です。
まず始めに「Swagger(http://swagger.io/)」とは何かを簡単に説明します。
SwaggerはWebAPI仕様ドキュメントのフォーマットおよびビューワーなどを提供するフレームワークです。「Swagger Specification(Spec)」と呼ばれるJSON形式のWebAPI仕様を記述すると、Webページで仕様を確認できたり、各種コードを生成できたりします。
主に以下のコンポーネントから構成されています。
Swagger Editor | Swagger Specのエディタ |
Swagger UI | Swagger Spec から動的にAPIドキュメントを生成するツール |
Swagger Codegen | Swagger Specからクライアントのコードを生成するツール |
WebAPI仕様を記述する仕様としてデファクトスタンダードになりつつあり注目の技術です。
RESTful APIの記述標準化を目指す「Open API Initiative」をマイクロソフト、Google、IBMらが立ち上げ。Swaggerをベースに
http://www.publickey1.jp/blog/15/open_api_initiative.html
弊社では外国拠点で開発を行うオフショア開発、地方拠点で開発を行うニアショア開発も積極的に推進しており、スマホアプリはオフショア、サーバサイドは国内で開発のような事例も増えてきています。
その際にオフショア先にどのようにWebAPI仕様を伝えるのかが問題になりますが、
API仕様がわかるだけでなく、簡単な稼動確認ができるSwaggerはコミニュケーションミスを防ぐ上でも打ってつけです。
とはいえ、、、
弊社は世間一般で言われるSIerになりますので、バイモーダルITにおけるモード1(従来型)開発が仕事のメインになります。
モード1(従来型)開発ではやっぱりウォーターフォール開発になりますし、設計書をしっかり作り・レビューするというとExcelの設計書から簡単に離れることはできません。
(Excelの表現力・融通性などは偉大なんですよね、、)
他の設計書類はExcel設計書で書いてWebAPIの仕様だけSwaggerSpecを書けといわれても現場には受け入れてもらえません。学習コストもかかりますし。
ただ今後の開発の潮流を考えるとSwaggerも活用していきたいと考えた結果、自動生成(ジェネレート)を活用したハイブリッド方式で取り入れることにしました。
弊社ではExcelの設計書からJavaソースコードをジェネレートする自社開発フレームワークを活用して開発を行うケースがあるのですが、そのジェネレート機能を拡張してSwaggerの機能を利用できるようにしました。
処理のイメージは以下の通りです。
WebAPIの仕様はSwaggerSpecを記述する方法とは別に、ソースコード上にSwaggerアノテーションを組み込む方法もあり今回はこちらを採用します。
Excelの設計書から生成されたJavaソースコード(SprinBootのController/RequestDTO/ResponseDTO)にSwaggerアノテーションを組み込み、そのままSpringBootのアプリとして起動します。そうしますとSwaggerUIからWebAPI仕様を確認できるようになります。
この機能を実現するために「Spring Fox(http://springfox.github.io/springfox/)」を利用しました。
生成されたControllerソースコードはこんな感じです。
/** |
* ログインのControllerクラスです。 |
* @author CRESCO |
*/ |
@RestController |
@Scope("prototype") |
@Transactional |
public class SimpleLoginController extends AbstractController { |
/** |
* ログイン:ログイン処理を行い、アクセストークンを戻す。 |
* @param reqDto リクエストDTO |
* @return レスポンスDTO |
*/ |
@ApiOperation(value = "ログイン", notes = "ログイン処理を行い、アクセストークンを戻す。", consumes = "application/json") |
@ApiResponses(value = { |
@ApiResponse(code = 200, message = "OK") |
, @ApiResponse(code = 400, message = "入力値に不備あり") |
}) |
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "application/json", produces = "application/json;charset=UTF-8") |
public SimpleLoginPostResDto postLogin(@RequestBody @Valid SimpleLoginPostReqDto reqDto, BindingResult result) { |
.... |
実際のプロジェクトではクラウド(AWS)上にあるサーバにアプリをデプロイしオフショア先に公開しています。実際のソースコードからWebAPI仕様を生成するため、よくあるJSONの項目名・構造誤りなどを回避でき、なかなかいい感じです。
SwaggerUIで現時点でいくつか使用を注意しないといけない点(バグ?)
がありますので紹介しておきます。
・API実行時にDeleteメソッドとGetメソッドでContent-Typeをリクエストヘッダに設定できない
Swaggerは実際にリクエストを実行することができます。そのため、リファレンスを見ながら即テスト実施ということも可能です。
しかし、DeleteメソッドとGetメソッドでリクエストを実行する際にParameter content typeを指定することができません。
そのため、特定のContent-Typeしか受け付けないようAPIを制御している場合(例えば”application/json”のみ許容など)、Content-Type相違でエラーになってしまします。
こちらを回避するために、リクエストヘッダを拡張する機能を使って、任意でContent-Typeを入れるようしました。
※こちらはバグ情報として取り扱いされているため、修正される可能性があります。
・Example Valueで配列が表現されない
リクエストのサンプル値を設定しておくと、Example ValueとしてリクエストJSONの設定例を表示してくれる機能があります。
しかし、{features (Array[string]) のようなArray[String]型の項目は、Example Valueが”features”: “string”と、配列ではなく文字列となってしまいます。
いかがでしたか?
従来型の開発をしていると新しい技術を取り入れるのは難しい部分がありますが、工夫することによって解決できることもあります。その参考例になれば幸いです。是非皆さんもSwaggerを使ってみてください。