Skip to main content
Version: 0.11.0

Java client

The Lucenia Java client (lucenia-java) lets you interact with your Lucenia cluster through Java methods and strongly-typed data structures rather than raw HTTP requests and JSON. The client provides builder-style request objects, response deserialization, and helpers for common operations like indexing, search, bulk loading, and index management.

Compatibility

The lucenia-java client requires Java 21 or later. The artifact version of the client tracks the Lucenia server version: client 0.11.x is intended for use with Lucenia 0.11.x clusters.

Installation

The client is published to Maven Central. Add the dependency to your build.

Maven

In your pom.xml, add the lucenia-java dependency:

<dependencies>
<dependency>
<groupId>io.lucenia.client</groupId>
<artifactId>lucenia-java</artifactId>
<version>0.11.0</version>
</dependency>
</dependencies>

Gradle (Kotlin DSL)

In build.gradle.kts:

repositories {
mavenCentral()
}

dependencies {
implementation("io.lucenia.client:lucenia-java:0.11.0")
}

The default transport (ApacheHttpClient5Transport) is bundled with the client, so no additional HTTP client dependency is required for typical use.

Creating a client

The recommended transport is ApacheHttpClient5Transport, which supports HTTP/1.1 and HTTP/2 and integrates with Apache HttpClient 5's connection pooling, TLS, and authentication.

Connecting to a secured cluster

Lucenia clusters typically run with TLS and basic authentication enabled. The snippet below creates a client that authenticates with a username and password and trusts self-signed certificates — suitable for local development. Use a properly verified trust store in production.

import io.lucenia.client.json.jackson.JacksonJsonpMapper;
import io.lucenia.client.lucenia.LuceniaClient;
import io.lucenia.client.transport.httpclient5.ApacheHttpClient5TransportBuilder;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.ssl.SSLContextBuilder;

var hosts = new HttpHost[] { new HttpHost("https", "localhost", 9200) };

var sslContext = SSLContextBuilder.create()
.loadTrustMaterial(null, (chains, authType) -> true)
.build();

var transport = ApacheHttpClient5TransportBuilder.builder(hosts)
.setMapper(new JacksonJsonpMapper())
.setHttpClientConfigCallback(httpClientBuilder -> {
var credentialsProvider = new BasicCredentialsProvider();
for (var host : hosts) {
credentialsProvider.setCredentials(
new AuthScope(host),
new UsernamePasswordCredentials("admin", "MyStrongPassword123!".toCharArray()));
}

var tlsStrategy = ClientTlsStrategyBuilder.create()
.setSslContext(sslContext)
.setHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();

var connectionManager = PoolingAsyncClientConnectionManagerBuilder.create()
.setTlsStrategy(tlsStrategy)
.build();

return httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.setConnectionManager(connectionManager);
})
.build();

LuceniaClient client = new LuceniaClient(transport);

var info = client.info();
System.out.printf("Connected to %s %s%n",
info.version().distribution(), info.version().number());
warning

The snippet above disables hostname verification and trusts any certificate. This is appropriate only for local development against demo certificates. In production, configure the SSL context with the Lucenia cluster's CA certificate and enable hostname verification.

Connecting to an unsecured cluster

For development clusters running without TLS or authentication, the setup is much simpler:

var hosts = new HttpHost[] { new HttpHost("http", "localhost", 9200) };

var transport = ApacheHttpClient5TransportBuilder.builder(hosts)
.setMapper(new JacksonJsonpMapper())
.build();

LuceniaClient client = new LuceniaClient(transport);

Working with documents

The examples below use a simple IndexData POJO with title and text fields. Define this class (or your own equivalent) with public no-arg constructor and standard getters/setters so the Jackson mapper can deserialize hits into instances.

public class IndexData {
private String title;
private String text;

public IndexData() {}

public IndexData(String title, String text) {
this.title = title;
this.text = text;
}

public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }

