Vladimir Salin
Vladimir Salin

Reputation: 3030

Using Neo4j EmbeddedDriver with Spring Boot & SDN fails with dependency issue on application startup

Spring Boot fails to start the application with EmbeddedDriver configured, when it comes to application context initialization. It raises UnsatisfiedDependencyException, unrolled it points to NoClassDefFoundError:

Caused by: java.lang.NoClassDefFoundError: org/apache/lucene/document/Fieldable
at org.neo4j.kernel.api.impl.index.NodeRangeDocumentLabelScanStorageStrategy.<init>(NodeRangeDocumentLabelScanStorageStrategy.java:71) ~[neo4j-lucene-index-2.3.6.jar:2.3.6]
at org.neo4j.kernel.api.impl.index.LuceneLabelScanStoreExtension.newInstance(LuceneLabelScanStoreExtension.java:72) ~[neo4j-lucene-index-2.3.6.jar:2.3.6]
at org.neo4j.kernel.api.impl.index.LuceneLabelScanStoreExtension.newInstance(LuceneLabelScanStoreExtension.java:39) ~[neo4j-lucene-index-2.3.6.jar:2.3.6]
at org.neo4j.kernel.extension.KernelExtensions.init(KernelExtensions.java:69) ~[neo4j-kernel-2.3.6.jar:2.3.6,7dc1b59]
at org.neo4j.kernel.lifecycle.LifeSupport$LifecycleInstance.init(LifeSupport.java:424) ~[neo4j-kernel-2.3.6.jar:2.3.6,7dc1b59]
... 197 common frames omitted

I also have EmbeddedDriver in Gradle dependencies:

compile 'org.neo4j:neo4j-ogm-embedded-driver:2.0.4'

And it looks like this artifact requires neo4j:2.3.6 (while artifact from Spring Boot starter comes with 3.0.x version), which in turn depends on neo4j-lucene-index:2.3.6 and finally brings in lucene-core:3.6.2.

I checked other dependencies and it seems that actual version of apache-lucene used by our application is 5.5.0, which in turn doesn't contain Fieldable interface at all. Most likely it comes from Hibernate dependencies (we also use it for JPA) and so Gradle resolves the higher one to put into runtime.

Not sure whether it helps, I follow Java-based configuration to setup EmbeddedDriver:

@org.springframework.context.annotation.Configuration
@Profile("test")
public class TestNeo4jConfig extends Neo4jConfig {

    @Override
    public Configuration getConfiguration() {
        Configuration configuration = new Configuration();
        configuration
                .driverConfiguration()
                .setURI("file:///var/tmp/graph.db");
        return configuration;
    }
}

Appreciate any help with this issue.

Update:

Relevant dependencies from build.gradle:

dependencies {
    // Spring Boot
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-data-elasticsearch')
    compile('org.springframework.boot:spring-boot-starter-data-neo4j')
    compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.2")

    // JPA
    runtime 'org.postgresql:postgresql'
    compile 'org.jadira.usertype:usertype.extended:5.0.0.GA'
    compile 'org.hibernate:hibernate-java8'

    // OGM
    compile 'org.neo4j.driver:neo4j-java-driver:1.0.4'
    runtime 'org.neo4j:neo4j-ogm-bolt-driver:2.0.4'
    runtime 'org.neo4j:neo4j-ogm-embedded-driver:2.0.4'
}

Update 2:

Dependency onlucene-core:5.5.0 comes from Elasticsearch or, to be more precise, from Spring Boot starter for ES (as we use Spring Data repositories for ES):

+--- org.springframework.boot:spring-boot-starter-data-elasticsearch: -> 1.4.0.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:1.4.0.RELEASE (*)
|    \--- org.springframework.data:spring-data-elasticsearch:2.0.2.RELEASE
|         +--- org.springframework:spring-context:4.2.6.RELEASE -> 4.3.2.RELEASE (*)
|         +--- org.springframework:spring-tx:4.2.6.RELEASE -> 4.3.2.RELEASE (*)
|         +--- org.springframework.data:spring-data-commons:1.12.2.RELEASE (*)
|         +--- commons-lang:commons-lang:2.6
|         +--- joda-time:joda-time:2.9.4
|         +--- org.elasticsearch:elasticsearch:2.2.0 -> 2.3.4
|         |    +--- org.apache.lucene:lucene-core:5.5.0

I've tried to exclude this transient dependency on lucene-core:5.5.0, as @digx1 proposed, no luck here:

Caused by: java.lang.NoSuchFieldError: LUCENE_4_0_0
    at org.elasticsearch.Version.<clinit>(Version.java:44)

Version 3.6.2 seems to be too low.

Will try another way with increasing neo4j's dependency to 3.0.4 core and see what will happen.

Upvotes: 1

Views: 566

Answers (2)

digx1
digx1

Reputation: 1088

This can be a frustrating issue with using open source libraries and transient dependencies.

So how can you fix this? You will have to identify the origin of transient dependency for the lucene-core:5.5.0 library. You can do this by simply typing in gradle dependencies at the root of your gradle project.

Once you have found the offending dependency you will need to exclude it. There are several ways to do this but the following way should be fine. Let's say the offending jar was hibernate-java8. Then you can exclude the transient dependency like so:

compile ('org.hibernate:hibernate-java8') {
    exclude group: "org.apache.lucene", module: "lucene-core"
}

Now, when you recompile the 5.5.0 version of lucene-core will be ignored and the classloader will now use the 3.6.2 one defined. A problem can occur if the excluded jar had code required at compile or runtime by the dependent jar that isn't present in the old version. If this is the case you are in a spot of bother and might have to explore the idea of repackaging lucene-core or something equally drastic.

Good luck!

Upvotes: 1

Mike Summers
Mike Summers

Reputation: 2239

ogm 2.0.4 depends on neo4j 2.3.6 which depends on lucene-core 3.6.2:

+--- org.neo4j:neo4j-ogm-bolt-driver:2.0.4
|    +--- org.neo4j:neo4j-ogm-api:2.0.4 (*)
|    +--- org.neo4j:neo4j:2.3.6
|    |    +--- org.neo4j:neo4j-kernel:2.3.6
|    |    |    +--- org.neo4j:neo4j-primitive-collections:2.3.6
|    |    |    |    +--- org.neo4j:neo4j-unsafe:2.3.6
|    |    |    |    \--- org.neo4j:neo4j-function:2.3.6
|    |    |    +--- org.neo4j:neo4j-io:2.3.6
|    |    |    |    +--- org.neo4j:neo4j-unsafe:2.3.6
|    |    |    |    +--- org.neo4j:neo4j-primitive-collections:2.3.6 (*)
|    |    |    |    \--- org.apache.commons:commons-lang3:3.3.2 -> 3.4
|    |    |    +--- org.neo4j:neo4j-csv:2.3.6
|    |    |    |    \--- org.neo4j:neo4j-primitive-collections:2.3.6 (*)
|    |    |    \--- org.neo4j:neo4j-logging:2.3.6
|    |    |         \--- org.neo4j:neo4j-io:2.3.6 (*)
|    |    +--- org.neo4j:neo4j-lucene-index:2.3.6
|    |    |    +--- org.neo4j:neo4j-kernel:2.3.6 (*)
|    |    |    \--- org.apache.lucene:lucene-core:3.6.2 -> 5.5.0

You can start with @digx1 's suggestion, you may get lucky and not run into any further issues.

I'd probably clone https://github.com/neo4j/neo4j-ogm and build a new ogm 2.0.5-SNAPSHOT that depends on neo4j 3.0.4, I don't know if that's ok in your case though.

Upvotes: 1

Related Questions