问题
Currently in v2, if a CorDapp references a module X, which has a transitive dependency to a module Y, such that Y is used by Corda, a potential version conflict can occur if the respective versions of Y for Corda and X differ. An example is the reuse of an existing internal library, containing business and serialisation logic, that depends on Jackson
.
In this case, the resulting CorDapp packaging and Corda runtime, seem to enforce the version of Y that is relevant for Corda.
If the versions of Y differ sufficiently, we can get such scenarios as X breaking because Y doesn’t support certain types and methods.
Is there a general way that the gradle configuration (or some other mechanism) can be used to restrict the correct version of Y for usage by X, without impacting the Corda runtime?
回答1:
So I worked this out, and in the process, finally learnt some gradle basics (having come from a maven background). No doubt the following is inelegant and could be generalised better - but it works!
TLDR:
shadowJar
Assumptions
- you're using the current v2 kotlin cordapp template
- the
cordapp
sub module uses dependencies that either they or their dependencies clash against theCorda
runtime.
Solution
1. add the shadowJar
reference
In the root build.gradle
file add the following
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
to the buildscript
dependencies
:
buildscript {
// ...
dependencies {
// ...
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
}
}
2. add shadowJar
task to the cordapp
In the cordapp
project, apply the shadowJar
plugin.
Please Note: I needed to put this before all existing plugins for it to work.
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'kotlin'
// ... etc
Then add the invocation parameterisation:
tasks {
shadowJar {
mergeServiceFiles()
// Place your shaded packages here!
relocate 'io.netty', 'shadow.io.netty'
relocate 'com.fasterxml', 'shadow.com.fasterxml'
configurations = [project.configurations.compile]
baseName = jar.baseName + "-" + jar.version
classifier = null
version = null
dependencies {
include(dependency(".*:.*:.*"))
exclude(dependency('org.jetbrains.kotlin:.*:.*'))
exclude(dependency('net.corda:.*:.*'))
exclude(dependency('org.apache.logging.*:.*:.*'))
exclude(dependency('org.apache.activemq:.*:.*'))
exclude(dependency('com.google.*:.*:.*'))
exclude(dependency('io.reactivex:.*:.*'))
exclude(dependency('org.bouncycastle.*:.*:.*'))
exclude(dependency('org.glassfish.*:.*:.*'))
exclude(dependency('co.paralleluniverse.*:.*:.*'))
exclude(dependency('co.paralleluniverse.*:.*:.*'))
exclude(dependency('com.typesafe.*:.*:.*'))
exclude(dependency('com.esotericsoftware.*:.*:.*'))
exclude(dependency('org.qpid.*:.*:.*'))
}
}
}
3. Alter the build dependencies
Now change the definition of deployNodes
to not depend on the jar
task, but instead, depend on the build of each module:
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: [':cordapp-contracts-states:jar', ':cordapp:shadowJar']) {
// ... etc
}
来源:https://stackoverflow.com/questions/48645361/how-can-cordapps-deal-with-transitive-dependencies