Hello, I would like to perform a task in Gradle s...
# community-support
h
Hello, I would like to perform a task in Gradle similar to the assemblyPackageDependency feature of the sbt assembly plugin. The goal is to package all runtime dependencies into a single JAR file, excluding the current project. The reason I need this is that while my code changes frequently, the dependencies remain the same. Instead of creating a fat JAR every time, I want to create a fat JAR for the dependencies only once. Then, whenever my project changes, I would package only my project and add both the dependency JAR and my project’s JAR to the classpath. How can I achieve this in Gradle?
t
From https://docs.gradle.org/current/userguide/working_with_files.html#sec:creating_uber_jar_example, just without the
from(sourceSets.main.get().output)
Copy code
tasks {
  register<Jar>("assemblyPackageDependency") {
    archiveClassifier = "dependencies"

    dependsOn(configurations.runtimeClasspath)
    from({
      configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
    })
  }
}
You can also change it as:
Copy code
tasks {
  val assemblyPackageDependency by registering(Jar::class) {
    // same as above
  }
  assemble { dependsOn(assemblyPackageDependency) }
}
so a
./gradlew assemble
will build both JARs
👍 1
m
I think a better solution is to use the artifactview api and filter on dependencies which are external
so that, for example, in a multi-project build, the "uber" jar doesn't contain project dependencies
it's more robust than filtering on a file extension
v
I think the better solution is not using a bad-practice fat jar at all, but for example building a proper distribution using the
application
plugin instead. 😄
m
there are environments where the only thing you can deploy is a single jar ;)
btw, the technique I mentioned is also used in the Micronaut plugins to build docker image layers 🙂
v
Rare and a desgin bug imho. 😄 And does not apply here, as he at least has two jars in his solution. 😛
h
Just to clarify, I’m creating a JAR for submission to Spark, and I was trying to separate the dependencies from the JAR related to my job. But I’m not sure if this is considered a best practice.
m
sounds reasonable to me... especially if you don't want to upload dozens of MBs for each update
v
I have no idea what Spark is. All I'm saying is that any re-packaging of existing JARs is imho an abuse of Java functionality and very bad practice. Often it can also not even work. For example if you have a security provider it has to be in a JAR signed by a certificate signed-off by Oracle for the JVM to accept it, after repackaging it does not work anymore. Also you have to make sure to exclude certain files like signature files. On the other hand there are files that might appear in multiple files and for which you must not only use one or the other like service provider files. Some of those like the service provider files can be merged, others can not and then again you break something. And often those breakages are also not immediately clear or nicely reproducable.
👍 1