I perform the first use of Dagger 2 in my life and I think I encounter some issues that are considered insignificant by expirienced users and thus omitted in their guides.
So I created a simple absolutely empty class that does nothing, marked its constructor with #Inject, then created an interface with #Component annotation with method return type of which is my empty class. Then I invoked gradlew build and Dagger actually generated files that it must have generated. But these files are in build/generated/source/apt/main/com/warden/bot/ directory of my IDEA project whilst source code is in src/main/java/com/warden/bot/ directory of the project, so I can't use Dagger generated code in my program. Should there be a special setup for Dagger before use and what do I do now?
UPD
My build.gradle file is:
plugins {
id "net.ltgt.apt" version "0.12"
}
version '2.0'
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.dagger:dagger:2.11'
apt 'com.google.dagger:dagger-compiler:2.11'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'com.warden.bot.Main'
)
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Related
I am pretty new to using Gradle. I am using Gradle-7.5.1. I just want a jar file created using Gradle that contains just the manifest file and the source files I wrote but why does the created jar contain a million other things in it?
My gradle.build file is as follows:
apply plugin: 'java'
apply plugin: 'application'
version = '1.0'
sourceSets {
main {
java {
srcDirs = ['src']
}
}
}
task fatJar(type: Jar) {
manifest {
attributes 'Manifest-Version': version,
'Class-Path': configurations.runtimeClasspath.files.collect { it.getName() }.join(' ')
}
baseName = 'MyProj'
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
repositories {
mavenCentral()
}
dependencies {
implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' < etc >
}
What I want in the MyProj-1.0 is:
META-INF (holding the Manifest.MF)
com (holding my src files)
What I get in the jar is:
assets
style
corejava
javax
..and a lot more such things
Thanks in advance for any pointers. As I have banged my head to the point of snapping it!
I've seen many people with "Could not find or load main class" errors when making jar files with Gradle. I have gone through many of the forums and have not found a solution that works for me yet. Following an online tutorial, I was able to set up a Gradle project in VSCode and add dependencies for a basic hello world program. Link to the tutorial I was following here: https://www.youtube.com/watch?v=BwdkyrnJQsg
This worked for me no problem but when I finished my much larger program, it doesn't find my Main.class file. Here's my build.gradle file:
plugins {
id 'java'
id 'java-library'
id 'application'
}
application
{
mainClass = 'Main'
}
java
{
sourceCompatibility = JavaVersion.VERSION_12
targetCompatibility = JavaVersion.VERSION_12
}
project.configurations.implementation.setCanBeResolved(true);
version = '1.0.0'
mainClassName = 'Main'
sourceSets
{
main
{
java
{
srcDirs 'src/main/java'
}
}
}
repositories
{
mavenCentral()
maven
{
url = 'https://licensespring-maven.s3.eu-central-1.amazonaws.com/'
}
}
dependencies
{
implementation 'com.licensespring:licensespring-license-client:2.1.0'
// https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java
implementation group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '4.0.0-alpha-6'
// https://mvnrepository.com/artifact/net.harawata/appdirs
implementation group: 'net.harawata', name: 'appdirs', version: '1.2.0'
// https://mvnrepository.com/artifact/net.java.dev.jna/jna-platform
implementation group: 'net.java.dev.jna', name: 'jna-platform', version: '5.6.0'
// https://mvnrepository.com/artifact/net.java.dev.jna/jna
implementation group: 'net.java.dev.jna', name: 'jna', version: '5.6.0'
// https://mvnrepository.com/artifact/org.slf4j/slf4j-api
implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.0-alpha1'
// https://mvnrepository.com/artifact/commons-io/commons-io
implementation group: 'commons-io', name: 'commons-io', version: '2.7'
}
jar
{
manifest
{
attributes(
"Main-Class": "$mainClassName",
"Class-Path": configurations.implementation.collect {it.name}.join(' ')
)
}
dependsOn('dependencies')
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
In src/main/java/ I have my Main.java file with the main method along with all my other .java files. When I run gradlew clean build, my .class files show up under build/classes/java/main.
Just to clarify, when I run java -jar './build/libs/myApplication.jar' I get the Could not find or load main class Main error. Let me know if you need any more specifics.
UPDATE: Switched over to Intellij again and I am getting errors involving the Main Manifest Attribute. I checked the outputted jar and the Manifest file is indeed packaged and it does have a Main Manifest Attribute. PLEASE HELP ME SOMEONE!
Can you try giving source set and full package name for main?
It should look something like this:
sourceSets {
main {
java {
srcDirs 'src/main/java'
}
}
}
project.configurations.implementation.setCanBeResolved(true)
jar{
manifest {
attributes(
"Main-Class": "com.xyz.Main",
"Class-Path": configurations.implementation.collect { it.name }.join(' ')
)
}
dependsOn ('dependencies')
}
I had similar issue to create runnable jar. I could solve it with following example
Solution 1 : Create a fat jar with all dependencies.
task fatJar(type: Jar) {
manifest {attributes 'Main-Class': 'com.example.gradle.App'}
from {
configurations.compile.collect
{ it.isDirectory() ? it : zipTree(it) }
}with jar
}
Solution 2 : Create a runnable jar with dependencies copied to a directory and setting the class path
def dependsDir = "${buildDir}/libs/dependencies/"
task copyDependencies(type: Copy) {
from configurations.compile
into "${dependsDir}"
}
task createJar(dependsOn: copyDependencies, type: Jar) {
manifest {
attributes(
'Main-Class': 'com.example.gradle.App',
'Class-Path': configurations.compile.collect
{ 'dependencies/' + it.getName() }.join(' ')
)}
with jar
}
Read more on this with an example here
After building my gradle jar within intellij, my project will run perfectly fine. If I try to then move that jar to my desktop and run it using the command "java -jar ProjectName.jar" it throws and error "Cannot find or load main class main"
I'm painfully aware that this question has been asked multiple times on this website as I've spent hours trying to fix it. Ever since I reinstalled Intellij I have been having this issue. I've tried making a fat jar and excluding META-INF, I tried creating a whole new project and creating a jar within that project. I also tried to use a recent iteration of this project which did run as a standalone and had no luck.
build.gradle
plugins {
id 'java'
}
group 'PantryDatabase'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile(
[group: 'com.google.cloud', name: 'google-cloud-bigquery', version: '1.74.0'],
[group: 'com.jfoenix', name: 'jfoenix', version: '9.0.8'],
[group: 'me.xdrop', name: 'fuzzywuzzy', version: '1.2.0']
)
}
jar {
manifest {
attributes 'Main-Class': "Main"
}
from configurations.runtime.collect { zipTree(it) }
}
task customFatJar(type: Jar) {
baseName = 'Pantry_Database'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
with jar
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
manifest {
attributes 'Main-Class': 'Main'
}
}
Class Files: https://imgur.com/gallery/HbGJPgr
Error Message: https://imgur.com/gallery/KkHNfas
This question is related to this one -- however, due to the deprecation of compile in favor of implementation, it doesn't work. It does pick up dependencies that are declared with compile. However, with it being deprecated, using it isn't an option (and we'd be right back here when it's removed anyway)
I got this Gradle task:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
And there's just one dependency, looking aside test dependencies:
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation group: 'junit', name: 'junit', version: '4.12'
}
Running from the IDE works fine. However, when I deploy to my Raspberry Pi (or use the jar gradlew fatJar results in locally), I get this exception:
$ java -jar java-sense-hat-1.0a.jar
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at io.github.lunarwatcher.pi.sensehat.UtilsKt.getSenseHat(Utils.kt:18)
at io.github.lunarwatcher.pi.sensehat.SenseHat.<init>(SenseHat.java:12)
at io.github.lunarwatcher.pi.sensehat.Tests.main(Tests.java:9)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 3 more
Which is triggered by this line:
return Optional.empty()
in a Kotlin method returning an Optional<File>. Answer on related question:
Either kotlin-runtime has to be in classpath and verify with $ echo $CLASSPATH.
Or you have to add kotlin-runtime to maven and then assemble inside the jar itself with mvn compile assembly:single,
Which means the kotlin-runtime isn't included in the classpath. Before you go ahead and answer "add kotlin-runtime to your dependencies", it's a part of the stdlib:
Kotlin Runtime (deprecated, use kotlin-stdlib artifact instead)
I use kotlin-stdlib-jdk8 and it works in the IDE. Just for testing purposes, using kotlin-stdlib instead does not change anything.
In addition, replacing implementation with compile fixes it.
In the post I linked at the top of the question, there's a suggestion to use runtime in the fatJar task. So:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
The dependency is still not included, and the program crashes.
So why not add implementation as a configuration to copy from?
I tried. I ended up with this:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.implementation.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
And an exception:
Resolving configuration 'implementation' directly is not allowed
So, considering:
compile instead of implementation works
The runtime exception is from Kotlin not being in the classpath
It works in the IDE
Adding an implementation clause to the fatJar task crashes the compiling with a separate exception
How do I generate a jar with all dependencies in Gradle 4.4 when using the implementation keyword?
Have you tried the Shadow Plugin like:
shadowJar {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
configurations = [project.configurations.compile, project.configurations.runtime]
}
Edit:
You can also do this (as described in an answer for this question):
configurations {
fatJar
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation group: 'junit', name: 'junit', version: '4.12'
fatJar "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.fatJar.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
but then you have to repeat all implementation dependencies as fatJar dependencies. For your current project it's fine since you have only one dependency, but for anything bigger it will become a mess...
Edit 2:
As #Zoe pointed out in the comments this is also an acceptable solution:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.runtimeClasspath.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
however make notice as per source code that runtimeClasspath is a combination of runtimeOnly, runtime and implementation, which may or may not be desirable depending on the situation - for instance you may not want to include runtime dependencies because they are provided by the container.
I have searching to solve this problem for two days and I did not find solution. Firstly I wanted to build fat-jar, then I gave up on that it looked more complicated so I started building normal executable jar. I am building some program inside NetBeans 8.2 with Gradle plugin(http://plugins.netbeans.org/plugin/44510/gradle-support)
My project structure is like this:
Project Structure
I am relatively new to Gradle I am using it less then one month. My build.gradle looks like this:
repositories {
mavenCentral()
}
dependencies {
// TODO: Add dependencies here ..
// // http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
// testCompile group: 'junit', name: 'junit', version: '4.10'
// https://mvnrepository.com/artifact/org.apache.poi/poi
compile group: 'org.apache.poi', name: 'poi', version: '3.16'
// https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml
compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.16'
// https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '2.0.6'
}
apply plugin: 'java'
mainClassName = "paket.Glavna"
jar {
from {
(configurations.runtime).collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes("Main-Class": "Glavna" )
}
}
Now, I cant get it working to make executable jar. I think i have traced problem that there isnt path to main class in jar but I dont know why it isnt adding it. Error i get is:
Error: Could not find or load main class DnevniIzvestajG-1.0.jar
jar runs with (inside Glavna class is main):
java -cp projectname.jar paket.Glavna
Also I have tried running
manifest-addition
but taht also didnt add link to main class.
Try adding a package to the class with main() method.
jar {
archiveName = 'Glavna.jar'
manifest {attributes 'Main-Class': 'paket.Glavna'}
from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }) {}
}
Building a fat jar like this is not preferable, try the Application plugin
I use below way to add all dependencies in .jar of gradle project.
build.gradle :-
jar {
manifest {
attributes(
'Main-Class': 'com.main.MainClass'
)
}
duplicatesStrategy = DuplicatesStrategy.INCLUDE
from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}