1. 概要

Apache Camel は、多くの既知の Enterprise IntegrationPatternsを実装する強力なオープンソース統合フレームワークです。

通常、Camelを使用してメッセージルーティングを操作する場合は、サポートされている多くのプラグ可能なデータ形式の1つを使用する必要があります。 JSONは最新のAPIとデータサービスのほとんどで人気があることを考えると、JSONは当然の選択になります。

このチュートリアルでは、 camel-jacksonコンポーネントを使用して、JSON配列をJavaオブジェクトのリストにアンマーシャリングするいくつかの方法を見ていきます。

2. 依存関係

まず、camel-jackson依存関係pom.xmlに追加しましょう。

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-jackson</artifactId>
    <version>3.6.0</version>
</dependency>

次に、ユニットテスト専用の camel-test 依存関係も追加します。これは、 MavenCentralからも入手できます。

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-test</artifactId>
    <version>3.6.0</version>
</dependency>

3. フルーツドメインクラス

このチュートリアル全体を通して、いくつかのライト POJO オブジェクトを使用して、フルーツドメインをモデル化します。

先に進んで、果物を表すIDと名前を使用してクラスを定義しましょう。

public class Fruit {

    private String name;
    private int id;

    // standard getter and setters
}

次に、Fruitオブジェクトのリストを保持するコンテナーを定義します。

public class FruitList {

    private List<Fruit> fruits;

    public List<Fruit> getFruits() {
        return fruits;
    }

    public void setFruits(List<Fruit> fruits) {
        this.fruits = fruits;
    }
}

次のいくつかのセクションでは、フルーツのリストを表すJSON文字列をこれらのドメインクラスにアンマーシャリングする方法を説明します。 最終的に私たちが探しているのは、List型の変数です。 一緒に仕事ができること

4. JSONのアンマーシャリングFruitList

この最初の例では、JSON形式を使用して果物の簡単なリストを表します。

{
    "fruits": [
        {
            "id": 100,
            "name": "Banana"
        },
        {
            "id": 101,
            "name": "Apple"
        }
    ]
}

とりわけ、このJSONは、配列を含むfruitsというプロパティを含むオブジェクトを表すことを強調する必要があります。

次に、Apache Camel route を設定して、逆シリアル化を実行します。

@Override
protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            from("direct:jsonInput")
              .unmarshal(new JacksonDataFormat(FruitList.class))
              .to("mock:marshalledObject");
        }
    };
}

この例では、directエンドポイントをjsonInputという名前で使用します。 次に、 unmarshal メソッドを呼び出します。このメソッドは、指定されたデータ形式を使用して、Camel交換でメッセージ本文をアンマーシャリングします。

カスタムのアンマーシャルタイプでJacksonDataFormatクラスを使用しています FruitList。 これは基本的に、 Jackon ObjectMapper JSONとの間でマーシャリングを行います。

最後に、 unmarshal メソッドの結果を、marshalledObjectと呼ばれるmockエンドポイントに送信します。 これから説明するように、これがルートをテストして、正しく機能しているかどうかを確認する方法です。

それを念頭に置いて、先に進み、最初の単体テストを作成しましょう。

public class FruitListJacksonUnmarshalUnitTest extends CamelTestSupport {

    @Test
    public void givenJsonFruitList_whenUnmarshalled_thenSuccess() throws Exception {
        MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
        mock.expectedMessageCount(1);
        mock.message(0).body().isInstanceOf(FruitList.class);

        String json = readJsonFromFile("/json/fruit-list.json");
        template.sendBody("direct:jsonInput", json);
        assertMockEndpointsSatisfied();

        FruitList fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(FruitList.class);
        assertNotNull("Fruit lists should not be null", fruitList);

        List<Fruit> fruits = fruitList.getFruits();
        assertEquals("There should be two fruits", 2, fruits.size());

        Fruit fruit = fruits.get(0);
        assertEquals("Fruit name", "Banana", fruit.getName());
        assertEquals("Fruit id", 100, fruit.getId());

        fruit = fruits.get(1);
        assertEquals("Fruit name", "Apple", fruit.getName());
        assertEquals("Fruit id", 101, fruit.getId());
    }
}

テストの重要な部分を見ていき、何が起こっているのかを理解しましょう。

  • まず最初に、CamelTestSupportクラスを拡張することから始めます。これは便利なテストユーティリティの基本クラスです。
  • 次に、テストの期待値を設定します。 mock 変数には1つのメッセージが必要であり、メッセージタイプはFruitListである必要があります。
  • これで、JSON入力ファイルを文字列として前に定義した直接エンドポイントに送信する準備が整いました。
  • 模擬の期待が満たされていることを確認した後、 FruitList を自由に取得して、内容が期待どおりであることを確認できます。

このテストは、ルートが正しく機能しており、JSONが期待どおりにマーシャリングされていないことを確認します。 素晴らしい!

5. JSON Fruit配列のアンマーシャリング

一方、Fruitオブジェクトを保持するためにコンテナオブジェクトを使用することは避けたいと思います。 JSONを変更して、フルーツ配列を直接保持することができます。

[
    {
        "id": 100,
        "name": "Banana"
    },
    {
        "id": 101,
        "name": "Apple"
    }
]

今回は、ルートはほぼ同じですが、JSON配列で特に機能するように設定しました。

@Override
protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            from("direct:jsonInput")
              .unmarshal(new ListJacksonDataFormat(Fruit.class))
              .to("mock:marshalledObject");
        }
    };
}

ご覧のとおり、前の例との唯一の違いは、ListJacksonDataFormatクラスをFruitのカスタムアンマーシャルタイプで使用していることです。 これは、リストを操作するために直接準備されたJacksonデータ形式タイプです

同様に、単体テストは非常に似ています。

@Test
public void givenJsonFruitArray_whenUnmarshalled_thenSuccess() throws Exception {
    MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
    mock.expectedMessageCount(1);
    mock.message(0).body().isInstanceOf(List.class);

    String json = readJsonFromFile("/json/fruit-array.json");
    template.sendBody("direct:jsonInput", json);
    assertMockEndpointsSatisfied();

    @SuppressWarnings("unchecked")
    List<Fruit> fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(List.class);
    assertNotNull("Fruit lists should not be null", fruitList);

    // more standard assertions
}

ただし、前のセクションで見たテストに関しては、2つの微妙な違いがあります。

  • 最初に、List.classを直接含む本文を含むモック期待値を設定します
  • メッセージ本文をList.classとして取得すると、型の安全性に関する標準の警告が表示されます。したがって、 @SuppressWarnings( “unchecked”)を使用します。

6. 結論

この短い記事では、ラクダのメッセージルーティングとcamel-jacksonコンポーネントを使用してJSON配列をアンマーシャリングするための2つの簡単なアプローチを見てきました。

いつものように、記事の完全なソースコードは、GitHubから入手できます。