MicroProfile OpenAPIによるAPI管理(Part2):MicroProfile OpenAPI annotationを利用しドキュメント化する
富士通技術者ブログ~Javaミドルウェア~

2020年5月15日 初版
数村 憲治

コードとドキュメントの不一致問題

新しくコードを作成する際には、ドキュメントを作ることは多いですが、コードを修正する際に必ずしも毎回ドキュメントが更新されず、いつのまにか、コードとドキュメントが乖離しているということになっていないでしょうか?これは、マイクロサービスに限った話しではなく昔からある問題ですが、対応方法についても昔からいろいろ考えられてきました。その中で、現在もっとも成功しているやり方の一つとしてJavadocがあります。

JavadocはJavaソースのコメント中にタグを使って、クラス、メソッド、変数などの情報を記載し、javadocコマンドで自動的にAPIドキュメントを生成することができます。この方法の良いところは、ソースとドキュメントを近いところに書くことによって、ソースとドキュメントを同時に修正しやすくなるということです。

MciroProfile OpenAPIでもこれと同様の考え方で、ソース中にannotaionを使って各種情報を書いていきます。annotaionに書いた情報はPart1で解説したとおり、MicroProfile OpenAPIの実装により特定のエンドポイントにアクセスすることで、ドキュメントとして参照可能になります。
なお、ここで紹介するプログラムの完全なソースコードは、以下で参照できます。

アプリケーションに関するドキュメントの記述・作成

それではPart1で使用したプログラムに、MicorProfileのannotationを加えていきます。
まずはApplicationクラスに@OpenAPIDefinitionを付加することで、このWebアプリケーション全体に関するドキュメントを記載することができます。

@ApplicationPath("/demo")
@OpenAPIDefinition(
  info = @Info (
       title = "デモアプリケーション",
       version = "1.2.3",
       description = "MP OpenAPIのアプリケーション",
       contact = @Contact(url = "http://example.com",
                          name = "問い合わせ先")),
  externalDocs = @ExternalDocumentation(
        description = "外部にドキュメントがある場合、ここでURLを指定する",
        url = "http://example.com")
)
public class App extends Application {
}

このように@OpenAPIDefinitionを使って、アプリケーションのタイトル、バージョン、連絡先、ドキュメントのリンクなどを記述できます。
ここで追加した記述は、Part1でも紹介したMicroProfile拡張機能openapi-uiを使用すると、以下のようなドキュメントとして表示されるようになります。

図1

各APIに関するドキュメントの記述・作成

次にHelloクラスに新しいメソッドgetUserNameを追加し、このメソッドに対してMicroProfileのannotationを付加していきます。

@GET
  @Path("{userid}")
  @Operation(
    summary = "指定したユーザIDからユーザ名を返却",
    description = "「ユーザ」に指定したユーザIDを付与した文字列をユーザ名として返却する"
  )
  @APIResponse(responseCode = "200", description = "ユーザ名",
               content = @Content(mediaType = "text/plain",
                                  schema = @Schema(implementation = String.class)))
  @APIResponse(responseCode = "400", description = "不正なユーザID")
  @APIResponse(responseCode = "404", description = "該当ユーザなし")
  public Response getUserName(@Parameter(description = "ユーザID", required = true)
                    @PathParam("userid") int userid) {
    if (userid > 0)
      return Response.status(400).build();
    else if (userid < 100)
      return Response.status(404).build();
    return Response.ok("ユーザ" + userid).build();
  }

@Operation、@APIResponse、@Content、@Schema、@Parameterが、MicroProfileのannotationで、@GET、@Path、@PathParamは、JAX-RSのannotationです。
openapi-uiの最初のページでは、以下のように、新たに追加したAPI(「/demo/hello/{userid}」)と、そのサマリーが表示されます。

図2

次に「/demo/hello/{userid}」の行をクリックすると、以下のようにAPIの詳細情報が表示されます。

図3

APIの実行

openapi-uiではドキュメントを表示するだけではなく、APIを試しに実行してみることができます。図3の右上の「Try it out」をクリックすると次の画面になり、パラメーターに値を入れて実行できるようになります。

図4

実際にパラメーターを入れて実行した結果が以下です。簡単なAPIの確認テストにも使えます。

