Creating a CDI Producer for an ElasticSearch Node Client

Oct 13, 2018 1 min read

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;

@Qualifier
@Retention(RUNTIME)
@Target({FIELD, TYPE, METHOD})
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;

@ApplicationScoped
@Startup
@Log
public class ClientProducer {

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

    @PostConstruct
    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)
                .build();

        final Node node = NodeBuilder.nodeBuilder()
                .settings(settings)
                .client(true)
                .node()
                .start();

        client = node.client();
    }

    @Produces
    @ElasticSearchClient
    public Client getClient() {
        return client;
    }

    @PreDestroy
    public void preDestroy() {
        client.close();
    }
}

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

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

Join the conversation

Great! Next, complete checkout for full access to Brandon's Blog.
Welcome back! You've successfully signed in.
You've successfully subscribed to Brandon's Blog.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info has been updated.
Your billing was not updated.