quarkus-smallrye-openapi はJavaのクラスからOpenAPI のYAML/JSONを生成出来るQuarkusの拡張で、InstancioはJavaのクラスから手早くダミーのオブジェクトを生成するライブラリです。
自分はこれらを2つの目的で使用しています。
1つ目はOpenAPI YAMLの生成・提供です。OpenAPI YAMLを直接書いても良いのかもしれませんが、修正作業が入ったときに手作業だと修正漏れなどのミスが発生する可能性が高いです。Javaファイルの修正の場合IDEに修正を任せらることやCompilerでエラーの検出が可能となります。
2つ目はスタブサーバーの提供です。ダミーデータの生成をするライブラリはdatafaker
などいくつかありますが、自分はInstancio
が一番手軽に利用できるライブラリだと思います。
よりリアルなスタブサーバーを作成したい場合には、datafaker
を使ってリアルなデータを生成して使っています。
次からは、どうやって今回の目的のquarkus
アプリケーションを生成するか手順を紹介します。
まず、quarkus
コマンド*1を使ってアプリケーションを生成します。
# quarkus create app --java <java version> --maven -P <quarkus version> --wrapper --extension <Quarkus extensionのリスト(カンマ区切り)> -o <出力先ディレクトリ> <Javaアプリケーション> $ quarkus create app --java 17 --maven -P 3.11.3 --wrapper --extension io.quarkus:quarkus-smallrye-openapi,rest-jackson -o . io.github.yuokada.sample:quarkus-openapi-app ----------- selected extensions: - io.quarkus:quarkus-rest-jackson - io.quarkus:quarkus-smallrye-openapi applying codestarts... 📚 java 🔨 maven 📦 quarkus 📝 config-properties 🔧 tooling-dockerfiles 🔧 tooling-maven-wrapper 🚀 rest-codestart ----------- [SUCCESS] ✅ quarkus project has been successfully generated in: --> /path/to/quarkus-openapi-app ----------- Navigate into this directory and get started: quarkus dev
次に、ダミーデータを生成するためにpom.xml
に次のコードを追加してinstancio-core
を導入します。
<dependency> <groupId>org.instancio</groupId> <artifactId>instancio-core</artifactId> <version>4.8.0</version> </dependency>
そして、APIの実装をInterfaceを使って定義していきます。Interfaceを作成せずClassに直接アノテーションを付与してもOpenAPI yamlの生成は出来ますが、OpenAPIの複数のアノテーションを付与すると見通しが悪くなるので自分はInterfaceとClassに分けるスタイルを採用しています。
メソッドに@GET
, @Path
, @APIResponses
などのAPIエンドポイントの定義をアノテーションで付与していきます。*2
必須なアノテーションとしては @(GET|POST|PUT|DELETE)
, @Path
をぐらいを定義していればスタブサーバーの生成には十分です。あとは、必要に応じてクエリパラメータ・パスパラメータなどを定義します。
@Produces(MediaType.APPLICATION_JSON) public interface SampleApiIf { @GET @Path("/") @Operation( summary = "Return a list of players", description = "Return a list of players" ) @APIResponses({ @APIResponse( responseCode = "200", description = "Returns a list of players", content = @Content( mediaType = "application/json", schema = @Schema(type = SchemaType.ARRAY, implementation = Player.class) ) ), }) Response getPlayers(); @GET @Path("/{id}") @Operation( summary = "Return the detail of a player", description = "Return the detail of a player" ) @APIResponses({ @APIResponse( responseCode = "200", description = "Returns the detail of a player", content = @Content( mediaType = "application/json", schema = @Schema(type = SchemaType.OBJECT, implementation = Player.class) ) ), }) Response getPlayer(@PathParam("id") Long userId); }
Interfaceの定義が完了したら次はその実装を作ります。今回はInstancio
を使ってダミーデータを生成しそれをAPIのレスポンスとします。
Instancio
では完全にランダムな値を生成する以外にもset()
で値を指定したり、generate()
で範囲を決めたランダムな値を付与することが出来ます。
@Path("/v1/api/stub/players") @Tag(name = "Demo App stub API", description = "Demo App Common APIs for development") @Deprecated public class StubApiImpl implements SampleApiIf { @Override public Response getPlayers() { List<Player> players = Instancio.ofList(Player.class).size(10) .generate(field(Player.class, "age"), gen -> gen.ints().range(15, 85)) .create(); return Response.ok(players).build(); } @Override public Response getPlayer(Long userId) { Player player = Instancio.of(Player.class) .set(field("userId"), userId) .generate(field("age"), gen -> gen.ints().range(15, 85)) .create(); return Response.ok(player).build(); } }
ここまで実装が出来たらmavenからquarkus サーバーを立ち上げます。デフォルトだと http://localhost:8080 でサーバーが立ち上がります。 また、http://localhost:8080/q/swagger-ui/#/ でSwagger UIが利用できるので実装したAPIに手軽にリクエストを投げて検証出来ます。
$ ./mvnw quarkus:dev
openapi.yaml
の出力先はquarkus.smallrye-openapi.store-schema-directory
で変更することが出来ます。次の例だとプロジェクト直下にopenapi-definition
が作成されてそこに出力されます。
# OpenApi quarkus.smallrye-openapi.enable=true quarkus.smallrye-openapi.store-schema-directory=openapi-definition
実装に迷った場合はこちらのリポジトリが参考になります。 github.com
まとめです。
quarkus-smallrye-openapi
を使えばOpenAPIの仕様をあまり知らなくてもOpenAPI yamlの生成が簡単に出来ることが伝わったかと思います。
自分も昔OpenAPI yaml
を手書きしていましたが、仕様をある程度知らないと書くのも難しいし修正も大変だった経験があるのでJavaのコードから自動的に生成出来るというのは作成・修正するハードルが下がるので良い手法だなと思いました。
今回のコードのリポジトリはこちらです。 github.com
*1: インストールはこちらから。ja.quarkus.io
*2:詳しい仕様はこちらを参照してください。 download.eclipse.org