コンテンツにスキップ

Javaガイド

Java連携は、小さなlauncherとJUnit 5 extensionで構成されます。Go製サーバーを子プロセスとして起動し、Docker内にJVMを立てる方式ではありません。テストクラス全体でseed済みbaseを再利用しつつ、各テストメソッドには専用のforkを渡せます。

テストを実行するマシンに合ったbinary classifierを選びます。以下はCIをLinux amd64とした例です。環境に応じてdarwin-arm64linux-arm64windows-amd64windows-arm64に置き換えてください。公式opensearch-javaクライアントはApache HttpClient 5 transportを使います。

dependencies {
testImplementation("io.github.shibukawa.osmem:osmem:0.1.0")
testImplementation("io.github.shibukawa.osmem:osmem-server-binaries:0.1.0:linux-amd64")
testImplementation("org.opensearch.client:opensearch-java:2.19.0")
testImplementation("org.apache.httpcomponents.client5:httpclient5:5.2.1")
testImplementation("org.junit.jupiter:junit-jupiter:5.11.4")
}

classifierはテスト実行ホストに合わせます。開発機とCIでOSが異なる場合、両方のplatform artifactを依存関係に含めます。ローカルビルドを使うならOSMEM_SERVER_BINまたはosmem.server.bin system propertyでbinaryを指定できます。

例のcoordinatesは0.1.0です。今後のosmem package releaseは1.<OpenSearchメジャー>.<osmemのrelease番号>(現在予定している系列は1.9.y)にする予定です。Maven Centralで実際に公開されているversionを指定してください。これはopensearch-java clientのversionとは独立しています。

例では、このosmemリリースのサーバーAPIに合わせてOpenSearch Java clientを2.19.0に固定しています。client versionを変更する場合は公式Java clientガイドを確認してください。

起動し、schemaとseed dataを登録して検索する

Section titled “起動し、schemaとseed dataを登録して検索する”

単発の連携確認やJUnit以外のframeworkでは、serverを直接管理します。準備には通常のREST APIを使い、検索は公式クライアントから送ります。

import org.apache.hc.core5.http.HttpHost;
import java.nio.file.Path;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.transport.OpenSearchTransport;
import org.opensearch.client.transport.httpclient5.ApacheHttpClient5TransportBuilder;
import io.github.shibukawa.osmem.OsmemServer;
try (OsmemServer server = OsmemServer.builder().japanese(false).start()) {
server.request("PUT", "/products",
"{\"mappings\":{\"properties\":{\"name\":{\"type\":\"text\",\"fields\":{\"keyword\":{\"type\":\"keyword\"}}}}}}}");
server.request("PUT", "/products/_doc/1", "{\"name\":\"Red Apple\"}");
try (OpenSearchTransport transport = ApacheHttpClient5TransportBuilder
.builder(HttpHost.create(server.url())).build()) {
OpenSearchClient client = new OpenSearchClient(transport);
var result = client.search(s -> s.index("products")
.query(q -> q.match(m -> m.field("name").query("apple"))),
java.util.Map.class);
System.out.println(result.hits().hits());
}
}

fixtureを繰り返し使う場合、mappingとdocumentは共通のseed directoryに置き、OsmemServer.builder().seed(Path.of("src/test/resources/seed"))に渡せます。

baseを再利用し、書き換えるテストはforkする

Section titled “baseを再利用し、書き換えるテストはforkする”

OsmemExtensionはテストクラスの前にserverを1つ起動し、seedを投入してbaseを凍結します。その後、各テストメソッドの前後で専用cloneを作成・破棄します。

@RegisterExtension
static OsmemExtension osmem = OsmemExtension.seed(Path.of("src/test/resources/seed"));
@Test
void addsAProduct(OsmemClone clone) {
OpenSearchClient client = clientFor(clone.url());
client.index(i -> i.index("products").id("x").document(Map.of("name", "new")));
assertTrue(client.get(g -> g.index("products").id("x"), Map.class).found());
}

documentの書き込み、mappingの変更、indexの作成・削除など、indexの状態を変えるテストではOsmemCloneを使います。読み取り専用テストはOsmemServerを受け取り、baseを検索できます。この構成なら初期化はクラス単位で共有しつつ、変更するテストごとにforkを分けられます。cloneは変更していないデータをbaseと共有し、最初のwrite時に対象indexを複製します。cloneを閉じれば変更は破棄されます。

schemaや起動optionが異なる場合に限り、テスト内で新しいOsmemServerを作ります。読み取り専用テストはメソッド引数にOsmemCloneの代わりにOsmemServerを宣言し、baseを検索できます。書き換え可能なcloneをテストメソッド間で共有しないでください。

毎回まったく新しいserverが必要なら、try-with-resourcesでテスト自身が所有します。

@Test
void isolatedSetup() {
try (OsmemServer server = OsmemServer.builder()
.seed(Path.of("src/test/resources/seed")).start()) {
OpenSearchClient client = clientFor(server.url());
// test専用schemaを登録するか、読み取り処理を検証する
}
}

clientForはclone URLを受け取る通常のOpenSearch client setupです。

static OpenSearchClient clientFor(String url) {
var transport = ApacheHttpClient5TransportBuilder.builder(HttpHost.create(url)).build();
return new OpenSearchClient(transport);
}

不要になったらtransportを閉じてください。JUnit以外でもOsmemServerOsmemCloneAutoCloseableとして使えます。

OsmemServerOsmemCloneAutoCloseableです。JUnit以外ではtry-with-resourcesで囲み、書き込み用のforkにはserver.clone()を使い、任意のHTTP clientをclone.url()へ接続します。

launcherは、まずosmem.server.bin system property、次にOSMEM_SERVER_BIN、最後にclasspath上の一致するosmem-server-binaries classifierを探します。classifier内のbinaryは初回起動時にtemporary directoryへ展開されます。標準入力が閉じたとき、親JVMが終了したとき、またはclose()時にserver processも終了します。