How to put the res files from the project to the jar in the same folder? - java

I have problem with gradle.
I need the res folder had exactly the same location as in the project in order that would be executable file addressed to the resource in the same way as in the "unbuild" project.
my project file tree:
Project
+--src
+--main
|--kotlin
+--res
In the project resource usage I address in the following way:
var serviceAccount = FileInputStream("src/main/res/my_resource_file.json")
And I need when assembled the project location of the resource file saved in the jar file
my build.gradle file:
group 'Bot'
version '1.0'
buildscript {
ext.kotlin_version = '1.1.2'
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
repositories {
mavenCentral()
}
ext {
jsoup = "1.10.2"
//...
firebase_admin = "5.0.0"
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
//...
compile "com.google.firebase:firebase-admin:$firebase_admin"
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin/'
test.java.srcDirs += 'src/test/kotlin/'
main {
resources {
srcDirs = ["src/main/res"]
}
}
}
jar {
manifest {
attributes 'Main-Class': 'com.my.bot.MainKt'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
I suspect that you need to configure this section jar{//...}, but i don't know what did is in gradle

Normally you would reference such as resource from: src/main/resources as the source folder which then is copied auto copied into your JAR by Gradle. You then use the Classloader to read the resources as a stream.
If I placed a file at src/main/resources/my_resource_file.json it would be loaded via:
// relative to the current class package location
val input = javaClass.getResourceAsStream("/my_resource_file.json")
// or use system classloader
val input = ClassLoader.getSystemClassLoader().getResourceAsStream("my_resource_file.json")
You are instead doing it in a non standard way by using res as the directory name instead of resources and by trying to access it as a file instead of a classpath resource. In Gradle docs (similarly for Maven) they explain the file layout: Gradle Java Project Layout

Related

no main manifest attribute error in multimodule app with gradle

I have multimodule java/kotlin app with Gradle.
I wanna make .jar to launch my app in a terminal: like java -jar mayApp.jar
How correct build .jar in multimodule app?
My .jar generated by IDEA is not runs when I trying in terminal due to error:
no main manifest attribute, in /Users/me/IdeaProjects/MyProject/out/artifacts/MyProject_jar/MyProject.jar
project structure:
- :ApplicationName
- :bot-app
- src/main/java/main
Main.java // psvm
- src/main/resources
- META-INF
MANIFEST.MF
build.gradle // module's build
- :data
- :utils
build.gradle // application (root) build
So, in my multimodule project the main class is located in the :bot-app module.
Each module has its own build.gradle and in the root project I have build.gradle of the app;
Module build.gradle
buildscript {
repositories {
...
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0"
}
}
apply plugin: "org.jetbrains.kotlin.jvm"
apply plugin: 'kotlin-kapt'
group 'org.my_project'
version '2.4.0'
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
}
And it is my root build.gradle
buildscript {
repositories {
...
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0"
}
}
apply plugin: 'java'
tasks.withType(Jar) {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes["Main-Class"] = "main.Main"
}
}
As u see, I added
tasks.withType(Jar) {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes["Main-Class"] = "main.Main"
}
}
but it is not works for me. With 1 module it worked, but after refactoring to multimodule, no.
How build .jar in multimodule app?
----
UPD:
if I delete the .gradle folder in the root project and then try to run the app via IDEA it works well. But when I build artifacts via IDEA, jar is created but not works with the error:
no main manifest attribute
And each next build in IDEA is failed with error:
`Execution failed for task ':bot-app:jar'.
Entry META-INF/bot-app.kotlin_module is a duplicate but no duplicate handling strategy has been set.`
If I delete .gradle again, build in IDEA works well.
Need to delete:
tasks.withType(Jar) {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes["Main-Class"] = "main.Main"
}
}
This code is extra for me.
Then create MANIFEST.MF at the root of the project.
Note: you must create it via file->project structure->artifact->+
and in the field Directory for META-INF/MANIFEST.MF: u must set root folder location (NOT module folder, but root)
Remove .gradle, clean, and build artifacts.

Get variable from child project in subproject configuration in multi module gradle project

I have a multi modul java project, where i want to create jar (bin,source,javadoc) and i have trouble getting variable, from subproejcts in subproject configuration.
this is my build.gradle file in the root project:
subprojects {
/*...*/
jar {
manifest {
attributes(
"Implementation-Title": project.name,
"Implementation-Version": project.version,
"Implementation-Vendor": "XXX",
"Main-Class": project.mainClassName
)
}
include '**/**'
}
/*...*/
}
And this the build.gradle file one of the subproejcts:
version = '1.2.0-SNAPSHOT'
ext {
mainClassName = "..."
}
/*...*/
when i want to run the build script i got the following exception:
Could not get unknown property 'mainClassName' for object of type
org.gradle.api.java.archives.internal.DefaultManifest.
In the sub process configuration i have other task where i can easily access the proejct.version from each subproejct also project.name, and works well, and when i change a the "Main-Class": project.mainClassName to "Main-Class": "i.hate.mylife.SoMuch" the script runs perfectly.
In the subproejct i also try the followings
def mainClassName = "..."
project.ext{
mainClassName = "..."
}
Is there any way in gradle to get variable of subroject from subproejcts in subproejct configuration?
In the subproject configuration i also try the followings:
project.ext.mainClassName
project.ext.get("mainClassName")
And non of them work, when i try to run it, it's says:
Cannot get property 'mainClassName' on extra properties extension as it does
not exist
To override extra properties in subproject's build.gradle you must put your desired task (in this case the jar task) inside the afterEvaluate block.
root project build.gradle:
subprojects {
apply plugin: 'java'
apply plugin: 'application'
ext {
// the property that should be overridden in suproject's build.gradle
mainClassName = ''
}
afterEvaluate {
jar {
manifest {
attributes(
"Implementation-Title": project.name,
"Implementation-Version": project.version,
"Implementation-Vendor": "XXX",
"Main-Class": mainClassName
)
}
include '**/**'
}
}
}
sub project build.gradle:
mainClassName = 'project.specific.Main'
ext.set("mainClassName", mainClassName)

