How to run shadow jar with a gradle task? - java

I want to run my app after building it with the shadow jar plugin.
build.gradle:
plugins {
id 'java'
id "org.jetbrains.kotlin.jvm" version "1.3.21"
id "com.github.johnrengelman.shadow" version "5.0.0"
}
group 'org.example.java'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
repositories {
jcenter()
}
dependencies {
compile "io.ktor:ktor-server-netty:1.1.3"
}
I also have a global init.gradle:
gradle.projectsLoaded {
rootProject.allprojects {
buildDir = "/Users/User/Builds/${rootProject.name}/${project.name}"
}
}
So now the fat jar can be built to my global build directory with the shadowJar task. But I want to be able to run and build it with just one run configuration in IntelliJ. How do I do that?
Maybe there is another way to let gradle redirect all my output to a global build directory. I don't want to configure each IntelliJ project with the same output path manually. Suggestions are welcome.
Thank you :)

You should not touch the buildDir property for achieving what you want.
Instead, you should create a JavaExec task that will start the application from the shadow jar.
If you want that execution to be at a different place than the default location of the generated jar, you should either change the output of the shadow task itself, and only that output or make your execution task depend on a copy task that would move the shadow jar around.
Something like:
shadowJar {
destinationDir = "/Users/User/Builds/${rootProject.name}/${project.name}"
}
task runApp(type: JavaExec) {
main = "your.main.Class
classpath = shadowJar.archiveFile // use archivePath before Gradle 5.1
}

Related

How to rename jar file that's being published using Gradle with maven-publish and shadow plugins?

Basically what I'm trying to do is publish a jar file to GitHub Packages with a certain name. What I have now is:
shadowJar {
archiveFileName = "Some-Name-${parent.version}.${extension}"
}
publishing {
...
publications {
shadow(MavenPublication) { publication ->
project.shadow.component(publication)
artifactId = 'me.project'
groupId = 'some-project'
version = 1.1.0
}
}
}
But from this I get some-project-1.1.0-all.jar, I would like to get some-project-1.1.0.jar but cant seem to find the way how. Changing the archiveFileName in the shadowJar task doesn't seem to affect the publishing jar only the build jar.
I believe you need to change the archiveClassifier of the shadowJar task. By default, this is configured as all.
Point 5: https://github.com/johnrengelman/shadow/blob/master/src/docs/getting-started/README.md#default-javagroovy-tasks
https://github.com/johnrengelman/shadow/blob/7.0.0/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy#L66
Something like:
tasks.shadowJar {
archiveClassifier = ""
}
The shadowJar task extends of the Jar task type. By default, with the Java plugin, archiveClassifier is configured as an empty String "". The Shadow plugin reconfigures its shadowJar task with all.

using Kotlin with Gradle

