Create a Jar file with dependencies from settings.gradle - java

I want to create a jar file which can be used by command like java -cp .\TrendAnalyzer.jar trend_detect.Main.
However, I can't find a way to create a jar file from settings.gradle, not build.gradle.
How can I create a jar file with dependencies from settings.gradle, which contains include etc. information.

Add com.github.johnrengelman.shadow plugin to main module build.jar
plugins {
// *snip*
id 'com.github.johnrengelman.shadow' version '7.1.2'
}
application {
// Define the main class for the application.
mainClass = 'jaso92559.app.App'
}
jar {
manifest {
// Define the main class for the application.
attributes "Main-Class": "jaso92559.app.App"
}
}
run ./gradle shadowJar command on the path where settings.gradle exists.
In app\build\libs, app-all.jar file is generated and it can be run java -jar app-all.jar.
According to https://github.com/yukihane/stackoverflow-qa/tree/main/jaso92559

To create a jar file from settings.gradle, you can use the jar task in Gradle. This task allows you to package the compiled code and any dependencies into a jar file, which can then be executed using the java command with the -cp option.
Creating a jar file using the jar task in settings.gradle:
// settings.gradle
include ':trend_detect'
// build.gradle (in the trend_detect module)
apply plugin: 'java'
jar {
manifest {
attributes 'Main-Class': 'trend_detect.Main'
}
from {
configurations.compile.collect {
it.isDirectory() ? it :
zipTree(it) }
}
}
The include statement in settings.gradle specifies that the trend_detect module should be included in the build.
In the build.gradle file for the trend_detect module, the jar task is defined to create a jar file with a MANIFEST.MF file that specifies the main class (trend_detect.Main). The from statement in the jar task specifies that the jar file should include all of the compiled code and dependencies from the compile configuration.
Once the jar file has been created, you can run it using the java command with the -cp option, as follows:
java -cp .\TrendAnalyzer.jar trend_detect.Main
This will execute the main() method in the trend_detect.Main class, using the compiled code and dependencies contained in the jar file.

Related

gradle exclude external resource folder from all jars

Using gradle 5.4 with a project dependency from external folder in a netbeans project.
The external folder contains resources like images, xml and custom objects that can only be created by this netbeans project. These external assets are then used to create binary files that get packed into a separate jar by that netbeans project.
These same external resources are also used during runtime for development in the gradle project. While I need the resources for development in the gradle project, I do not need or want them to be included in any jars anywhere for any reason when using the task build command because only the binaries are needed for distribution.
How to exclude the external resources from any and all jar files in the gradle project but allow them to be used for the classPath so I can run the project?
Some code examples of failure.
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'idea'
sourceSets {
main {
resources {
srcDir '../ExternalResourceFolder/assets'
}
}
}
jar {
exclude('../ExternalResourceFolder/assets/**')
}
dependencies {
runtimeOnly files('../ExternalResourceFolder/assets')
}
jar {
exclude('../ExternalResourceFolder/assets/**')
}
distributions {
main {
contents {
exclude '../ExternalResourceFolder/assets/**'
}
}
}
Tried many more things like adding to classPath and exclude but it would just be clutter to add them. Changing from sourceSet to dependency only moves the problem around from "build/lib" folder to "build/distributions" folder.
Had to exclude per file type in the end.
sourceSets {
main {
resources {
srcDir '.'
exclude ('**/*.j3odata','**/*.mesh','**/*.skeleton',\
'**/*.mesh.xml','**/*.skeleton.xml','**/*.scene',\
'**/*.material','**/*.obj','**/*.mtl','**/*.3ds',\
'**/*.dae','**/*.blend','**/*.blend*[0-9]','**/*.bin',\
'**/*.gltf')
}
}
}

Tasks for build and run works but executing with the generated run script doesn't

