Gradle fatJar/uberJar causing Could not find or load main class - java

I'm having an issue where gradle fatJar/uberJar is causing the following exception when trying to run the jar:
Error: Could not find or load main class com.domhauton.membrane.Main
The simple jar task without
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
works with no issues (up to the point where it starts needing dependencies).
I presume this is to do with one of my dependencies changing the classpath, but I'm not sure why that would be happening.
Relevant part of build.gradle
project.version = '1.0.0-alpha.2'
project.group = 'com.domhauton.membrane'
jar {
baseName = 'membrane-daemon-simple'
version = project.version
manifest {
attributes 'Implementation-Title': 'Membrane Daemon',
'Implementation-Version': project.version,
'Main-Class': project.group + '.Main'
}
}
//create a single Jar with all dependencies
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Membrane Daemon',
'Implementation-Version': project.version,
'Main-Class': project.group + '.Main'
}
baseName = 'membrane-daemon'
version = project.version
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
Gradle build file is here (with the remainder of code):
https://github.com/domhauton/membraned/blob/master/build.gradle
The META-INF folder is very full of files from the other dependencies so I'm not sure where to start looking for conflicts.

Took another run at the problem using shadowjar and it worked flawlessly.
Relevant code:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath group: 'com.github.jengelman.gradle.plugins', name: 'shadow', version: '1.2.4'
}
}
apply plugin: 'com.github.johnrengelman.shadow'
project.version = '1.0.0-alpha.2'
project.group = 'com.domhauton.membrane'
jar {
baseName = 'membrane-daemon'
version = project.version
manifest {
attributes 'Implementation-Title': 'Membrane Daemon',
'Implementation-Version': project.version,
'Main-Class': project.group + '.Main'
}
}
Can be seen in context here: https://github.com/domhauton/membraned/blob/4d28ea451acc5bf52724a0cc5c94823659236287/build.gradle

Related

Gradle does not import added dependency after build operation

I am using spring-boot version 1.5.12 and gradle 5.2.1.
I have added Sentry library in my project as mentioned in its documents like below :
implementation 'io.sentry:sentry:1.7.23'
Gradle downloads the related jarFile in : \.gradle\caches\modules-2\files-2.1\io.sentry\sentry\1.7.23
and also I can see it in my IDE in External Libraries part
then I configed it in my local environment and everything worked fine and I could see my Exception reports in Sentry dashboard.
but after that when I wanted to create a version of project for my production environment, the build operation ended successfully but this new library is not in the folder(which is the result of my build operation named Distribution) which contains myPro.jar and other libraries that I use , I faced the Exception :
Exception in thread "main" java.lang.NoClassDefFoundError: io/sentry/Sentry
at ir.anarestan.ipc.boot.Boot.initSentry(Boot.java:22)
at ir.anarestan.ipc.boot.Boot.main(Boot.java:17)
Caused by: java.lang.ClassNotFoundException: io.sentry.Sentry
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
here is my build.gradle file :
group 'pc-server'
version '0.2.1-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'groovy'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
<some other dependecies>
implementation 'io.sentry:sentry:1.7.23'
}
apply plugin: 'application'
mainClassName = 'ir.anarestan.ipc.boot.Boot'
jar {
manifest {
attributes 'Main-Class': mainClassName,
'Class-Path': configurations.runtime.files.collect {"$it.name"}.join(' ')
}
}
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File PC',
'Implementation-Version': version,
'Main-Class': 'ir.anarestan.ipc.boot.Boot'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
ext.distributionDir= "${rootDir}/dist/core"
ext.mainClassName = 'ir.anarestan.ipc.boot.Boot'
jar {
manifest {
attributes("Implementation-Title": project.name,
"Implementation-Version": version,
"Main-Class": mainClassName,
"Class-Path": configurations.compile.collect { it.getName() }.join(' '))
}
destinationDir = file("$distributionDir")
}
task copyLibs(type: Copy){
from configurations.compile
into "$distributionDir"
}
task copyConfig(type: Copy){
from "$projectDir/src/main/resources/"
into "$distributionDir"
}
task distribution(dependsOn: ['copyLibs', 'copyConfig', 'jar']){
}
and I face Exception here :
#SpringBootApplication
#EnableMongoRepositories(basePackages = {"ir.anarestan.ipc.repository.mongodb"})
public class Boot {
public static void main(String[] args) {
SpringApplication.run(Boot.class, args);
Sentry.init();
}
}
any help would be appreciated, it has take me lots of time!!!

