Using elasticsearch 1.x and 2.x from java client


(Ivan Kuznetsov) #1

Hello, dear developers!

Sorry for this mad thing... but we need to support search on old clusters with Elasticsearch 1.x
and new clusters with Elasticsearch 2.x

We have own java client to pass search requests to cluster using elasticsearch as a dependency library. To do this feature, I decided to use two different versions of elasticsearch as a dependency, but keep 1.x jar separately from clath path and perform loading this version using URLClassLoader to avoid conflicts of the same classes from differently versioned jars. And what I have done inside that java client: I have made interface for accessing search and two interface implementations for 1.7/2.3 versions of Elasticsearch, but I'm stuck with this strange error when I try to launch client:

    Exception in thread "main" java.lang.IncompatibleClassChangeError: Implementing class
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at Main.main(Main.java:13)

Error occurs on trying to load class ImmutableSettings.Builder.

This error is reproducible with this simple code:

    public class Main {
        public static void main(String... args) throws Exception {
            File file = new File("elasticsearch-1.7.3.jar");
            if(!file.exists()) {
                throw new Exception("jar not found: " + file);
            }
            // file really exists and it is correct jar
            URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{file.toURI().toURL()});
            // fail on the line below:
            Class<?> clzz = urlClassLoader.loadClass("org.elasticsearch.common.settings.ImmutableSettings");
            System.out.println(Arrays.toString(clzz.getMethods()));
        }
    }

By this answer on Stackoverflow, I assume that interface Settings.Builder which is implemented by ImmutableSettings.Builder, somehow became a class.

But we run 1.7.3 successfully!
Is it real error what it says about or it something else?


(Ivan Kuznetsov) #2

I'm so stupid... If I spent more time, I wouldn't created this topic...

This error really take a place and that's why: ImmutableSettings will be loaded from 1.x jar, but Settings will be loaded from 2.x jar as it exists in 2.x jar which is in class path. The cause is in class loading strategy where system class loader will first try to find and load class, and only after it URLClassLoader will try to do the same.

Sorry for disturbing.


(system) #3