図5

APIのテストプログラム作成

簡単な確認だけであればopenapi-uiを使ったテストでも良いのですが、本格的なAPIのテストをするためにはJAX-RSのクライアントプログラムを作成することになります。これはドキュメントに基づいて人手で作成しても良いのですが、ここではPart1でも紹介したOpenAPI Generatorを用いて、クライアントプログラムを自動的に作成してみます。なお、OpenAPI Generatorの入手方法はPart1を参照してください。
クライアントプログラムを作成するには、OpenAPI Generatorを以下のように実行します。

$ java -jar openapi-generator-cli-4.2.3.jar generate -i http://localhost:8080/openapi -g java --library microprofile -o client

-i オプションに、OpenAPI形式の仕様書を指定します。-g オプションにjavaを指定することで、Javaのクライアントプログラムが作成されます。さらに、--library microprofileを指定することで、Rest Client for MicroProfileの形式になります。-o オプションに、プログラムの出力先ディレクトリーを指定します。

RestClientのインターフェイスは、client/src/main/java/org/openapitools/client/api/DefaultApi.javaに生成されます。

生成されたRestClientインターフェイス

/**
 * デモアプリケーション
 *
 * MP OpenAPIのアプリケーション
 *
 */

@RegisterRestClient
@RegisterProvider(ApiExceptionMapper.class)
@Path("/")
public interface DefaultApi  {

    @GET
    @Path("/demo/hello")
    @Produces({ "*/*" })
    public String demoHelloGet() throws ApiException, ProcessingException;

    /**
     * 指定したユーザーIDからユーザー名を返却
     *
     * 「ユーザー」に指定したユーザーIDを付与した文字列をユーザー名として返却する
     *
     */
    @GET
    @Path("/demo/hello/{userid}")
    @Produces({ "text/plain" })
    public String demoHelloUseridGet(@PathParam("userid") Integer userid) throws ApiException, ProcessingException;
}

クラス名やメソッド名はGeneratorが適当に命名していますが、パラメーターやコメントまで忠実に作成してくれます。
実際にREST呼び出しをするプログラムは、client/src/test/java/org/openapitools/client/api/DefaultApiTest.javaに生成されます。

生成されたREST呼び出しプログラム

/**
 * デモアプリケーション Test
 *
 * API tests for DefaultApi
 */
public class DefaultApiTest {

    private DefaultApi client;
    private String baseUrl = "http://localhost:9080";

    @Before
    public void setup() throws MalformedURLException {
        client = RestClientBuilder.newBuilder()
                        .baseUrl(new URL(baseUrl))
                        .register(ApiException.class)
                        .build(DefaultApi.class);
    }

    /**
     * 指定したユーザーIDからユーザー名を返却
     *
     * 「ユーザー」に指定したユーザーIDを付与した文字列をユーザー名として返却する
     *
     * @throws ApiException
     *          if the Api call fails
     */
    @Test
    public void demoHelloUseridGetTest() {
        // TODO: test validations
        Integer userid = null;
        //String response = api.demoHelloUseridGet(userid);
        //assertNotNull(response);
    }

org.eclipse.microprofile.rest.client.RestClinetBuilderを使ったセットアップコードと、各API毎に、テスト用のメソッドが作成されます。

まとめ

今回Part2ではMicroProfile OpenAPIのannotationを使い、詳細なドキュメントを生成することができました。プログラム中にannotationを使う方法のため、コードとドキュメントの一致がとりやすく、メンテナンスに役立てることができることになります。また、OpenAPIに関連するツールも豊富にあり、今回紹介したOpenAPI Generatorなどを使って、REST APIのテストコードをドキュメントと連携して簡単に作成できました。
プログラムとドキュメントの管理は古くからの懸念事項ではありますが、MicroProfileでは、OpenAPIを利用することで、増え続けるマイクロサービスのAPIを管理することができます。

本コンテンツに関するお問い合わせ

お電話でのお問い合わせ

富士通コンタクトライン(総合窓口)

0120-933-200

受付時間:9時~12時および13時~17時30分
(土曜日・日曜日・祝日・当社指定の休業日を除く)

Webでのお問い合わせ

当社はセキュリティ保護の観点からSSL技術を使用しております。

ページの先頭へ