public String getText() { return text; }
public void setText(String text) { this.text = text; }
}

Creating an index

Create an index with custom settings and mappings:

import io.lucenia.client.lucenia._types.mapping.IntegerNumberProperty;
import io.lucenia.client.lucenia._types.mapping.Property;
import io.lucenia.client.lucenia._types.mapping.TypeMapping;
import io.lucenia.client.lucenia.indices.CreateIndexRequest;
import io.lucenia.client.lucenia.indices.IndexSettings;

String index = "my-index";

IndexSettings settings = new IndexSettings.Builder()
.numberOfShards("1")
.numberOfReplicas("0")
.build();

TypeMapping mapping = new TypeMapping.Builder()
.properties("age", new Property.Builder()
.integer(new IntegerNumberProperty.Builder().build())
.build())
.build();

client.indices().create(new CreateIndexRequest.Builder()
.index(index)
.settings(settings)
.mappings(mapping)
.build());

Indexing a single document

import io.lucenia.client.lucenia._types.Refresh;
import io.lucenia.client.lucenia.core.IndexRequest;

IndexData doc = new IndexData("Introduction to Lucenia",
"Lucenia is a high-performance search engine.");

client.index(new IndexRequest.Builder<IndexData>()
.index(index)
.id("1")
.document(doc)
.refresh(Refresh.True)
.build());

Bulk indexing

For higher throughput, use the bulk API to send many documents in a single request:

import io.lucenia.client.lucenia.core.BulkRequest;
import io.lucenia.client.lucenia.core.BulkResponse;
import io.lucenia.client.lucenia.core.bulk.BulkOperation;
import io.lucenia.client.lucenia.core.bulk.IndexOperation;
import java.util.ArrayList;

var ops = new ArrayList<BulkOperation>();
ops.add(new BulkOperation.Builder()
.index(IndexOperation.of(io -> io.index(index).id("2")
.document(new IndexData("Getting Started", "Connect with the lucenia-java client."))))
.build());
ops.add(new BulkOperation.Builder()
.index(IndexOperation.of(io -> io.index(index).id("3")
.document(new IndexData("Search Features", "Full-text search, aggregations, and more."))))
.build());

BulkResponse bulkResponse = client.bulk(new BulkRequest.Builder()
.index(index)
.operations(ops)
.refresh(Refresh.WaitFor)
.build());

System.out.printf("Indexed %d documents (errors: %s)%n",
bulkResponse.items().size(), bulkResponse.errors());

Searching

Run a match_all query to return every document in the index:

import io.lucenia.client.lucenia.core.SearchResponse;

SearchResponse<IndexData> response = client.search(s -> s.index(index), IndexData.class);

for (var hit : response.hits().hits()) {
System.out.printf("[%s] %s%n", hit.id(), hit.source());
}

Run a match query against a specific field:

import io.lucenia.client.lucenia._types.FieldValue;
import io.lucenia.client.lucenia.core.SearchRequest;

SearchRequest request = new SearchRequest.Builder()
.index(index)
.query(q -> q.match(m -> m.field("title").query(FieldValue.of("Lucenia"))))
.build();

SearchResponse<IndexData> response = client.search(request, IndexData.class);

for (var hit : response.hits().hits()) {
System.out.printf("[%s] score=%.4f %s%n",
hit.id(), hit.score(), hit.source());
}

Deleting a document and the index

import io.lucenia.client.lucenia.indices.DeleteIndexRequest;

client.delete(d -> d.index(index).id("1"));

client.indices().delete(new DeleteIndexRequest.Builder().index(index).build());

Next steps

The Lucenia Java client supports a wider set of features beyond the basics covered here, including:

  • Authentication with AWS IAM (SigV4)
  • Bulk indexing helpers and streaming bulk
  • Search: aggregations, hybrid search, suggesters
  • Point-in-time search
  • Cat APIs
  • Data streams
  • k-NN plugin integration