ルーティングアダプタ

http-request-router(外部サイト) を使用して、 リクエストURLと業務アクションのマッピングを行うアダプタ。

本アダプタを使用することで、 ウェブアプリケーションRESTfulウェブサービス を 構築する際に、URLと業務アクションのマッピングを容易に定義できる。

モジュール一覧

<!-- ルーティングアダプタ -->
<dependency>
  <groupId>com.nablarch.integration</groupId>
  <artifactId>nablarch-router-adaptor</artifactId>
</dependency>

補足

http-request-routerのバージョン0.1.1を使用してテストを行っている。 バージョンを変更する場合は、プロジェクト側でテストを行い問題ないことを確認すること。

ルーティングアダプタを使用するための設定を行う

本アダプタを使用するための手順を以下に示す。

ディスパッチハンドラを設定する

ディスパッチハンドラとして、 RoutesMapping をハンドラキューの最後に設定する。

設定例を以下に示す。

ポイント
  • コンポーネント名は packageMapping とする。
  • basePackage属性には、アクションクラスが格納されているパッケージを設定する。 (アクションクラスが複数のパッケージに格納されている場合は、共通となる親パッケージを設定する。)
  • RoutesMapping を初期化対象のリストに設定する。
<component name="packageMapping" class="nablarch.integration.router.RoutesMapping">
  <property name="basePackage" value="sample.web.action" />
</component>

<component name="webFrontController" class="nablarch.fw.web.servlet.WebFrontController">
  <property name="handlerQueue">
    <list>
      <!-- その他のハンドラは省略 -->
      <component-ref name="packageMapping" />
    </list>
  </property>
</component>

<component name="initializer"
    class="nablarch.core.repository.initialization.BasicApplicationInitializer">
  <property name="initializeList">
    <list>
      <!-- その他の初期化処理は省略 -->
      <component-ref name="packageMapping"/>
    </list>
  </property>
</component>

ルート定義ファイルを作成する

クラスパス直下に routes.xml を作成し、 指定したURLと業務アクションのマッピングを設定する。

ルート定義ファイルへの設定方法は、ライブラリのREADMEドキュメント(外部サイト) を参照。

業務アクションとURLを自動的にマッピングする

ルート定義ファイルにて、 match タグのpath属性に :controller:action といったパラメータを使用することで業務アクションとURLの自動マッピングを行うことができる。

重要

アプリケーションサーバに JBossWildFly を使用している場合、この機能は使用できない。 get タグ等を使用して個別に業務アクションとURLのマッピングを定義すること。

重要

get タグ等を使用したマッピングの個別定義とこの機能の併用は推奨しない。 併用した場合に、業務アクションとURLがどのようにマッピングされるかが、ルート定義ファイル上から読み取りづらくなる問題があるため。

この機能を有効にするには、クラスパス直下に作成した net/unit8/http/router ディレクトリに routes.properties を作成し、以下のとおり値を設定する。

router.controllerDetector=nablarch.integration.router.NablarchControllerDetector

ルート定義ファイルへの設定とマッピングの例を以下に示す。

ルート定義ファイル
<routes>
  <match path="/action/:controller/:action" />
</routes>
業務アクションとマッピングするURLの例
業務アクション URL
PersonAction#index /action/person/index
PersonAction#search /action/person/search
LoginAction#index /action/login/index
ProjectUploadAction#index /action/projectUpload/index

JAX-RSのPathアノテーションでマッピングする

本アダプタのバージョン1.2.0から、JAX-RSの javax.ws.rs.Path アノテーション(以下 Path アノテーションと表記)を使ったルーティングのマッピングができるようになった。

ここでは、既存の RESTfulウェブサービス に対して Path アノテーションを使ったルーティングを有効にする方法と、各種設定の詳細について説明する。

重要

本機能は、クラスパス配下のリソースを独自のファイルシステムで管理している一部のウェブアプリケーションサーバでは使用できない。

例えば、JbossやWildflyでは、vfsと呼ばれるバーチャルファイルシステムで クラスパス配下のリソースが管理されるため、 Path アノテーションで注釈されたクラスの検索ができない。

そのようなウェブアプリケーションサーバを使用する場合は、従来通りXMLを用いたルーティングの定義を使用すること。

ディスパッチハンドラを変更する

XMLのマッピング定義を使用する場合は、ディスパッチハンドラの実装として RoutesMapping を使用していた。 一方、 Path アノテーションによるマッピング定義を用いる場合は、 PathOptionsProviderRoutesMapping をディスパッチハンドラとして設定する必要がある。

<!-- Pathアノテーションによるルーティング定義を有効にする場合の設定例 -->
<component name="packageMapping" class="nablarch.integration.router.PathOptionsProviderRoutesMapping">
  <property name="pathOptionsProvider">
    <component class="nablarch.integration.router.jaxrs.JaxRsPathOptionsProvider">
      <property name="applicationPath" value="${nablarch.webApi.applicationPath}" />
      <property name="basePackage" value="${nablarch.commonProperty.basePackage}" />
    </component>
  </property>

  <property name="methodBinderFactory">
    <component class="nablarch.fw.jaxrs.JaxRsMethodBinderFactory">
      <property name="handlerList">
        <component class="nablarch.integration.jaxrs.jersey.JerseyJaxRsHandlerListFactory"/>
      </property>
    </component>
  </property>
</component>

<!-- ハンドラキュー構成 -->
<component name="webFrontController" class="nablarch.fw.web.servlet.WebFrontController">
  <property name="handlerQueue">
    <list>
      <!-- 省略 -->
      <component-ref name="packageMapping"/>
    </list>
  </property>
