我对Gradle有一些依赖问题。依赖包是apache storm (org.apache.storm:storm-core:0.9.5)和使用Intellij.
我需要storm包编译,但不是在运行时,所以我有我的构建。Gradle配置如下。
apply plugin: 'application'
apply plugin: 'idea'
apply plugin: 'eclipse'
...
configurations {
provided
}
idea {
module{
scopes.PROVIDED.plus += [configurations.provided]
}
}
eclipse {
classpath {
plusConfigurations += [configurations.provided]
}
}
sourceSets {
main {
compileClasspath += configurations.provided
runtimeClasspath += configurations.provided
}
test {
compileClasspath += configurations.provided
runtimeClasspath += configurations.provided
}
}
dependencies {
...
provided 'org.apache.storm:storm-core:0.9.5'
...
}
类似地,配置允许Intellij知道链接到引用和构建的依赖关系。我的问题是我想在LocalMode下运行Storm拓扑,但是当我这样做时,依赖项似乎没有在运行时被拉入,我得到下面的错误。如何在创建jar时排除包,但在通过Intellij或Eclipse运行时包含包?
Connected to the target VM, address: '127.0.0.1:56593', transport: 'socket'
Exception in thread "main" java.lang.NoClassDefFoundError: backtype/storm/topology/IRichSpout
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2693)
at java.lang.Class.privateGetMethodRecursive(Class.java:3040)
at java.lang.Class.getMethod0(Class.java:3010)
at java.lang.Class.getMethod(Class.java:1776)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
Disconnected from the target VM, address: '127.0.0.1:56593', transport: 'socket'
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: backtype.storm.topology.IRichSpout
at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
我找到了一种方法来做到这一点,通过配置运行/调试配置显式地包括我的应用程序的jar和apache-storm的jar的类路径。
如果有更好的方法,我很乐意听听。
我这样做。首先,有一堆新配置,它们的名字很麻烦:
configurations {
includedInStormJar
excludedFromStormJar.extendsFrom includedInStormJar
compile.extendsFrom excludedFromStormJar
}
然后,在我的dependencies部分:
excludedFromStormJar "org.apache.storm:storm-core:$stormVersion"
includedInStormJar "org.yaml:snakeyaml:1.15"
// any other cool stuff here
最后一个任务看起来非常类似于广为人知的"fatJar":
task stormJar(type: Jar) {
dependsOn configurations.runtime
from {
(configurations.runtime - configurations.excludedFromStormJar + configurations.includedInStormJar).collect {
it.isDirectory() ? it : zipTree(it)
}
}
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
with jar
}
所以当用"gradle clean stormJar"构建一个jar时,它排除了所有与Storm本身相关的东西(加上它的依赖),但包含了它的依赖项中的所有其他东西——这可能很重要,因为有时我有依赖冲突。此外,由于编译配置从excludedFromStormJar扩展,IntelliJ的构建得到Storm,可以在LocalCluster实例上运行。
你可能还想检查这个问题:
让Storm jar只在Gradle项目中编译
类似的方法,但以一种不同的,我不得不承认,更优雅的方式。