Corda Dependency Conflicts在使用类星体代理时阻止调用Classloader

时间:2018-02-27 11:07:03

标签: corda

这是关于corda的github问题的my post的副本。

我正在尝试将外部依赖项包含在sample projects之一。

此依赖项调用ClassLoader.defineClass,它以java.lang.ClassFormatError: Illegal UTF8 string in constant pool in class file org/apache/xerces/impl/xpath/regex/ParserForXMLSchema退出。该异常与this quasar issue提到的异常相同,这表示它是由冲突的依赖关系和使用类星体代理引起的。

在运行项目的依赖关系报告之后,我不仅可以看到外部库和Corda之间的一些冲突,还可以看到Corda本身之间的冲突。到目前为止,Gradle一直通过其瞬态依赖管理来处理它们。以下是报告摘录:

+--- org.apache.jena:jena-core:3.6.0                            <-external library
     ...
|    \--- org.apache.jena:jena-base:3.6.0
       ...
|         +--- commons-io:commons-io:2.6      <- external lib dependency
\--- net.corda:corda-node-api:2.0.0
     ...
     +--- commons-beanutils:commons-beanutils:1.9.3       <- corda dependency
     |    +--- commons-logging:commons-logging:1.2
     |    \--- commons-collections:commons-collections:3.2.2
     +--- org.apache.activemq:artemis-core-client:2.1.0
     |    +--- org.jgroups:jgroups:3.6.13.Final
     |    +--- org.apache.activemq:artemis-commons:2.1.0
           ...
     |    |    +--- commons-beanutils:commons-beanutils:1.9.2 -> 1.9.3 (*) <- corda conflict
     ...
     +--- commons-fileupload:commons-fileupload:1.3.3
     |    \--- commons-io:commons-io:2.2 -> 2.6     <-    external lib conflict
    ...

这是我的root build.gradle:

buildscript {
    ext.corda_release_version = '2.0.0'
    ext.corda_gradle_plugins_version = '1.0.0'
    ext.kotlin_version = '1.1.4'
    ext.junit_version = '4.12'
    ext.quasar_version = '0.7.9'

    repositories {
        mavenLocal()
        mavenCentral()
        jcenter()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version"
        classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version"
        classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
    }
}

repositories {
    mavenLocal()
    jcenter()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
}

apply plugin: 'kotlin'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'net.corda.plugins.quasar-utils'

sourceSets {
    main {
        resources {
            srcDir "config/dev"
        }
    }
    test {
        resources {
            srcDir "config/test"
        }
    }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
    testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
    testCompile "junit:junit:$junit_version"

    cordaCompile "net.corda:corda-core:$corda_release_version"
    cordaCompile "net.corda:corda-node-api:$corda_release_version"
    cordaRuntime "net.corda:corda:$corda_release_version"
    testCompile "net.corda:corda-node-driver:$corda_release_version"

    compile "org.apache.jena:jena-core:3.6.0"
}

作为参考,来自jena-core的函数调用是JUnit测试中的单行ModelFactory.createDefaultModel()。此时我正在使用最少的Corda库来运行其他测试,因为在编译未使用的库时会出现更多冲突。

另一种方法是使用quasar aot而不是代理,但我是Gradle的新手,更不用说Ant了,我无法找到/想出一个例子。

最后,我还尝试按照corda docs的建议将ext.corda_gradle_plugins_version = '1.0.0'升级为2.0.9,但gradle在升级后无法调用cordaCompile,而我还没有能够在插件上找到任何文档。

编辑:我注意到从2.1.0升级到2.4.0的artemis-core-client会解决corda-node-api的内部冲突as you can see here。至于commons-io,遗憾的是commons-fileupload是最新版本1.3.3,自17年7月以来一直没有更新

1 个答案:

答案 0 :(得分:0)

您需要设置依赖关系,如下所述:How can CorDapps deal with transitive dependencies

背景:什么是阴影?

说corda依赖于Guava版本1.它将使用import com.google.guava.SpecialList类型的import语句,这意味着当Corda运行时,类com.google.guava.SpecialList必须存在于类加载器中。

现在,假设开发人员正在编写使用Guava版本2的CorDapp。运行CorDapp时,Guava版本1和Guava版本2 JAR都将在类路径上。

在运行时,Java将在其类路径上加载所有JAR。这意味着它未定义将加载com.google.guava.SpecialList的哪个副本。这取决于订单,环境,Java版本等。并且可能会加载40%的版本1,而版本2的60%将被加载。

如果版本1和版本2兼容,则这不是问题。 CorDapp将使用版本1,或者Corda运行时将使用版本2.真正的乐趣在两个版本不兼容时开始,因为现在应用程序可能在某些情况下工作,而在其他情况下失败 - 这是一场噩梦。

着色让我们摆脱了这个问题。它允许我们重新打包依赖项,以便它们的包定义不再发生冲突。

作为构建过程的一部分,执行shade插件,它将corda.dep附加到Corda引用的所有类,并重写导入类的字节码,以便它们引用修改后的包, import corda.dep.com.google.guava.SpecialList

这导致Guava版本1与其名称空间(corda.dep)中的Corda JAR捆绑在一起。任何依赖于Guava的CorDapp现在都可以安全地导入这个库,并将其包含在类路径中,而不会与Corda使用的版本冲突。

有一个名为shadow的着色Gradle插件。我们将调用此插件作为生成Corda运行时jar的构建的最后一个阶段。