Ratpackの紹介

Ratpackの概要

1. 概要

Ratpackは、現代の高性能リアルタイムアプリケーション用に構築されたJVMベースのライブラリのセットです。 組み込みのNettyイベント駆動型ネットワークエンジンの上に構築されており、リアクティブデザインパターンに完全に準拠しています。

この記事では、Ratpackの使用方法を学び、それを使用して小さなアプリケーションを構築します。

2. なぜラットパック?

Ratpackの主な利点:

  • 非常に軽量、高速、スケーラブルです

  • DropWizardなどの他のフレームワークよりも少ないメモリを消費します。興味深いベンチマーク比較結果が見つかりますhere

  • Nettyの上に構築されているため、Ratpackは完全にイベント駆動型であり、本質的に非ブロッキングです。

  • Guiceの依存関係管理をサポートしています

  • SpringBootと同様に、Ratpackには、テストケースをすばやくセットアップするための独自のテストライブラリがあります。

3. アプリケーションの作成

Ratpackがどのように機能するかを理解するために、Ratpackを使用して小さなアプリケーションを作成することから始めましょう。

3.1. Mavenの依存関係

まず、次の依存関係をpom.xml:に追加しましょう


    io.ratpack
    ratpack-core
    1.4.5


    io.ratpack
    ratpack-test
    1.4.5

MavenCentralで最新バージョンを確認できます。

ビルドシステムとしてMavenを使用していますが、Ratpack recommendationに従って、RatpackはRatpack’s Gradle pluginを介して提供されるファーストクラスのGradleサポートを備えているため、ビルドツールとしてGradleを使用することをお勧めします。

次のビルドGradleスクリプトを使用できます。

buildscript {
    repositories {
      jcenter()
    }
    dependencies {
      classpath "io.ratpack:ratpack-gradle:1.4.5"
    }
}

apply plugin: "io.ratpack.ratpack-java"
repositories {
    jcenter()
}
dependencies {
    testCompile 'junit:junit:4.11'
    runtime "org.slf4j:slf4j-simple:1.7.21"
}
test {
    testLogging {
      events 'started', 'passed'
    }
}

3.2. アプリケーションの構築

ビルド管理を構成したら、組み込みNettyサーバーを起動するクラスを作成し、デフォルトのリクエストを処理するための単純なコンテキストをビルドする必要があります。

public class Application {

    public static void main(String[] args) throws Exception {
        RatpackServer.start(server -> server.handlers(chain -> chain
          .get(ctx -> ctx.render("Welcome to example ratpack!!!"))));
    }
}

ご覧のとおり、RatpackServerを使用して、サーバーを起動できます(デフォルトのポート5050)。 handlers()メソッドは、Chainオブジェクトを受け取る関数を取ります。このオブジェクトは、それぞれの着信要求をすべてマップします。 この「ハンドラチェーンAPI」は、応答処理戦略を構築するために使用されます。

このコードスニペットを実行し、ブラウザのhttp://localhost:5050を押すと、「サンプルラットパックへようこそ!!!」表示されます。

同様に、HTTP POSTリクエストをマップできます。

3.3. URLパスパラメータの処理

次の例では、アプリケーションでURLパスパラメーターをキャプチャする必要があります。 Ratpackでは、PathTokensを使用してそれらをキャプチャします。

RatpackServer.start(server -> server
  .handlers(chain -> chain
  .get(":name", ctx -> ctx.render("Hello "
  + ctx.getPathTokens().get("name") + " !!!"))));

ここでは、nameのURLパラメータをマッピングしています。 http://localhost:5050/Johnのようなリクエストが来ると、応答は「HelloJohn !!!」になります。

3.4. Request/Response Header Modification With/Without Filter

場合によっては、必要に応じてインラインHTTP応答ヘッダーを変更する必要があります。 Ratpackには、発信応答をカスタマイズするためのMutableHeadersがあります。

たとえば、応答の次のヘッダーを変更する必要があります:Access-Control-Allow-OriginAccept-Language、およびAccept-Charset

RatpackServer.start(server -> server.handlers(chain -> chain.all(ctx -> {
    MutableHeaders headers = ctx.getResponse().getHeaders();
    headers.set("Access-Control-Allow-Origin", "*");
    headers.set("Accept-Language", "en-us");
    headers.set("Accept-Charset", "UTF-8");
    ctx.next();
}).get(":name", ctx -> ctx
    .render("Hello " + ctx.getPathTokens().get("name") + "!!!"))));

MutableHeadersを使用することにより、3つのヘッダーを設定し、それらをChainにプッシュします。

同様に、着信リクエストヘッダーも確認できます。

ctx.getRequest().getHeaders().get("//TODO")

同じことは、フィルターを作成することで実現できます。 Ratpackには、フィルターを作成するために実装できるHandlerインターフェース,があります。 現在のContextをパラメーターとして受け取るメソッドhandle(),は1つだけです。

