如何解决由于使用gradle或其他任何东西使用具有两个不同版本的相同库而引起的NoMethodError?

时间:2016-12-06 19:35:49

标签: apache-spark gradle

我有两个使用相同库但具有不同版本的依赖项,我得到NoM​​ethodError。我不知道如何使用gradle或其他任何东西来解决它?任何帮助都会很棒

group 'com.hello'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'idea'

repositories {
    mavenCentral()
    mavenLocal()
}


dependencies {
    compile 'org.slf4j:slf4j-log4j12:1.7.12'
    compile group: 'org.apache.spark', name: 'spark-core_2.11', version: '2.0.1'
    compile group: 'org.apache.spark', name: 'spark-streaming_2.11', version: '2.0.1'
    compile group: 'org.apache.spark', name: 'spark-streaming-kafka-0-10_2.11', version: '2.0.1'
    compile group:'org.apache.kafka', name: 'kafka-clients', version: '0.10.1.0'
    compile group: 'com.datastax.spark', name: 'spark-cassandra-connector_2.11', version: '2.0.0-M3'
    compile group: 'com.github.brainlag', name: 'nsq-client', version: '1.0.0.RC2'
    compile group: 'com.google.code.gson', name: 'gson', version: '2.7'
}


task buildStreamingJar(type: Jar) {
    if(project.hasProperty("jarname")) {
        def fullyQualifiedPackageName = ""
        def jarname = project.getProperty("jarname")
        if (jarname.equalsIgnoreCase("SparkDriver1")) {
            fullyQualifiedPackageName = "com.hello.streamprocessing.app.SparkDriver1"
        }
        if (jarname.equalsIgnoreCase("SparkDriver2")) {
            fullyQualifiedPackageName = "com.hello.streamprocessing.app.SparkDriver2"
        }

        baseName = project.name + "-$jarname" + "-stream"
        from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
        with jar
        zip64 true
        from sourceSets.test.output
        manifest {
            attributes 'Main-Class': fullyQualifiedPackageName
        }
        exclude 'META-INF/.RSA', 'META-INF/.SF', 'META-INF/*.DSA'
    }
}

所以这里发生的事情就是我的依赖关系spark-core_2.11使用了 com.google.guava:14.0.1和nsq-client使用com.google.guava:19.0

导致以下错误。

Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.collect.Sets.newConcurrentHashSet()Ljava/util/Set;
    at com.github.brainlag.nsq.NSQProducer.(NSQProducer.java:22)
    at com.hello.streamprocessing.app.SparkDriver2.main(SparkDriver2.java:37)

我需要使用这个build.gradle文件来构建一个FAT Uber jar,这样我就可以将它与spark-submit一起使用

2 个答案:

答案 0 :(得分:2)

如果spark-corensq-client使用的guava功能在一个版本或另一个版本中存在或不存在,则基本上无法解决此问题。您可以运行gradlew dependencies,它会向您显示gradle如何解决guava上的版本冲突。默认情况下,它将选择版本19.0作为其新版本。您最好的机会是使用依赖于guava相同版本的库版本。如果可能的话,要么降级nsq-client要么升级spark-core

您可以将传递依赖项排除在guava之外:

dependencies {
...
  compile (group: 'com.github.brainlag', name: 'nsq-client', version: '1.0.0.RC2') {
    exclude group: 'com.google.guava', module: 'guava'
  }
...
}

但是,只有当nsq-client不依赖于上面提到的番石榴版19.0中仅存在的功能时,这才有效。

遗憾的是,这是一个常见问题,尤其是guava库,因为几乎每个项目都使用它,开发人员并不关心其库的稳定API。

您最好的选择可能是尝试从guava中排除spark-core并试一试,如果不能正常工作,请将其从nsq-client中排除并试一试。但是,即使它看起来乍一看可能性很好(或者在你的情况下实际上很糟糕),你将在应用程序的运行期间遇到类似的问题。

如果以上操作不起作用,您仍然可以分叉nsq-client并使用与guava 14.0.1兼容的内容替换有问题的部分。我真的不喜欢这个选项,但如果nsq-client的开发人员很好,他们可能接受你的改变......

答案 1 :(得分:0)

其中一个依赖项lib未被下载。使用两者的最新库。使用也可以使用:

repositories {
    mavenCentral()
}
configurations {
    compile
}
dependencies {
    compile 'dependency repo1'
    compile 'dependency repo2'
}
task libs(type: Sync) {
    from configurations.compile
    into "$buildDir/libs"
}

这将有助于下载两个依赖项。