"Could not find or load main class" error for Gradle-generated Scala JAR

After much research, I can't seem to get to the root of a problem I am having in generating a runnable Scala jar file using Gradle. I'm overriding the 'jar' Gradle task to create a jar file (dependencies included) that executes starting from my main class file. However, whenever I run it, regardless of what I use for a Main-Class attribute, the console throws a "Could not find or load main class" error. Here's what I have so far:
build.gradle
buildscript {
repositories {
mavenCentral()
}
}
apply plugin: 'java'
apply plugin: 'scala'
apply plugin: 'application'
repositories {
mavenCentral()
// some other repos
}
version = '1.0'
sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = "com.test.Main"
dependencies {
// my dependencies
}
jar {
zip64 = true
manifest {
attributes "Main-Class": "$mainClassName"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
src/main/scala/com/test/Main.scala
package com.test
object Main {
def main(args: Array[String]): Unit = {
print("Hello world");
}
}
In fact, when I run "java tf test.jar", it shows "com/test/Main.class" in the root of the jar! Am I missing some important class path info or something? I'm running Java 1.8 on macOS Sierra using Gradle 3.5. Any help is appreciated. Thanks!
I had a similar problem and it turns out that my META-INF folder inside my jar file contains a few RSA, SF, and DSA files.
Once I excluded them, it worked!
here is how to based on your jar declaration
jar {
zip64 = true
manifest {
attributes "Main-Class": "$mainClassName"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
exclude ('META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA')
}
You can use the Shadow Jar Plugin instead of your own jar definition.
Benefits of Shadow
Shadowing a project output has 2 major use cases:
Creating an executable JAR distribution
Bundling and relocating common dependencies in libraries to avoid classpath conflicts
Basic setup:
shadowJar {
baseName = 'your-app'
classifier = 'all'
version = version
configurations = [project.configurations.compile]
}
jar {
manifest {
attributes 'Main-Class': 'com.test.Main'
}
}
You can use the new syntax of Gradle Plugins:
plugins {
id 'java'
id 'scala'
id 'application'
}

How to add dependency in Gluon Project

I have my custom jar file suppose to be added in the classpath of my Gluon project, but I couldn't find any facility in Netbeans that allows you to add your custom jars. Can someone guide me on how to do it?
build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.0-b9'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
}
mainClassName = 'com.rameses.Main'
jfxmobile {
android {
manifest = 'src/android/AndroidManifest.xml'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
}
}
Though I do not use Netbeans or the plugin you have mentioned, but since it is a gradle project, you can add the custom jars to your classpath by adding the following code in your build.gradle file.
dependencies {
compile files('libs/custom.jar')
}
where,
libs/custom.jar is the relative path of the jar w.r.t to the gradle file.

Gradle generated Jar does not include gwt.xml file?

I created a small library project with the following build.gradle:
apply plugin: 'java'
apply plugin: 'gwt-base'
apply plugin: 'eclipse'
buildscript {
repositories {
mavenCentral()
jcenter()
maven {
url new File(rootProject.projectDir.parentFile, 'repo').toURI()
// url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
}
}
gwt {
gwtVersion='2.7.0'
}
The folder structure looks like this:
/library
/library/Library.gwt.xml
/library/client/HelloWorldWidget.java
The sources are taken from here.
When I perform a gradle buildgradle generates a jar file which does not contain the sources and also does not contain the gwt.xml module file.
How can I force gradle to include the sources and the gwt.xml file in the generated jar?
Here is the solution to include the *.java files use:
jar {
from('src/main/java') {
include '**/*.java'
}
}
The include any other resources like gwt.xml files put them into:
/src/main/resources
Alternatively you can use:
jar {
from project.sourceSets.main.allSource
from project.sourceSets.main.output
}
When using the Java plugin, Gradle assumes that the project has the standard structure, i.e. 'src\main\java' & 'src\test\java'. Therefore when executing the build tasks it simply doesn't find any of those directories.
The best way to fix this will be to define your project structure by modifying the existing source sets, which define where your sources are:
sourceSets {
main {
java {
include '/library/**'
}
}
test {
java {
include '/test/sources/directory/**'
}
}
}

Categories