hello_its_me
hello_its_me

Reputation: 793

Elasticsearch JAR hell error

I created a Java file using Elasticsearch Java API. in NetBeans, everything worked just fine.

However, I started getting the following error:

org/elasticsearch/plugins/PluginsService.java:342:in `loadBundles': java.lang.IllegalStateException: failed to load bundle [file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/license/license-2.0.0.jar, file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/license/license-core-2.0.0.jar, file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/license/license-plugin-api-2.0.0.jar, file:/D:/ELK-2.0/elasticsearch-2.0.0/plugins/marvel-agent/marvel-agent-2.0.0.jar] due to jar hell
        from org/elasticsearch/plugins/PluginsService.java:113:in `<init>'
        from org/elasticsearch/node/Node.java:144:in `<init>'
        from org/elasticsearch/node/NodeBuilder.java:145:in `build'
        from spamdetection/SpamDetection.java:63:in `client'
        from spamdetection/SpamDetection.java:30:in `SpammerDetector'
        from java/lang/reflect/Method.java:497:in `invoke'
        from spam.rb:53:in `(root)'
        from spam.rb:53:in `(root)'
Caused by:
JarHell.java:120:in `parseClassPath': java.lang.IllegalStateException: Classpath should not contain empty elements! (outdated shell script from a previous version?) classpath=''
        from JarHell.java:95:in `parseClassPath'
        from PluginsService.java:338:in `loadBundles'
        from PluginsService.java:113:in `<init>'
        from Node.java:144:in `<init>'
        from NodeBuilder.java:145:in `build'
        from SpamDetection.java:63:in `client'
        from SpamDetection.java:30:in `SpammerDetector'
        from NativeMethodAccessorImpl.java:-2:in `invoke0'
        from NativeMethodAccessorImpl.java:62:in `invoke'
        from DelegatingMethodAccessorImpl.java:43:in `invoke'
        from Method.java:497:in `invoke'
        from JavaMethod.java:451:in `invokeDirectWithExceptionHandling'
        from JavaMethod.java:312:in `invokeDirect'
        from InstanceMethodInvoker.java:45:in `call'
        from CachingCallSite.java:326:in `cacheAndCall'
        from CachingCallSite.java:170:in `call'
        from spam.rb:53:in `__file__'
        from spam.rb:-1:in `load'
        from Ruby.java:857:in `runScript'
        from Ruby.java:850:in `runScript'
        from Ruby.java:729:in `runNormally'
        from Ruby.java:578:in `runFromMain'
        from Main.java:395:in `doRunFromMain'
        from Main.java:290:in `internalRun'
        from Main.java:217:in `run'
        from Main.java:197:in `main'

When trying to call my Java JAR file from JRuby. What's causing this error?

Upvotes: 4

Views: 14204

Answers (5)

Wojciech Wirzbicki
Wojciech Wirzbicki

Reputation: 4382

Since elasticsearch 7.14.0 JarHell class has been moved to org.elasticsearch.jdk package. To disable jar hell checking in Elasticsearch versions >= 7.14 just create below class in org.elasticsearch.jdk package.

package org.elasticsearch.jdk;

import java.net.URL;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;

public class JarHell {
    private JarHell() {}

    public static void checkJarHell(Set<URL> urls, Consumer<String> output) throws Exception {}

    public static void checkJarHell(Consumer<String> output) {}

    public static void checkVersionFormat(String targetVersion) {}

    public static void checkJavaVersion(String resource, String targetVersion) {}

    public static Set<URL> parseClassPath() {
        return new HashSet<>();
    }

    static Set<URL> parseClassPath(String classPath) {
        return new HashSet<>();
    }
}

Upvotes: 0

Yeikel
Yeikel

Reputation: 935

I am late, but I figured that my answer may help others in the future and that's why I am posting it.

I believe that the right solution is to find the root cause and exclude the library that is producing the jar hell rather than hiding the problem. For example, in my case, I had the following duplicated library :

Caused by: java.lang.IllegalStateException: jar hell!
class: org.hamcrest.BaseDescription
jar1: C:\Users\Yeikel\.m2\repository\org\hamcrest\hamcrest-all\1.3\hamcrest-all-1.3.jar
jar2: C:\Users\Yeikel\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar
        at org.elasticsearch.bootstrap.JarHell.checkClass(JarHell.java:275)
        at org.elasticsearch.bootstrap.JarHell.checkJarHell(JarHell.java:192)
        at org.elasticsearch.bootstrap.JarHell.checkJarHell(JarHell.java:89)
        at org.elasticsearch.bootstrap.BootstrapForTesting.<clinit>(BootstrapForTesting.java:90)

All I did to fix the problem is to find the duplication and exclude it from my libraries. In this case, the library was bundled with JUnit as well

<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.hamcrest</groupId>
                    <artifactId>hamcrest-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

Upvotes: 3

jzonthemtn
jzonthemtn

Reputation: 3414

You can now disable the "jar hell" check during tests via the tests.jarhell.check property.

Upvotes: 3

Antoni Myłka
Antoni Myłka

Reputation: 990

You can create a package named org.elasticsearch.bootstrap in your src/test/java, and put this class in there:

package org.elasticsearch.bootstrap;
import java.net.URL;
public class JarHell {
    private JarHell() {}
    public static void checkJarHell() throws Exception {}
    public static void checkJarHell(URL urls[]) throws Exception {}
    public static void checkVersionFormat(String targetVersion) {}
    public static void checkJavaVersion(String resource, String targetVersion) {}
    public static URL[] parseClassPath() {return new URL[]{};}
}

This has the advantage that the production code that uses the node builder to initialize the node can stay clean of any hacks, jar hell check is disabled only in the unit tests.

Upvotes: 17

geekprogrammer
geekprogrammer

Reputation: 1123

If you are getting "jar hell" error while running unit tests, following hack should take care of it - agree that it's not an elegant way.

String originalClassPath = System.getProperty("java.class.path");
  String[] classPathEntries = originalClassPath.split(";");
  StringBuilder esClasspath = new StringBuilder();
       for (String entry : classPathEntries) {
           if (entry.contains("elasticsearch") || entry.contains("lucene")) {
               esClasspath.append(entry);
               esClasspath.append(";");
           }
       }
  System.setProperty("java.class.path", esClasspath.toString());
  node = nodeBuilder().local(true).settings(settings).node();
  System.setProperty("java.class.path", originalClassPath);

Upvotes: 3

Related Questions