How to solve: Could not run build action using connection to Gradle distribution issue in eclipse?

The problem occurred, In eclipse, the project was refreshed by right-clicked project > Gradle > Refresh Gradle Project
I have tried different approaches, downloading \gradle-4.3.1 file, and by going window > preferences > local installation directory > c:\gradle-4.3.1
Gradle Project structure
apply plugin: 'java'
repositories {
mavenCentral()
}
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "com.github.jengelman.gradle.plugins:shadow:6.1.0"
}
}
apply plugin: "com.github.johnrengelman.shadow"
task fatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.XXXX.webservices.samples.Controller'
}
baseName = 'XXXXX'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
jar {
baseName = 'XXXX'
from('src/main') {
include 'resources/*.properties'
}
manifest {
attributes 'Main-Class': 'com.netsuite.webservices.samples.Controller'
}
}
dependencies {
compile fileTree(dir: 'lib', includes: ['suitetalk-*0.jar'])
compile 'axis:axis:1.4'
runtime 'commons-httpclient:commons-httpclient:3.1'
runtime 'org.slf4j:log4j-over-slf4j:1.7.6'
runtime 'org.slf4j:slf4j-nop:1.7.25'
compileOnly 'com.google.code.findbugs:jsr305:3.0.1'
}
apply plugin: 'com.github.johnrengelman.shadow'
task runApplication(type: JavaExec) {
description "Builds and executes the sample application"
classpath = sourceSets.main.runtimeClasspath
main = "com.netsuite.webservices.samples.Controller"
standardInput = System.in
}

Proguard example for gradle java application

I am new to obfuscation and trying to figure out how to obfuscate a java application created using gradle. The idea is that the runnable jar created after the gradle build is obfuscated. Here is the gradle file
plugins {
// Apply the java plugin to add support for Java
id 'java'
// Apply the application plugin to add support for building a CLI application.
id 'application'
}
repositories {
mavenCentral()
}
dependencies {
// This dependency is used by the application.
implementation 'com.google.guava:guava:29.0-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.13'
}
application {
// Define the main class for the application.
mainClassName = 'com.abc.gradle.hello.App'
}
jar {
manifest {
attributes 'Main-Class': 'com.abc.gradle.hello.App'
}
}
Finally I could achieve this with the following steps
Create a runnable jar with all dependent libraries copied to a directory "dependencies" and add the classpath in the manifest.
task createJar(type: Jar) {
println("Cleaning...")
clean
manifest {
attributes('Main-Class': 'com.abc.gradle.hello.App',
'Class-Path': configurations.default.collect { 'dependencies/' +
it.getName() }.join(' ')
)
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it)
}
} with jar
println "${outputJar} created"
}
Copy the dependencies
task copyDepends(type: Copy) {
from configurations.default
into "${dependsDir}"
}
Obfuscate the library with Proguard
task proguard(type: proguard.gradle.ProGuardTask) {
println("Performing obfuscation..")
configuration 'proguard.conf'
injars "${outputJar}"
outjars "${buildDir}/libs/${rootProject.name}_proguard.jar"
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
libraryjars "${dependsDir}"
}
Here is the complete build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'net.sf.proguard:proguard-gradle:6.0.3'
classpath 'net.sf.proguard:proguard-base:6.0.3'
}
}
plugins {
id 'java'
id 'application'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.slf4j:slf4j-api:1.7.30'
implementation 'ch.qos.logback:logback-classic:1.2.3'
implementation 'ch.qos.logback:logback-core:1.2.3'
testImplementation 'junit:junit:4.13'
}
def outputJar = "${buildDir}/libs/${rootProject.name}.jar"
def dependsDir = "${buildDir}/libs/dependencies/"
def runnableJar = "${rootProject.name}_fat.jar";
task copyDepends(type: Copy) {
from configurations.default
into "${dependsDir}"
}
task createJar(type: Jar) {
println("Cleaning...")
clean
manifest {
attributes('Main-Class': 'com.abc.gradle.hello.App',
'Class-Path': configurations.default.collect { 'dependencies/' +
it.getName() }.join(' ')
)
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
} with jar
println "${outputJar} created"
}
task proguard(type: proguard.gradle.ProGuardTask) {
println("Performing obfuscation..")
configuration 'proguard.conf'
injars "${outputJar}"
outjars "${buildDir}/libs/${rootProject.name}_proguard.jar"
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
libraryjars "${dependsDir}"
}
Proguard.conf
-keep public class * {
public * ;
}
Gradle commands to obfuscate
gradle createJar
gradle copyDepends
gradle proguard