I'm new to Kotlin and Gradle, and tried to follow these steps, so I got the following 2 files:
after running gradle init I changed the build.gradle to be:
// set up the kotlin-gradle plugin
buildscript {
ext.kotlin_version = '1.1.2-2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// apply the kotlin-gradle plugin
apply plugin: "kotlin"
apply plugin: 'application'
mainClassName = "hello.main"
// add kotlin-stdlib dependencies.
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
Hello.kt:
package hello
fun main(args: Array<String>) {
println("Hello World!")
}
Then I run the gradle build and got the build\classes\main\hello\HelloKt.class
my question is: Why the file generated is .class not .jar and how to get the .jar file and how to run it, I tried running the generated file using kotlin -classpath HelloKt.class main but got an error error: could not find or load main class hello.main
The classes are the direct output of the Kotlin compiler, and they should be packaged into a JAR by Gradle afterwards. To build a JAR, you can run the jar task, just as you would in a Java project:
gradle jar
This task is usually run during gradle build as well, due to the task dependencies.
This will pack the Kotlin classes into a JAR archive (together with other JVM classes, if you have a multi-language project), normally located at build/libs/yourProjectName.jar.
As to running the JAR, see this Q&A for a detailed explanation: (link)
Thanks for #hotkey answer, it helped me going the correct way.
First of all there is a mistake in the main class declaration, as it should follow the new methodology, that is in the below format:
mainClassName = '[your_namespace].[your_arctifact]Kt'
namespace = package name
arctifact = file name
so, considering the names given in the example above where filename is: Hello.kt, and the namespace is hello, then:
mainClassName = `[hello].[Hello]Kt`
using the previous method, that contains:
apply plugin: 'application'
mainClassName = 'hello.HelloKt'
the generated .jar file is not including the kotlin runtime, so the only way to execute it, is by:
d:/App/build/libs/kotlin -cp App.jar hello.HelloKt
but in order to generate a self contained jar that can be self-executed, and contains the kotlin runtime then the build.gradle should be written as:
// set up the kotlin-gradle plugin
buildscript {
ext.kotlin_version = '1.1.2-2'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// apply the kotlin-gradle plugin
apply plugin: "kotlin"
// add kotlin-stdlib dependencies.
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
jar {
manifest {
//Define mainClassName as: '[your_namespace].[your_arctifact]Kt'
attributes 'Main-Class': 'hello.HelloKt'
}
// NEW LINE HERE !!!
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
followed by gradle build, the [your_working_folder].jar file will be generated at the build/libs folder, assuming the working folder name is app, then file app.jar will be generated.
To run this file, one of the following 2 commands can be used:
D:\App\build\libs\java -jar App.jar
OR
D:\App\build\libs\kotlin App.jar hello.HelloKt

Gradle - Create jar only if tests pass

I am new to Gradle. I would like to manipulate the following build.gradle contents to do this. Instead of separately running the tests then building the jar via separate commands, I'd like to do both in one command, except that the jar does not get created if one of the tests fail (it will not even try to build the jar).
apply plugin: 'java'
apply plugin: 'eclipse'
version = '1.0'
sourceCompatibility = 1.6
targetCompatibility = 1.6
// Create a single Jar with all dependencies
jar {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'com.axa.openam'
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
// Get dependencies from Maven central repository
repositories {
mavenCentral()
}
test {
testLogging {
showStandardStreams = true
}
}
// Project dependencies
dependencies {
compile 'com.google.code.gson:gson:2.5'
testCompile 'junit:junit:4.12'
}
Thanks!
The simplest solution is to place all the tasks you want gradle to execute in order. So you may use the following:
gradle clean test jar
Tasks Breakout
clean: this is used mainly just to safely remove the last outdated jar (this is not mandatory);
test: execute the tests;
jar: create the jar artifact.
Key point: if one of the task fails for some reason gradle stops its execution.
So if just a single test fails for some reason an exception is thrown and the jar file is not created at all.
Alternative solution: add 'test' as dependency of 'jar'
Just to explore some other possibilities: modify the build.gralde file as follows:
[...]
jar {
dependsOn 'test'
[...]
}
[...]
Now every time you run gradle jar the test task is automatically executed before.
Emulate the pure command line solution using 'dependsOn'
To emulate the first command line approach (i.e., gradle clean test jar) using the dependency method you have to further modify the build.gradle. This is because is not assured that multiple dependsOn statements are evaluated in order:
[...]
jar {
dependsOn 'clean'
dependsOn 'test'
tasks.findByName('test').mustRunAfter 'clean'
[...]
}
[...]
Now you can use:
gradle jar
and both the tasks clean and test are executed (in the right order) before the actual jar task.

Gradle error with lack of mainClassName property in gradle build

I have graddle configuration with two subprojects and when I want do build the project the following error is thrown:
Executing external task 'build'...
:core:compileJava
:core:processResources UP-TO-DATE
:core:classes
:core:jar
:core:startScripts FAILED
FAILURE: Build failed with an exception.
* What went wrong:
A problem was found with the configuration of task ':core:startScripts'.
> No value has been specified for property 'mainClassName'.
My configuration:
ROOT - build.gradle:
subprojects {
apply plugin: 'java'
apply plugin: 'application'
group = 'pl.morecraft.dev.morepianer'
repositories {
mavenLocal()
mavenCentral()
}
run {
main = project.getProperty('mainClassName')
}
jar {
manifest {
attributes 'Implementation-Title': project.getProperty('name'),
'Implementation-Version': project.getProperty('version'),
'Main-Class': project.getProperty('mainClassName')
}
}
}
task copyJars(type: Copy, dependsOn: subprojects.jar) {
from(subprojects.jar)
into project.file('/jars')
}
ROOT - setting.gradle:
include 'app'
include 'core'
APP PROJECT - build.gradle:
EMPTY
CORE PROJECT - build.gradle:
dependencies {
compile 'com.google.dagger:dagger:2.4'
compile 'com.google.dagger:dagger-compiler:2.4'
}
AND BOTH SUBPROJECTS (SIMILAR) - gradle.properties:
version = 0.1-SNAPSHOT
name = MorePianer Core Lib
mainClassName = pl.morecraft.dev.morepianer.core.Core
I've tried to add the mainClassName property in many places, but it does not work. This is even stranger, that It worked a couple days ago as it is. I'm using gradle for first time and I'm thinking about switching back to maven.
The application plugin needs to know the main class for when it bundles the application.
In your case, you apply the application plugin for each subproject without specifying the main class for each of those subprojects.
I had the same problem and fixed it by specifying "mainClassName" at the same level as apply plugin: 'application' :
apply plugin: 'application'
mainClassName = 'com.something.MyMainClass'
If you want to specify it in the gradle.properties file you might have to write it as : projectName.mainClassName = ..
Instead of setting up mainClassName try to create
task run(type: JavaExec, dependsOn: classes) {
main = 'com.something.MyMainClass'
classpath = sourceSets.main.runtimeClasspath
}
Please look at Gradle fails when executes run task for scala
Whenever we bind a gradle script with the application plugin, Gradle expects us to point out the starting point of the application. This is neccessary because, Gradle will start bundling your application (jar/zip) using the given location as the entry point.
This error is thrown simply because Gradle knows that you want to bundle your application but is clueless about where to start the bundling process.
One can specify the mainClassName as a project extended property:
ext {
mainClassName = 'com.something.MyMainClass'
}
I faced the same issue in my project and solved it by excluding from gradle.properties:
#ogr.gradle.configurationdemand = true

How to export a Spring Boot project to an executable standalone file?

I have created a project in Spring Tool Suite with Spring Boot and Gradle, and I really don't know how to export to make it work.
I don't know much about gradle, just the basics to add dependencies from the maven repository. So in some articles says to apply the application plugin to do the task, but I don't know how to set up the configuration file and how to create the executable.
If anyone could write or link a step by step detailed explanation on how to do it, it would be very much appreciated.
This is my build.gradle file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.1.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'spring-boot'
springBoot {
mainClass = "com.rodamientosbulnes.objetivosventa.Application"
executable = true
}
jar {
baseName = 'objetivosventa'
version = '0.1.0'
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile('org.springframework.boot:spring-boot-starter')
compile('org.springframework:spring-jdbc')
compile('net.sourceforge.jtds:jtds:1.3.1')
compile('org.apache.poi:poi-ooxml:3.13')
compile('com.miglayout:miglayout-swing:4.2')
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
Build file looks fine, you only need to run gradle build (or Run As -> Gradle -> Gradle build in the STS) to create the runnable jar.
More details about configuration of the gradle plugin are available on spring boot documentation site.
Gradle's application plugin doesn't make a single execitable for you, but it can create a distribution, which includes all the dependencies, jar-artifact for your project and 2 scripts to run it (one batch-file and linex executable).
The main thing you need to know, is that spring-boot plugin already provide all the task from application plugin you may need. All the task you can find here. You need distZip or installDist to package your project to the distribution. This task will create a ready project distribution under your project-folder/build folder. One more task you may find usefull is buildRun which will run you spring-boot application without package it into distribution.

Categories

Resources