I have a probleme with my build.gradle, it's compile fine but when i try to execute the .jar the console give me this: "no manifest manifest attribute..."
it's my bluid.gradle:
apply plugin: 'java'
group = "com.xxx.xxx.xxx"
archivesBaseName = "xxx"
version = "0.1"
task pack(type: Jar, dependsOn: 'jar') {
inputs.files jar.archivePath;
jar {
baseName = 'xxxx'
version = '0.1'
}
manifest {
attributes(
"Manifest-Version" : "1.0",
"Main-Class" : "com.xxx.xxx.xxx.xxx"
)
}
doLast {
manifest.writeTo("${buildDir}/MANIFEST.MF")
project.ant {
taskdef name: "jarjar", classname: "com.tonicsystems.jarjar.JarJarTask", classpath: configurations.tools.asPath
jarjar(jarfile: archivePath, manifest: "${buildDir}/MANIFEST.MF") {
fileset(dir : "${buildDir}/classes")
fileset(dir : "${buildDir}/resources/main")
configurations.runtime.files.each { jarjarFile ->
zipfileset(src: jarjarFile) {
// WARNING: MUST keep META-INF/DgmInfo, META-INF/services, ... which are needed by Groovy
}
}
rule pattern: "*", result: "#0"
}
}
}
configurations {
tools
}
dependencies {
tools files("${rootDir}/tools/jarjar-1.4.jar")
compile files("${rootDir}/lib/bluecove-2.1.0.jar")
compile files("${rootDir}/lib/bluecove-gpl-2.1.0.jar")
}
}
I don't write the whole code, I don't really know to code a gradle script,
someone help ? :)
I understand that this part:
"Main-Class" : "com.xxx.xxx.xxx.xxx"
in reality is pointing to a valid Java class that has a main method inside, and the class is on your class path?
If yes, unzip your output jar, find META-INF folder and check what is inside MANIFEST.MF and tell us.
Related
I have spent 3 days trying to see why this error is produced when executing the jar.
Finally, I opened the jar file and noticed that the META-INF folder contains the MANIFEST.MF file but also some folders and some other files too.
If I delete all the files except the MANIFEST.MF file (the folders are not deleted) then the error disappears and I can execute the jar.
The build.gradle file I have used is:
plugins {
// Apply the java-library plugin for API and implementation separation.
id 'java-library'
id 'java'
id 'application'
id 'eclipse' // for avoiding 'java.smartcardio' complain #see:https://stackoverflow.com/a/75222235/7704658
}
// This code is for avoiding 'java.smartcardio' complain in Eclipse #see: https://stackoverflow.com/a/75222235/7704658
eclipse {
classpath {
file {
whenMerged {
def jre = entries.find { it.path.contains 'org.eclipse.jdt.launching.JRE_CONTAINER' }
jre.entryAttributes['module'] = 'true'
jre.entryAttributes['limit-modules'] = 'java.se,jdk.accessibility,jdk.dynalink,jdk.httpserver,jdk.jartool,jdk.javadoc,jdk.jconsole,jdk.jshell,jdk.jsobject,jdk.management.jfr,jdk.net,jdk.nio.mapmode,jdk.sctp,jdk.security.auth,jdk.security.jgss,jdk.unsupported,jdk.unsupported.desktop,jdk.xml.dom,java.smartcardio'
jre.entryAttributes['add-modules'] = 'java.smartcardio' //--limit-modules java.se --add-modules java.smartcardio
}
}
}
}
repositories {
jcenter()
mavenCentral()
maven { url "https://jitpack.io" } //#see: https://stackoverflow.com/questions/38905939/how-to-import-library-from-jitpack-io-using-gradle
flatDir {dirs "$rootDir/../mynewtargets2"} //#see https://stackoverflow.com/a/25966303
}
// My customization
project.jar.destinationDirectory = file("$rootDir/../mynewtargets2")
project.archivesBaseName = 'd05-autofirma-simple'
project.version = '4.0'
dependencies {
api libs.pdfbox
/** other apis stuff go here.........*/
}
distTar {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
distZip {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
application {
mainClass = 'es.gob.afirma.standalone.SimpleAfirma'
}
jar {
zip64=true
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
manifest {
attributes(
'Main-Class': 'es.gob.afirma.standalone.SimpleAfirma',
)
}
archiveClassifier = "all"
from {
sourceSets.main.allSource //Include java sources
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Can anybody explain why the MANIFEST.MF cannot share the META-INF folder with any other file?
Thanks
Here is my tree files :
src
--JaJson.java
build.gradle
Here is my JaJson.java:
public class JaJson {
public static void main(String args[]) {
System.out.println("Hello");
}
public JaJson(){
System.out.println("what time is it ?");
}
public void getTime(){
System.out.println("Hammer time!");
}
}
Here is my gradle.build :
apply plugin: 'java'
apply plugin: 'eclipse'
//apply plugin: 'java-library'
apply plugin: 'application'
mainClassName = "JaJson"
// tag::repositories[]
repositories {
mavenCentral()
}
// end::repositories[]
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
sourceSets {
single{
java {
srcDir 'src'
}
}
}
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'JaJson'
)
}
}
task compileSingle(type: JavaCompile) {
source = sourceSets.single.java
sourceSets.main.java.srcDirs = ['src']
classpath = sourceSets.main.compileClasspath
destinationDirectory = sourceSets.main.output.classesDirs[0]
}
compileJava {
options.release = 7
}
version = '1.2.1'
// tag::dependencies[]
dependencies {
implementation "joda-time:joda-time:2.2"
testImplementation "junit:junit:4.12"
}
When i make a gradle build and a :
java -jar build\libs\jajson-1.2.1.jar
It works fine and print hello
But when i try to launch the class only with :
java build\classes\java\main\JaJson.class
I have a :
Impossible to found or load main class for build\classes\java\main\JaJson.class
And before each build i rm the builds folder.
rd /s /q build
gradle build && java -jar build\libs\jajson-1.2.1.jar && java build\classes\java\main\JaJson.class
regards
Run as
java -cp build/classes/main/java JaJason
As explained in the Java command's help you need to give the name of the main class, not a path to the main class. If your classes don't live in the current directory (or in their package directory right under the current directory), you need to specify the classpath:
--class-path classpath, -classpath classpath, or -cp classpath
[...] If the class path option isn't used and classpath isn't set, then the user class path consists of the current directory (.).
That said, you can also run a simple .java file straight from the command line:
java src/JaJson.java
This is useful to quickly run single-file programs without going through the whole Gradle build cycle.
I would like to exclude all config files from the jar file since they will be provided at the provisioning and having a different version in the build path may create some runtime issues. I am using the following Gradle build script, but for some reason, I can still see whatever exist in the resources directory to be copied into the built Jar. Which means for some reason the provided Gradle build is not working as expected.
apply plugin: 'distribution'
distributions {
main {
baseName = "${project.name}"
contents {
into('/conf'){
from('src/main/resources')
exclude("application.yml")
}
into('/lib'){
from('build/libs')
}
into('/bin'){
from('../bin')
}
}
}
}
processResources {
# Not sure how I need to point to the resources, so I included both. However, none is working.
exclude('resources/*')
exclude('src/main/resources/*')
}
bootJar{
# Not sure how I need to point to the resources, so I included both. However, none is working.
exclude('resources/*')
exclude('src/main/resources/*')
}
distTar {
dependsOn bootJar
}
tasks.withType(Tar) {
compression = Compression.GZIP
extension = "tar.gz"
}
configurations {
customArch
}
artifacts {
customArch file(distTar.archivePath)
}
I was able to exclude resources from appearing in the Jar file by using processResources.enabled = false, so the build file is as follows.
apply plugin: 'distribution'
distributions {
main {
baseName = "${project.name}"
contents {
into('/conf'){
from('src/main/resources')
exclude("application.yml")
}
into('/lib'){
from('build/libs')
}
into('/bin'){
from('../bin')
}
}
}
}
processResources.enabled = false
distTar {
dependsOn bootJar
}
tasks.withType(Tar) {
compression = Compression.GZIP
extension = "tar.gz"
}
configurations {
customArch
}
artifacts {
customArch file(distTar.archivePath)
}
I found that this solution works for me:
processResources {
exclude('logback-spring.xml')
}
...where logback-spring.xml is located in src/main/resources
I'm having some trouble getting my code, which uses JavaFX, to run in a jar file. It runs fine in Intellij, but when I try to run the jar file I get:
Exception in Application start method caused by java.lang.NullPointerException
The line in question is: loginScene.getStylesheets().add(LoginUI.class.getResource("UI.css").toExternalForm());
I'm using Gradle to build my jar so I think my problem is caused by my compiled code not including the UI.css file. My css file is currently located in the same directory as my LoginUI class.
My build.gradle file looks like this:
apply plugin: 'java'
sourceCompatibility = 1.11
repositories {
mavenCentral()
}
def currentOS = org.gradle.internal.os.OperatingSystem.current()
def platform
if (currentOS.isWindows()) {
platform = 'win'
} else if (currentOS.isLinux()) {
platform = 'linux'
} else if (currentOS.isMacOsX()) {
platform = 'mac'
}
dependencies {
compile "org.openjfx:javafx-base:11:${platform}"
compile "org.openjfx:javafx-graphics:11:${platform}"
compile "org.openjfx:javafx-controls:11:${platform}"
compile "org.openjfx:javafx-fxml:11:${platform}"
compile "com.google.code.gson:gson:2.2.4"
compile "org.apache.commons:commons-lang3:3.6"
compile "org.apache.httpcomponents:httpclient:4.5.6"
}
task run(type: JavaExec) {
classpath sourceSets.main.runtimeClasspath
main = "project.Main"
}
sourceSets {
main {
resources {
srcDirs = ["src/main/java"]
includes = ["**/*.css"]
}
}
}
jar {
manifest {
attributes 'Main-Class': 'main.java.edu.ufl.activitymonitor.Main'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
compileJava {
doFirst {
options.compilerArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls,javafx.fxml'
]
}
}
run {
doFirst {
jvmArgs = [
'--module-path', classpath.asPath,
'--add-modules', 'javafx.controls,javafx.fxml'
]
}
}
So far I have tried:
1. Adding the following to my build.gradle file (like in this solution):
sourceSets {
main {
resources {
srcDirs = ["src/main/java"]
includes = ["**/*.css"]
}
}
}
Moving my css files from main/java. to main/resources so my file structure looks like this:
directory structure
And then replacing "UI.css" with either: "../../../../resources/UI.css", "../../../resources/UI.css", "../../../../../resources/UI.css", or "/UI.css", or just leaving it as UI.css. However, this just results in a nullpointer error in IntelliJ.
How do I fix this?
UPDATE: I also added the last two lines to my build.gradle (from this question) and it didn't work:
jar {
manifest {
attributes 'Main-Class': 'main.java.edu.ufl.activitymonitor.Main'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
from('src/main/java') {
include '**/*.css'
}
}
Update: Since I don't have a lot of time before deploying my code for an experiment, I ended up using inline css for the most important graphical elements. It's not perfect, but it does work and it is enough for my purposes.
I'm experimenting with gradle and trying to setup a system that builds different flavors (brands) of an application, which differ by configuration mainly. What I have so far are two versions of the build scripts - both not working.
Version 1
First flavor specific resource folder flavor-res is added to sourcesets, which achieves overwriting some default resources. A task rule defines tasks for each flavor, which should (ideally) trigger build of the whole jar.
This works fine and generates the required jar, for one flavor at a time, like
gradle clean flavorOne
but the shadowJar task runs only once, if I do
gradle clean flavorOne flavorTwo
Stripped down Script:
sourceSets {
main {
...
resources {
srcDirs = ['src/main/resources', "${project.buildDir}/flavor-res/"]
}
}
}
shadowJar { classifier = 'SNAPSHOT' }
tasks.addRule("Pattern: flavor<Name>") { String taskName ->
if (taskName.startsWith("flavor")) {
String flavorName = (taskName - "flavor")
String flavorOutDir = "${project.buildDir}/${flavorName}"
// Set output folder and jar name
task("${taskName}Configure") {
outputs.dir(flavorOutDir)
doFirst {
archivesBaseName = flavorName
project.buildDir = flavorOutDir
}
}
// Copy res to folder used in sourcesets
task("${taskName}CopyResources") {
mustRunAfter = ["${taskName}Configure"]
outputs.dir("${project.buildDir}/flavor-res")
doFirst {
copy {
from "flavors/${flavorName}/"
into "${project.buildDir}/flavor-res/"
}
}
}
shadowJar.mustRunAfter = ["${taskName}Configure", "${taskName}CopyResources"]
// Define task that depends on shadowJar
task(taskName, dependsOn: ["${taskName}Configure", "${taskName}CopyResources",
shadowJar]) {
println "Configuring ${taskName}"
}
}
Sensing that it probably doesnt work because the change detection somehow doesnt work, I tried an alternative approach. Here is a simplified version of script
Version 2
Modified the rule to define a shadowJar dynamic task for each flavor.
/* Removed sourceSets in this version */
shadowJar { classifier = 'SNAPSHOT' }
tasks.addRule("Pattern: flavor<Name>") { String taskName ->
if (taskName.startsWith("flavor")) {
String flavorName = (taskName - "flavor")
String flavorOutDir = "${project.buildDir}/${flavorName}"
// Set resources for main sourceset
task("${taskName}Configure") {
outputs.dir(flavorOutDir)
doFirst {
archivesBaseName = flavorName
sourceSets.main.resources.srcDirs = ['src/main/resources', "${flavorOutDir}/flavor-res"]
project.buildDir = flavorOutDir
}
}
task("${taskName}CopyResources") {
outputs.dir("${flavorOutDir}/flavor-res")
dependsOn "${taskName}Configure"
doFirst {
copy {
from "flavors/${flavorName}/"
into "${project.buildDir}/flavor-res/"
}
}
}
// This should shadowJar for each flavor - but generate jars dont have the required artifacts.
task ("${taskName}Build", type: ShadowJar) {
from sourceSets.main.output
configurations = [ configurations.runtime ]
classifier = 'SNAPSHOT'
dependsOn "${taskName}CopyResources"
}
task(taskName, dependsOn: ["${taskName}Build"]) {
}
}
}
However, now, the generated jars are malformed. The first flavor gets just the artifacts for main, but no showed jars. The second jar has just the manifest and nothing else.
What would be the correct way of achieving that.
PS: No, its not an android application (flavor is just a synonym for a brand).
I decided to recreate a flavor build script, because it can be simplified to what you have now. The ShadowJar task can handle copying all the classes and resources by itself, there is no need to define separate ones. I also took some default configuration that would have been applied to the shadowJar task and applied this to the custom ShadowJar tasks to get the same behavior.
I first build a quick test project structure which can be found here:
Test Structure
Then I came up with the following script:
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
id 'java'
id "com.github.johnrengelman.shadow" version "2.0.4"
}
group 'your-group'
version 'dev-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
// Example dependency
compile group: 'com.google.guava', name: 'guava', version: '19.0'
}
tasks.addRule("Pattern: flavor<Name>") { def taskName ->
if (!taskName.startsWith("flavor")) {
return
}
def flavorName = taskName - "flavor"
// Define the shadow task
def shadowTask = task ("${flavorName}ShadowJar", type: ShadowJar) {
classifier = flavorName
// Add our flavor resources, first to prioritize these resources
from file("src/main/flavors/${flavorName}")
// Include our project classes
from project.sourceSets.main.output
// Don't include duplicate resources, only the first ones added, in
// this case the flavored resources will override the default ones
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
// Some defaults taken from the default shadowJar task
// https://github.com/johnrengelman/shadow/blob/master/src/main/groovy/com/github/jengelman/gradle/plugins/shadow/ShadowJavaPlugin.groovy#L48
configurations = [ project.configurations.runtime ]
manifest.inheritFrom project.tasks.jar.manifest
exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA')
}
// Define the flavor task
task ("${taskName}", dependsOn: shadowTask) {}
}