I recently began diving into ElasticSearch and trying to learn the Java API. While the documentation is actually good, it also doesn't provide a clear big picture.

After a few hours on trial and error, I was finally able to come up with a CDI producer which is @ApplicationScored. From my googling, it does seem that the ElasticSearch clients are thread-safe.

Below is my producer class.

CDI qualifier annotation

package com.brandonlamb.elasticsearch;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

public @interface ElasticSearchClient {

CDI producer class

package com.brandonlamb.elasticsearch;

import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeBuilder;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Startup;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;

import lombok.extern.java.Log;

public class ClientProducer {

    private Client client;
    private final String hosts = "host1:9300, host2:9300";
    private final String clusterName = "my-cluster;

    public void postConstruct() {
        final Settings settings = ImmutableSettings.settingsBuilder()
                .put("http.enabled", false)
                .put("client.transport.sniff", true)
                .put("cluster.name", clusterName)
                .put("discovery.zen.ping.unicast.hosts", hosts)

        final Node node = NodeBuilder.nodeBuilder()

        client = node.client();

    public Client getClient() {
        return client;

    public void preDestroy() {

Now to use this, I simply inject into a DAL/Repository object.

@ElasticSearchClient // provided by me/you, not some built-in
private Client client;