</component>
Path アノテーションによるルーティングを使用するには、 PathOptionsProviderRoutesMappingpathOptionsProvider プロパティに JaxRsPathOptionsProvider を設定する。
methodBinderFactory プロパティの設定については JAX-RSアダプタ を参照)

さらに、この JaxRsPathOptionsProvider には、次の2つのプロパティを設定する必要がある。

applicationPath

マッピングするパスに共通するプレフィックスを設定する。
JAX-RS の javax.ws.rs.ApplicationPath アノテーションで設定する値と同じものを意味する。

basePackage

Path アノテーションが設定されたクラスを検索する、ルートとなるパッケージ名を設定する。

定義した PathOptionsProviderRoutesMapping のコンポーネントは初期化が必要なので、初期化対象のリストに追加する。

<component name="initializer"
           class="nablarch.core.repository.initialization.BasicApplicationInitializer">
  <property name="initializeList">
    <list>
      <component-ref name="packageMapping" />
      <!-- 省略 -->
    </list>
  </property>
</component>

以上の設定により、 Path アノテーションによるルーティングの登録機能が使用できるようになる。

マッピングの実装方法

Path アノテーションを使ってマッピングを定義した実装例を以下に示す。

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

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

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public int register(JaxRsHttpRequest request) {
        // 省略
    }
}
アクションクラスを Path アノテーションで注釈することで、 Path アノテーションの value で設定したパスとアクションクラスを紐づけることができる。
さらに、 javax.ws.rs.GET などのHTTPメソッドを表すアノテーションでアクションクラスのメソッドを注釈することで、HTTPメソッドとアクションクラスのメソッドを紐づけることができる。

上記の実装例では、次のように HTTP リクエストがディスパッチされる。

パス HTTPメソッド ディスパッチされるメソッド
/sample GET SampleAction#findAll()
/sample POST SampleAction#register(JaxRsHttpRequest)

補足

HTTPメソッドを紐づけるアノテーションは、標準で以下のものが用意されている。

  • javax.ws.rs.DELETE
  • javax.ws.rs.GET
  • javax.ws.rs.HEAD
  • javax.ws.rs.OPTIONS (JAX-RS 1.1 以上)
  • javax.ws.rs.PATCH (JAX-RS 2.1 以上)
  • javax.ws.rs.POST
  • javax.ws.rs.PUT

さらに、以下のようにメソッドを Path アノテーションで注釈することで、サブパスのマッピングも定義できる。

@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() {
        // 省略
    }
}

この場合、HTTPリクエストのディスパッチは次のようになる。

パス HTTPメソッド ディスパッチされるメソッド
/sample/foo GET TestAction#foo()
/sample/bar GET TestAction#bar()

パスパラメータの定義

次のように、パスにパラメータを含めることもできる。

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

    @GET
    @Path("/foo/{param}")
    @Produces(MediaType.APPLICATION_JSON)
    public Person foo(JaxRsHttpRequest request) {
        String param = request.getPathParam("param");
        // 省略
    }

    @GET
    @Path("/bar/{id : \\d+}")
    @Produces(MediaType.APPLICATION_JSON)
    public Person bar(JaxRsHttpRequest request) {
        int id = Integer.parseInt(request.getPathParam("id");
        // 省略
    }
}
パスパラメータはhttp-request-routerの記法ではなく、JAX-RSの仕様に従った形で記述する。
これは、本機能(Path アノテーションによるルーティング定義)がJAX-RSの仕様に準拠しているためである。
パスの一部を {パラメータ名} と記述することで、その部分をパラメータとして定義できる。
ここで定義したパラメータ名を JaxRsHttpRequest#getPathParam(String) に渡すことで、パスパラメータの値を取得できる。
さらに、 {パラメータ名 : 正規表現} と記述することで、そのパスパラメータの書式を正規表現で定義できる。
上記実装例では \\d+ と正規表現を指定しているので、パスの値が数値のときのみメソッドがディスパッチされるようになる。

HTTPリクエストのディスパッチの例は次のようになる。

パス HTTPメソッド ディスパッチされるメソッド
/sample/foo/hello GET TestAction#foo(JaxRsHttpRequest)
/sample/foo/world GET TestAction#foo(JaxRsHttpRequest)
/sample/bar/123 GET TestAction#bar(JaxRsHttpRequest)
/sample/bar/987 GET TestAction#bar(JaxRsHttpRequest)

ルーティング定義を一覧で確認する

PathOptionsProviderRoutesMapping によって読み込まれたルーティング定義は、初期化時にデバッグレベルでログに出力される。

デフォルトでは、次のようにしてルーティングの一覧がログに出力される。

2020-07-20 13:35:53.092 -DEBUG- nablarch.integration.router.PathOptionsProviderRoutesMapping [null] boot_proc = [] proc_sys = [jaxrs] req_id = [null] usr_id = [null] GET /api/bar => com.example.BarAction#findAll
GET /api/bar/fizz => com.example.BarAction#fizz
GET /api/foo => com.example.FooAction#findAll
POST /api/foo => com.example.FooAction#register
DELETE /api/foo/(:id) => com.example.FooAction#delete
GET /api/foo/(:id) => com.example.FooAction#find
POST /api/foo/(:id) => com.example.FooAction#update

ログのフォーマットを変更したい場合は、 PathOptionsFormatter を実装したクラスを作り、 PathOptionsProviderRoutesMappingpathOptionsFormatter プロパティに設定する。

<component name="packageMapping" class="nablarch.integration.router.PathOptionsProviderRoutesMapping">
  <property name="methodBinderFactory">
    <!-- 省略 -->
  </property>
  <property name="pathOptionsProvider">
    <!-- 省略 -->
  </property>

  <property name="pathOptionsFormatter">
    <!-- 自作のフォーマットクラスを設定する -->
    <component class="com.example.CustomPathOptionsFormatter" />
  </property>
</component>