public class RequestValidatorFilter implements Handler {

    @Override
    public void handle(Context ctx) throws Exception {
        MutableHeaders headers = ctx.getResponse().getHeaders();
        headers.set("Access-Control-Allow-Origin", "*");
        ctx.next();
    }
}

このフィルターは次の方法で使用できます。

RatpackServer.start(
    server -> server.handlers(chain -> chain
      .all(new RequestValidatorFilter())
      .get(ctx -> ctx.render("Welcome to example ratpack!!!"))));
}

3.5. JSONパーサー

Ratpackは内部的にJSON解析にfaster-jacksonを使用します。 Jacksonモジュールを使用して、任意のオブジェクトをJSONに解析できます。

解析に使用される単純なPOJOクラスを作成しましょう。

public class Employee {

    private Long id;
    private String title;
    private String name;

    // getters and setters

}

ここでは、id, titlenameの3つのパラメーターを持つEmployeeという名前の1つの単純なPOJOクラスを作成しました。 次に、このEmployeeオブジェクトを使用してJSONに変換し、特定のURLがヒットしたときに同じものを返します。

List employees = new ArrayList();
employees.add(new Employee(1L, "Mr", "John Doe"));
employees.add(new Employee(2L, "Mr", "White Snow"));

RatpackServer.start(
    server -> server.handlers(chain -> chain
      .get("data/employees",
      ctx -> ctx.render(Jackson.json(employees)))));

ご覧のとおり、2つのEmployeeオブジェクトを手動でリストに追加し、Jacksonモジュールを使用してそれらをJSONとして解析しています。 /data/employees URLがヒットするとすぐに、JSONオブジェクトが返されます。

ここで注意すべき点は、RatpackのJacksonモジュールが必要な処理をその場で行うため、we are not using ObjectMapper at allであるということです。

3.6. インメモリデータベース

Ratpackには、インメモリデータベースのファーストクラスサポートがあります。 JDBC接続プールにHikariCPを使用します。 これを使用するには、RatpackのHikariCP module dependencypom.xmlに追加する必要があります。


    io.ratpack
    ratpack-hikari
    1.4.5

Gradleを使用している場合は、同じものをGradleビルドファイルに追加する必要があります。

compile ratpack.dependency('hikari')

次に、サーバーが起動してすぐにテーブルが作成されるように、テーブルDDLステートメントを含むSQLファイルを作成する必要があります。 src/main/resourcesディレクトリにDDL.sqlファイルを作成し、それにいくつかのDDLステートメントを追加します。

H2データベースを使用しているため、その依存関係も追加する必要があります。

これで、HikariModuleを使用して、実行時にデータベースを初期化できます。

RatpackServer.start(
    server -> server.registry(Guice.registry(bindings ->
      bindings.module(HikariModule.class, config -> {
          config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
          config.addDataSourceProperty("URL",
          "jdbc:h2:mem:example;INIT=RUNSCRIPT FROM 'classpath:/DDL.sql'");
      }))).handlers(...));

4. テスト

前述のように、RatpackはjUnitテストケースのファーストクラスサポートを備えています。 MainClassApplicationUnderTestを使用することで、テストケースを簡単に作成し、エンドポイントをテストできます。

@RunWith(JUnit4.class)
public class ApplicationTest {

    MainClassApplicationUnderTest appUnderTest
      = new MainClassApplicationUnderTest(Application.class);

    @Test
    public void givenDefaultUrl_getStaticText() {
        assertEquals("Welcome to example ratpack!!!",
          appUnderTest.getHttpClient().getText("/"));
    }

    @Test
    public void givenDynamicUrl_getDynamicText() {
        assertEquals("Hello dummybot!!!",
          appUnderTest.getHttpClient().getText("/dummybot"));
    }

    @Test
    public void givenUrl_getListOfEmployee()
      throws JsonProcessingException {

        List employees = new ArrayList();
        ObjectMapper mapper = new ObjectMapper();
        employees.add(new Employee(1L, "Mr", "John Doe"));
        employees.add(new Employee(2L, "Mr", "White Snow"));

        assertEquals(mapper.writeValueAsString(employees),
          appUnderTest.getHttpClient().getText("/data/employees"));
    }

    @After
    public void shutdown() {
        appUnderTest.close();
    }

}

JVMリソースを不必要にブロックする可能性があるため、close()メソッドを呼び出して、実行中のMainClassApplicationUnderTestインスタンスを手動で終了する必要があることに注意してください。 そのため、テストケースが実行されると、@Afterアノテーションを使用してインスタンスを強制的に終了しました。

5. 結論

この記事では、Ratpackのシンプルな使用方法を説明しました。

いつものように、完全なソースコードはover on GitHubで利用できます。