Kotlin+Gradle runnable jar - dependency causing "Could not find or load main class"

Gradle build file:
buildscript {
ext.kotlin_version = '1.2.41'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
group 'com.anivive'
version '0.1'
apply plugin: 'kotlin'
sourceSets {
main.java.srcDirs += 'src/main/kotlin/'
test.java.srcDirs += 'src/test/kotlin/'
}
repositories {
mavenLocal()
maven {
url "https://packagecloud.io/anivive/anivive/maven2"
}
mavenCentral()
}
dependencies {
compile 'anivive:Import_Utils:1.2.44'
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
jar {
baseName = 'XMLModelBuilder'
version = '0.1'
manifest {
attributes 'Main-Class': 'com.anivive.Main'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
File structure:
src
- main
- kotlin
- com
- anivive
- Main.kt
Main.kt:
package com.anivive
import com.anivive.util.ExampleClass
object Main {
#JvmStatic
fun main(args: Array<String>) {
ExampleClass.exampleMethod()
}
}
So, I'm trying to build a runnable jar file that will call a single method from a class in the dependency 'anivive:Import_Utils:1.2.44'.
If I remove the dependency, and change my main method to just println("Test"), the jar will run fine via java -jar build/libs/jarFile.jar and it will print out Test.
However, with the dependency included and when trying to call a function from it, I will get Error: Could not find or load main class com.anivive.Main whenever I try to run the Jar file. I suspect it has something to do with hosting the jar file on packagecloud, but I'm surprised this is a problem, considering I can run the program just fine from IntelliJ.
What gives?

Can't run generated JAR file with Gradle and Kotlin

I have a project configured with Gradle and Kotlin. It's a command line utility and I would like to be able to run the generated jar from my terminal. However I get the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at com.autentia.impt.MainKt.main(Main.kt)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
My gradle configuration is as follows:
buildscript {
ext.kotlin_version = '1.2.20'
ext.junit_platform_version = '1.0.1'
ext.junit_version = '5.0.0'
ext.moshi_version = '1.5.0'
ext.jna_version = '4.5.0'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.junit.platform:junit-platform-gradle-plugin:$junit_platform_version"
}
}
version '1.0-SNAPSHOT'
apply plugin: 'kotlin'
apply plugin: 'application'
apply plugin: 'org.junit.platform.gradle.plugin'
mainClassName = 'com.autentia.impt.MainKt'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.squareup.moshi:moshi:$moshi_version"
implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
implementation "net.java.dev.jna:jna:$jna_version"
testImplementation("org.junit.jupiter:junit-jupiter-api:$junit_version")
testRuntime("org.junit.jupiter:junit-jupiter-engine:$junit_version")
}
sourceSets {
main.kotlin.srcDirs += 'src/main/kotlin'
}
task wrapper(type: Wrapper) {
gradleVersion = '4.4.1'
}
jar {
manifest {
attributes "Main-Class": mainClassName
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
The command I use to generate the jar is ./gradlew clean build and the command I use to run the jar is java -jar build/libs/impt-1.0-SNAPSHOT.jar.
I've tried following the official docs and also I've tried with these resources: 1, 2 and 3 without any luck.
Just change implementation configurations to compile. (At least for kotlin-stdlib)
The compile configuration is deprecated and should be replaced by implementation or api in Gradle plugin for Android, however for kotlin-gradle-plugin, I think you still need compile.
Alright I had the same problem and finally figured this out:
My main class name was Main.kt and this is what I had in my build.gradle file when I was getting the same error:
jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': "play.Main"
)
}
}
Although I noticed when I create the jar artifact in Intellij, it uses play.MainKt as my Main-Class name (yeah, weird naming convention), then I changed my build.gradle file to this:
jar {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': "play.MainKt"
)
}
}
and now I am not getting that error.

Categories

Resources