テクノロジー&エンジニアリングセンターの伊藤です。 TISの会津若松拠点(AiCT)で働き出して1年が経過しているのですが、 会津若松の観光名所「大内宿」に一度も行ったことがありません。近くにいると行かないものですね。

さて、9/29にNablarch 5u18をリリースしました。 今回のブログでは5u18のリリース内容の中から注目機能について紹介します。 リリース内容の詳細はリリースノートをご覧ください。

クラウドネイティブ対応

Nablarchのクラウドネイティブ対応は、「Twelve-Factor App」を参考に、 アプリケーションのステートレス化、コンテナ化、環境変数を使った設定の対応を行いました。

アプリケーションのステートレス化と環境変数を使った設定は、5u16でリリースした 「Webアプリケーションをステートレスにする」 と 「OS環境変数を使って環境依存値を上書きする」 で対応済みです。

5u18では残りのコンテナ化の対応を行っています。 さらに、ステートレス化の運用負荷を減らすためセッションストア の保存先としてRedisを追加しました。

コンテナ化

Nablarchを使ったアプリケーションでコンテナ化を行う方法については下記を参照ください。

上記方法を実現したブランクプロジェクトを追加しました。 これらのブランクプロジェクトによりコンテナで稼働するアプリケーション開発をすぐに始められます。

Redis対応

クラウド上でスケールしやすいアプリケーション構成とするためにセッションストアの保存先をRedisにできるアダプタを追加しました。

DBストアに比べて事前にスキーマを準備する必要がない、有効期限切れのセッション情報をRedisの仕組みで削除できるなどのメリットがあります。

MSA(マイクロサービスアーキテクチャ)対応

NablarchでMSAを実現するにあたり必要となるメトリクス収集の機能追加を行いました。

メトリクス収集

Micrometerのアダプタを追加しました。

Micrometerアダプタを使うことで、次のようなことができるようになり、アプリケーションの運用監視がしやすくなるというメリットが得られます。

  • JVMのメモリ使用量やCPU使用率など、アプリケーションのメトリクスを収集できる
  • 収集したメトリクスをDataDogAmazon CloudWatchなどの監視サービスに連携できる

RESTfulウェブサービスの機能強化

サービス開発ではSPA(シングルページアプリケーション)+REST API構成が一般的に採用されるようになり、 少人数で変更が発生しやすいサービス開発でRESTfulウェブサービスを利用するケースが増えています。 そのような状況に対応するためRESTfulウェブサービスの機能強化を行いました。

今回の機能強化を取り込んだNablarchを使ったSPA+REST API構成のサービス開発リファレンスを公開していますので、 SPA+REST API構成にご興味がある方はぜひご覧ください。 SPAとREST APIで構成されるウェブアプリケーションを開発する際にリファレンスとして活用して頂ける方式設計のガイド アプリケーションのコード例ハンズオンコンテンツが含まれています。

単体テストフレームワークの追加

既存のテスティングフレームワークでサポートしていなかったRESTfulウェブサービス向け単体テストフレームワークを追加しました。

RESTfulウェブサービス向け単体テストフレームワークでは、データベース初期値のみExcelに定義し、 リクエストとレスポンスはコーディングします。リクエストに必要な機能はテストフレームワークが提供していますが、 レスポンスボディのアサート機能はOSSのライブラリを使うことにしています。 アサート機能はプロジェクトの要件に合わせて柔軟に変更できるようにしています。

import nablarch.fw.web.HttpResponse;
import nablarch.fw.web.RestMockHttpRequest;
import nablarch.test.core.http.RestTestSupport;
import org.json.JSONException;
import org.junit.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;

import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertThat;