I am doing the simple HelloWorld example from https://spring.io/guides/gs/gradle/.
I had to do some changes (I'm using Gradle 5.2.1 on Ubuntu 18) to the build.gradle. I used gradlew wrapper. I managed to get tasks like 'build' and 'run' working. Everything is generated correctly, it seems. But running the app without gradle using the generated build/scripts/<appscript> does not work. Running the jar with
java -jar build/libs/hello-1.0.jar
works. But
./build/scripts/sayhello
Does not work and produces an error:
erno#moongate:~/Projects/java/sayhello$ ./build/scripts/sayhello
Error: Could not find or load main class hello.HelloWorld
Caused by: java.lang.ClassNotFoundException: hello.HelloWorld
Project file structure is as suggested:
sayhello/
build.gradle
gradlew
src/
main/
java/
hello/
Greeter.java
HelloWorld.java
I had to add the manifest and the mainclass attribute to the build configuration file as it seems that the gradle init --type java-application does not do it. Meaning that even trying to run the gradle generated base project does not work.
My build.gradle is like this:
plugins {
id 'java'
id 'application'
}
mainClassName = 'hello.HelloWorld'
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile "joda-time:joda-time:2.10"
testCompile "junit:junit:4.12"
}
jar {
manifest {
attributes(
'Main-Class': 'hello.HelloWorld'
)
}
baseName = 'hello'
version = '1.0'
}
The problem with the startScripts task is that it generates a very basic script. It does not make sure dependent jars are in the right places - it expects this to be done by you. Also it assumes that you will be running the script from a directory it refers to as the $APP_HOME and this folder needs to contain a lib folder which contains all the jars your app needs.
My very hacky solution is to generate an even more basic unix script instead of relying on the default one.
startScripts {
dependsOn jar
doFirst {
unixStartScriptGenerator = configure(new CustomUnixStartScript()) {
classpath = configurations.runtimeClasspath + jar.outputs.files
}
}
}
class CustomUnixStartScript implements ScriptGenerator {
#InputFiles
FileCollection classpath
#Override
void generateScript (JavaAppStartScriptGenerationDetails details, Writer destination) {
destination << """java -classpath $classpath.asPath ${details.mainClassName}"""
}
}
You can extend this as you see fit.

gradle project: error couldn't find main class

I have the following project structure:
Root project 'rmi-tutorial'
+--- Project ':client'
+--- Project ':lib'
\--- Project ':server'
The path to clients main class looks like this:
client/src/main/java/client/ComputePi.java
my build.gradle for the client subproject loooks like this:
dependencies {
compile project(':lib')
}
mainClassName = "ComputePi"
The main build.gradle file is this one:
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'
repositories {
mavenCentral()
}
dependencies {
//compile project(':server')
//compile project(':client')
testCompile 'junit:junit:4.12'
}
version = '1.0'
jar {
manifest.attributes provider: 'gradle'
}
}
The generation of the jars works so far but the MANIFEST.MF file in the jar is wrong. It contains the following:
Manifest-Version: 1.0
provider: gradle
Where is my specified main class? When I try to execute the startscript that got created by the gradle application-plugin I get the error: couldn't find nor load main class
The jar contains all necessary class files
The application plugin does not produce a runnable JAR with Main-Class entry. Instead it generates a distribution with Windows and *nix start scripts where the main class is used and all libaries put to the class path.
If you want a runnable JAR, you have to configure it yourself, or use one of the plugins that produces a fat JAR, also including the dependencies into the runnable JAR (I don't like this, but it works if the target computer has the correct file associations set). If the target computer e. g. has associated JAR files with an archiving tool, double-clicking the JAR will open the JAR in the archiving tool, not run your application.
If you want to run your application, use gradlew run, or do gradlew installDist and then execute the application that is installed to build/install/.... That is how the application plugin works. With gradlew distZip or gradlew distTar you can create shippable archives of your application.

Gradle Output Jar has no Main-Class

I have the following simple build.gradle file:
apply plugin: 'application'
apply plugin: 'java'
mainClassName = 'com.kurtis.HelloGradle'
And the following single java file located at src/main/java/com/kurtis/HelloGradle.java:
package com.kurtis;
public class HelloGradle {
public static void main(String[] args) {
System.out.println("Hello gradle");
}
}
However, if I run gradle build I get a jar in the build/lib directory that has no main class set. It's manifest file has no Main-Class entry. Why is this?
It's due to the way application plugin works. mainClassName is a property used by application plugin, when it creates an executable jar, it doesn't need to have a Main-Class in the manifest, since it doesn't use it.
If you need to have a Main-Class in your jar, then you have to provide it vie jar configuration of the java plugin as follows:
jar {
manifest {
attributes(
'Main-Class': 'com.kurtis.HelloGradle'
)
}
}
Otherwise, just use an executable, which is generated by application plugin, whether via run task or via distributions it can create for you, with scripts to run your application and all it's dependencies.

Gradle custom task for jar

I am using Gradle for my Java project and I was wondering if it's possible to prevent gradle build from creating a jar file each time executed.
Also, is it possible to have a custom task for creating the Jar with dependencies at a specific location build/myAppJar/.
Here's what I have so far for the custom task:
task toJar (type: Jar) {
from configurations.compile.collect { zipTree it }
manifest {
attributes 'Implementation-Title': 'myApp',
'Implementation-Version': 1.0,
'Main-Class': mainClassName
}
}
The above code will create the jar file under build/libs, and the file does not contain the compiled files, only the dependencies.
Thank you!
The build task comes from the java plugin. You can control when a jar is built with something like this:
jar {
onlyIf { condition }
}
You can set jar to be built when you declare something else to be true, or hard set it to false to never build a jar.
You can include sourcesets in your toJar custom task, to include compiled files into your jar.
task toJar (type: Jar) {
from sourceSets.all
}
You are explicitly calling for all compile time dependencies to be included in the jar here: from configurations.compile.collect
ref: Gradle java plugin

Categories

Resources