A_G
A_G

Reputation: 2370

Embedded elasticsearch test in java application

I use Elasticsearch 7.11.2 with the following dependencies to write unit tests

    implementation 'org.codelibs.elasticsearch.module:lang-painless:7.10.2'
    implementation 'org.codelibs.elasticsearch.module:analysis-common:7.10.2'

Spinning up a node looks like

        public EmbeddedElastic() throws NodeValidationException, IOException {
        tempDir = Files.createTempDirectory("elastic_search_temp").toAbsolutePath().toString();

        int port = getAvailableBasePort();
        Map<String, String> settings = new HashMap<>();
        settings.put("path.home", tempDir);
        settings.put("http.port", Integer.toString(port));
        settings.put("transport.tcp.port", Integer.toString(port + 1));
        settings.put("transport.type", "netty4");
        settings.put("http.cors.enabled", Boolean.FALSE.toString());
        new PluginNode(settings).start();
        client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", port, "http")));

        System.out.println("Client: " + client.getClass().getName());
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // file deletion
            }
        });
    }

    private static class PluginNode extends Node {
        public PluginNode(Map<String, String> preparedSettings) {
            super(InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, preparedSettings,
                                                              null, () -> "node-test"),
                  Lists.newArrayList(Netty4Plugin.class, ParentJoinPlugin.class, CommonAnalysisPlugin.class,
                                     PainlessPlugin.class),
                  false);
            System.out.println("Started local elastic with PainlessPlugin loaded.");
        }
    }

Now I am upgrading to ES 7.16.2 and the same code doesn't work well. I presume its because of the lang-painless and analysis-common libraries. Their latest version is only 7.10.

The exception I receive after upgrading the elasticsearch client to 7.16 and spring-data-elasticsearch to 4.3.0

Failed to instantiate [org.springframework.data.elasticsearch.core.ElasticsearchOperations]: Factory method 'elasticsearchTemplate' threw exception; nested exception is java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: org/elasticsearch/common/xcontent/ToXContentObject

Before I dive deep into fixing it, I am wondering if anyone has actually made unit tests work with 7.16 ES version? I have seen that Elasticsearch Test containers is the recommended way to go

EDIT:

Thanks to Augusto's tip on checking classes in Maven Central, I found out that lang-painless depends on certain libraries from elasticsearch client which are not available in the higher versions of ES client. So its not possible to write unit tests with the same libs.

Upvotes: 2

Views: 3689

Answers (2)

Abacus
Abacus

Reputation: 19471

Elasticsearch moved this class in 7.16 from the org.elasticsearch.common.xcontent package to the org.elasticsearch.xcontent package, a breaking change between 7.15 and 7.16.

Spring Data Elasticsearch 4.3 is built against 7.15.x and so won't work with Elasticsearch 7.16 libraries.

You either need to use Elasticsearch 7.15 or wait for Spring Data Elasticsearch 4.4 (the first milestone for that should be published next week) to be released which is built against 7.16.

And, yes, you should better use testcontainers.

Upvotes: 4

Augusto
Augusto

Reputation: 30062

You are probably missing the dependency with this class. It could be that before it came transitevily with the ES client.

Try adding org.elasticsearch:elasticsearch-x-content:7.15.2 to your build tool. A word of caution, you might be missing other dependencies too.

Just as a tip, if you ever get a NoClassDefFoundError, one of the easiest ways to find where that class is defined is to search in maven central. Search for fc:<fully_qualified_class_name>, and it will show all the jars where the class is present.

Upvotes: 1

Related Questions