public class SampleTest extends RestTestSupport { //RestTestSupportを継承する
    @Test  //アノテーションを付与する
    public void プロジェクト一覧が取得できること() throws JSONException {
        String message = "プロジェクト一覧取得";

        RestMockHttpRequest request = get("/projects");               //リクエストを生成する
        HttpResponse response = sendRequest(request);                 //リクエストを送信する
        assertStatusCode(message, HttpResponse.Status.OK, response);  //結果を確認する

        assertThat(response.getBodyString(), hasJsonPath("$", hasSize(10)));    //json-path-assertを使ったレスポンスボディの検証

        JSONAssert.assertEquals(message, readTextResource("プロジェクト一覧が取得できること.json")
                , response.getBodyString(), JSONCompareMode.LENIENT);                  //JSONAssertを使ったレスポンスボディの検証
    }
}

先ほど「データベース初期値のみExcelに定義し」と伝えましたが、RESTfulウェブサービス向け単体テストフレームワークは Excelの使用を必須としていないので、Excelの代わりに他の仕組みを使ってテストに必要なデータのセットアップを行えます。 SPA+REST API構成のサービス開発リファレンスに含まれる アプリケーションのコード例では、Flywayを使ってテストに必要なデータのセットアップを実現しています。

アノテーションによるルーティング定義

JAX-RSのPathアノテーションによるルーティングの定義が可能となりました。 開発途上でAPIの増減が発生しやすいサービス開発においてもXML修正の競合などが発生しにくく、各開発者が自身の担当機能に集中できます。

パス/HTTPメソッドとアクションクラスのマッピングは次のようになります。

@Path("/sample")
public class SampleAction {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Person> findAll() {
        // 省略
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public int register(HttpRequest request) {
        // 省略
    }
}

サブパスをマッピングすることもできます。

@Path("/sample")
public class TestAction {

    @GET
    @Path("/foo")
    @Produces(MediaType.APPLICATION_JSON)
    public Person foo() {
        // 省略
    }

    @GET
    @Path("/bar")
    @Produces(MediaType.APPLICATION_JSON)
    public Person bar() {
        // 省略
    }
}

パスパラメータを使うこともできます。

@Path("/sample")
public class TestAction {

    @GET
    @Path("/foo/{param}")
    @Produces(MediaType.APPLICATION_JSON)
    public Person foo(HttpRequest request) {
        String param = request.getParam("param")[0];
        // 省略
    }
    
    @GET
    @Path("/bar/{id : \\d+}")    // パスパラメータの書式を正規表現で指定
    @Produces(MediaType.APPLICATION_JSON)
    public Person bar(HttpRequest request) {
        int id = Integer.parseInt(request.getParam("id")[0]);
        // 省略
    }
}

アプリケーションアーキテクチャ対応

Nablarchはレイヤードアーキテクチャ、オニオンアーキテクチャ、クリーンアーキテクチャといった アプリケーションの構造を組み立てる機能がありませんでした。

従来のシステムリポジトリは、 XMLファイルにコンポーネント定義をするため、 複雑なアプリケーションの構造を設定ファイルに全て記載していくのは手間とメンテナンスの面で現実的ではありません。 この問題を解決するため、アノテーションでコンポーネント登録できる機能を追加しました。

SystemRepositoryComponentアノテーションを付与することでコンポーネント登録を行い、 コンストラクタインジェクションを使ってアプリケーションの構造を組み立てることができます。

@SystemRepositoryComponent
@Path("/todos/{todoId}")
public class TodoAction {

    private final TodoService todoService;

    public TodoAction(TodoService todoService) {
        this.todoService = todoService;
    }
}
@SystemRepositoryComponent
public class TodoService {

    private final TodoRepository todoRepository;

    public TodoService(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

ConfigValueアノテーションを使って設定値をインジェクションすることもできます。

@SystemRepositoryComponent
public class ExampleService {

    private final String errorMessageId;

    public ExampleService(@ConfigValue("${example.service.errorMessageId}") String errorMessageId) {
        this.errorMessageId = errorMessageId;
    }

今回紹介した以外にも要望/不具合対応を実施していますので、詳細はリリースノートをご覧ください。

大規模システム開発、サービス開発を問わず、Webアプリケーションやバッチアプリケーションといった、 アプリケーションに対する技術要件に応じてフレームワークの機能拡張を今後も実施していきます。 新しく追加した機能をぜひご活用ください。


本コンテンツはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。