Configuration compile and runtime for gradle - java

I set up a classpath for my jar reference inside a jar.('classpath: 'wee.jar'), but apparently, I also need to type the following in my jar task
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
Can Someone explain to me what does from, configuration.compile.collect, runtime, and isDirectory and zipTree do? I look up google, but couldn't find any answer. I'm really new to gradle

For starters, you do not need both configurations.compile and configurations.runtime. In gradle, the compile time dependencies are already included in runtime config automatically - which makes compile a subset of runtime. Depending on what you're trying to achieve, you'll only need one or the other. So let's take this snippet:
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
A configuration represents a collection of artifacts and their dependencies. compile and runtime are among configs that are added by the java plugin. collect is groovy for: do the following operation for every element of a collection and return the result as a set. So effectively the line of code translates to - for all dependencies declared in configurations.compile, do the following and return the results as a set.
it is groovy shorthand for iterator - so it represents each element of the aforesaid collection.
if `it` is a directory
include it as is,
else
unpack the file and then include it
(See zipTree reference here)
Putting the whole thing together, the code is taking all compile time dependency directories and all unpacked compile time jars and including that into the jar you're building.

Related

Kotlin Library Exported As Jar Usable In Java Code, But Not In Kotlin Code

I've written a utility library for a project I am working on in Kotlin. The project has a number of dependencies (such as AWS libraries). I want to package the library as a 'fat' .jar so that I can use the library in other projects without issue.
Currently, I am using the gradle shadow plugin. I am able to successfully use the .jar classes in Java code/projects without issue. However, when using the .jar classes in Kotlin projects/code (or attempting to) I am facing visibility issues (code does not compile b/c of unresolved references). I have no idea what I am doing wrong and am not sure if this is a common issue.
I've already tried:
Gradle Shadow plugin here
Modifying the gradle jar task to include all dependencies myself
The fat jar is successfully created in both cases, and usable in Java code, but Kotlin is not able to resolve the references. However, when I create a non fat jar, the classes are visible, but obviously broken (bc of missing dependencies). So, essentially, only when I create a fat .jar, only my Kotlin code cannot use the library.
Does anyone have any insight?
Most likely, your re-packaged JAR is missing the META-INF/*.kotlin_module files from the original JARs. These are the Kotlin package metadata files which the Kotlin compiler needs to be able to read top-level declarations from the classes.
If these files are lost, you will face visibility issues with top-level declarations and extensions.
You need to configure your fat JAR tools to also copy these files into the resulting JAR.
You would also need to add both the compile time and run time dependencies when you compile your library jar file.
One way to add them would be for example:
tasks {
jar{
from({
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
configurations.compileClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }
})
exclude ("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")
}
}

Compile a groovy script with all it's dependencies which are managed by gradle and then run it as a standalone application via the command line

I have a simple groovy script with a single java library dependency:
package com.mrhacki.myApp
import me.tongfei.progressbar.ProgressBar
class Loading {
static void main(String[] arguments) {
List list = ["file1", "file2", "file3"]
for (String x : ProgressBar.wrap(list, "TaskName")) {
println(x)
}
}
}
I'm using gradle to manage the dependencies of the project. The gradle configuration for the project is pretty straightforward too:
plugins {
id 'groovy'
}
group 'com.mrhacki'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
compile 'me.tongfei:progressbar:0.7.2'
}
If I run the script from the Intellij IDE, the script is executed as expected.
What I would like to do now is to compile the script with this dependency into one single .jar file, so I can distribute it as such, and run the application from any filesystem path, as the script logic will be dependent on the path from which the execution was called.
I've tried with a few gradle fat jars examples out there but none have worked for me since the .jar file is constantly throwing Could not find or load main class Loading when I try it to run.
If anyone would be so kind to give a hint or to show an example of a gradle task that would do a build that fits my described needs I would be very gratefull.
I'm aware of the groovy module Grape with the #Grab annotation too, but I would leave that as a last resort since I don't want the users to wait for the dependencies download, and would like to bundle them with the app.
I'm using groovy 2.5.6 and gradle 4.10 for the project
Thanks
You can simply create the fat-jar yourself, without any extra plugin, using the jar Task. For a simple/small project like yours, it should be straightforward :
jar {
manifest {
// required attribute "Main-Class"
attributes "Main-Class": "com.mrhacki.myApp.Loading"
}
// collect (and unzip) dependencies into the fat jar
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
EDIT : pleas take other comments into consideration: if you have more that one external lib you might have issues with this solution, so you should go for a solution with "shadow" plugins in this case.

Intellij Grade Build Jar with dependencies

I want to build a jar file in IntelliJ IDEA with Gradle.
When I run my code in Intellij everything works fine,
but when I run the jar file I get an error:
SQLExecption: No suitable driver found for jdbc:sqlite:/applications/elite-dangerous/database/ED_Database.db
I build the jar throw pressing the build button.
It's strange for me because it works perfectly fine when I run it in IntelliJ IDEA.
Dependencies included using implementation config are not being included in the Jar which makes them not available in runtime. So, I guess that could be the case. You can try changing implementation to compile dependencies ( which is deprecated, so not recommended ) or You can include your dependencies in the jar as below
jar {
manifest {
attributes 'Main-Class': 'eliteDangerousRestUpdater.Main'
}
from {
compileJava.classpath.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}

how to include my test in application jar

I am using Gradle build in my java application. My project has the elasticsearch intergation test. Following is my gradle.build
jar {
baseName = 'myproject'
version = 'V.4.0.0'
manifest {
attributes 'Main-Class': 'com.myapp.Application'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
test {
systemProperties = System.properties
systemProperty 'tests.security.manager', 'false'
}
When i give gradle build it executed the test and created the myproject-V.4.0.0.jar. but when i run the
java -cp myproject-V.4.0.0.jar;junit-4.11.jar junit.textui.TestRunner com.myapp.test.testclassname
i got class not found exception for com.myapplication.test.testclassname.
I extracted the myproject-V.4.0.0.jar and can not find the test class.
My question is, How can i include the test class also in my application jar?
This is a deliberate behaviour of gradle java projects. A jar is your production artifact, so usually you want to test it during the build, but you do not want to run your tests in production, so I do not recommend doing it. Having said that, there is a way of doing it in gradle, like this:
task myJar(type:Jar) {
from {sourceSets.main.output + sourceSets.test.output}
}

How to package dependencies into output jar?

I am trying to make my application work in a stand alone jar. The problem is, a jar is generated for my program, and a bunch of other jars are generated for the libraries. Is there any way to get these jars to get inside one? I am using Gradle if that helps.
The IntelliJ IDEA artifact config:
The output directory:
What I expected (and want) to happen:
You need a fat-jar (jar file with all it's dependencies inside). It's not a big problem for Gradle, you just need to make one additional task of type jar, which will collect all the dependencies and zip it alltogether
There are many examples, how you can do it, here is one of them. Take a closer look at task fatJar:
task fatJar(type: Jar) {
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}

Categories

Resources