I want to build a jar file in IntelliJ IDEA with Gradle.
When I run my code in Intellij everything works fine,
but when I run the jar file I get an error:
SQLExecption: No suitable driver found for jdbc:sqlite:/applications/elite-dangerous/database/ED_Database.db
I build the jar throw pressing the build button.
It's strange for me because it works perfectly fine when I run it in IntelliJ IDEA.
Dependencies included using implementation config are not being included in the Jar which makes them not available in runtime. So, I guess that could be the case. You can try changing implementation to compile dependencies ( which is deprecated, so not recommended ) or You can include your dependencies in the jar as below
jar {
manifest {
attributes 'Main-Class': 'eliteDangerousRestUpdater.Main'
}
from {
compileJava.classpath.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
Related
I have a simple groovy script with a single java library dependency:
package com.mrhacki.myApp
import me.tongfei.progressbar.ProgressBar
class Loading {
static void main(String[] arguments) {
List list = ["file1", "file2", "file3"]
for (String x : ProgressBar.wrap(list, "TaskName")) {
println(x)
}
}
}
I'm using gradle to manage the dependencies of the project. The gradle configuration for the project is pretty straightforward too:
plugins {
id 'groovy'
}
group 'com.mrhacki'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
compile 'me.tongfei:progressbar:0.7.2'
}
If I run the script from the Intellij IDE, the script is executed as expected.
What I would like to do now is to compile the script with this dependency into one single .jar file, so I can distribute it as such, and run the application from any filesystem path, as the script logic will be dependent on the path from which the execution was called.
I've tried with a few gradle fat jars examples out there but none have worked for me since the .jar file is constantly throwing Could not find or load main class Loading when I try it to run.
If anyone would be so kind to give a hint or to show an example of a gradle task that would do a build that fits my described needs I would be very gratefull.
I'm aware of the groovy module Grape with the #Grab annotation too, but I would leave that as a last resort since I don't want the users to wait for the dependencies download, and would like to bundle them with the app.
I'm using groovy 2.5.6 and gradle 4.10 for the project
Thanks
You can simply create the fat-jar yourself, without any extra plugin, using the jar Task. For a simple/small project like yours, it should be straightforward :
jar {
manifest {
// required attribute "Main-Class"
attributes "Main-Class": "com.mrhacki.myApp.Loading"
}
// collect (and unzip) dependencies into the fat jar
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
EDIT : pleas take other comments into consideration: if you have more that one external lib you might have issues with this solution, so you should go for a solution with "shadow" plugins in this case.
I have some library Gradle Java projects that I am currently publishing to my local Maven repositoty with the publishToMavenLocal task. I can look for a library called base file in my local .m2\repository\... area, and find it as (say):
... lib\base\08.00.003-SNAPSHOT\base-08.00.003-SNAPSHOT.jar
A client project, socket_listener uses base and declares the local repository as shown. This project build fine and runs successfully from the Gradle command line.
repositories {
mavenLocal()
jcenter()
}
// later in the file...
//
assemble.dependsOn distDirectory
Run ...
gradle socket_listener:run
:
lots of logger output
:
The socket_listener project creates a dist directory for the socket_listener.jar assembly with requried dependencies in a lib/* folder for dependencies with this:
task distDirectory( type: Copy ) {
into 'dist'
from jar
from 'src/dist'
into( 'lib' )
{
from configurations.runtime
}
}
Which I also thought was OK until I tried to run my listener project from the command line; it fails thus.
cd socket_listener\dist
java -jar SocketListener.jar
Gives error (manifest setting below):
Error: Could not find or load main class example.app.cmd.SocketListener
And when I inspected the lib/ folder -- NO base-08.00.003-SNAPSHOT.jar was to be found. None of the mavenLocal JAR files are in lib/. This is my first hurdle, the program won't work without those mavenLocal JAR-s.
As well manifest settings in gradle are just copies from other working projects.
mainClassName = 'example.app.cmd.SocketListener'
:
jar
{
manifest
{
attributes( "Main-Class": mainClassName )
attributes( "Application-Name": "socket_listener" )
attributes( "Class-Path": 'lib/' + ( configurations.runtime.collect { it.getName() }.join(' lib/') ) )
attributes( "Codebase": "*" )
attributes( "Permissions": "all-permissions" )
}
}
That should not be problem #2.
Upon discovering base-08.00.003-SNAPSHOT.jar missing-in-action from the lib/ directory, I set about to find that file. Guess what?
The ONLY place I found the JAR file is in the Maven repositor, viz.:
dir /s/b d:\*08.00.003-SNAPSHOT.jar
d:\.rep\.m2\repository\local\lib\driver_model\08.00.003-SNAPSHOT\driver_model-08.00.003-SNAPSHOT.jar
d:\.rep\.m2\repository\local\lib\base\08.00.003-SNAPSHOT\base-08.00.003-SNAPSHOT.jar
dir /s/b d:\*08.00.003-SNAPSHOT.jar
File Not Found
Which is kind of same as a linux find / -name "*08.00.003-SNAPSHOT.jar" command. That's every directory on the PC, directly after a successful
gradle socket_listener:build -x test --refresh-dependencies
gradle socket_listener:run
And ensuring the latest dependencies loaded. From my little experiemtal result it is quite clear that the project's Gradle build is using the library JAR-s directly from the repository -- For build, for run, for test.
This is completly UNEXPECTED ...
My collegues and I feel sure that other locally build artefacts were cached or at least saved locally to a dist/ folder. In ths example the base JAR is not copied anywhere.
Can I force the mavenLocal assets to be (at least) copied into the lib/ folder and be ready for use?
In addition, looking into the contents of the current SocketListener.jar's manifest I am not convinced that all requisite JAR files have been loaded. For a start, things that my base JAR depends are also will be missing. I feel that other up-stream dependencies are NOT there either.
What is the usual process to ensure all dependencies are gathered for a build and for running a Java command line app from both Gradle and the command line prompt??
Is it normal to use the maven repository like that?
How can it be overridden?
I have discovered that configurations.runtime is not what I need.
The from clause in the distDirectory task should
As follows
task distDirectory( type: Copy ) {
into 'dist'
from jar
from 'src/dist'
into( 'lib' )
{
from configurations.from configurations.runtimeClasspath
}
}
runtimeClasspath gives me all the direct dependencies for socket_listener.
I am unsure 'how' the build.gradle I took that model from performs for other projects. I expect those projects make an installer and don't need to use that dist/ folder explicitly.
Also, afer some testing and experimentation it is confirmed that this JAR won't run unless the Manifest also uses runtimeClasspath collection (or compileClasspath), viz.
jar {
manifest {
attributes( "Main-Class": mainClassName )
attributes( "Application-Name": "socket_listener" )
attributes( "Class-Path": 'lib/' + ( configurations.runtimeClasspath.collect { it.getName() }.join(' lib/') ) )
attributes( "Codebase": "*" )
attributes( "Permissions": "all-permissions" )
}
}
However, I suspect that is Not Always the case. The main class SocketListener probably needs an absent JAR in the runtimeClasspath to load. Other programs may load fine. They may fall over with a stacktrace that will identify were look. Or just work OK.
Would that the java launcher would be as nice.
Btw, I didn't find ClassPath mentioned in any of the many 'simple Gradle examples` for making a JAR that runs outh there the web. While you can build without a ClassPath, it is better to have one for real-world use imho.
On to practical matters. This problem arose because the build.gradle file in question uses: implementation( ... ) dependency specifications instead of:compile( ... ) dependencies.
I was able to confirm this by moving one dependency from an implementation to a compile line and use the runtime collection. The resulting JAR and lib/ have the module I moved.
I leave which one you use to the reader. Here's some references:
Recognizing API and implementation dependencies (The Java Library Plugin)
API and implementation separation (java plugin)
Declaring a concrete version of a dependency (Declaring Dependencies)
I am using Gradle build in my java application. My project has the elasticsearch intergation test. Following is my gradle.build
jar {
baseName = 'myproject'
version = 'V.4.0.0'
manifest {
attributes 'Main-Class': 'com.myapp.Application'
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
test {
systemProperties = System.properties
systemProperty 'tests.security.manager', 'false'
}
When i give gradle build it executed the test and created the myproject-V.4.0.0.jar. but when i run the
java -cp myproject-V.4.0.0.jar;junit-4.11.jar junit.textui.TestRunner com.myapp.test.testclassname
i got class not found exception for com.myapplication.test.testclassname.
I extracted the myproject-V.4.0.0.jar and can not find the test class.
My question is, How can i include the test class also in my application jar?
This is a deliberate behaviour of gradle java projects. A jar is your production artifact, so usually you want to test it during the build, but you do not want to run your tests in production, so I do not recommend doing it. Having said that, there is a way of doing it in gradle, like this:
task myJar(type:Jar) {
from {sourceSets.main.output + sourceSets.test.output}
}
Is there a tutorial explaining how to properly create a Java Gradle project and build the .jar file?
When I create a Java project and add Gradle: File -> New -> Module -> Gradle -> ... I receive errors about Java EE websocket's not available (I'm using Ultimate Edition). However, I can successfully create a project by selecting File -> New -> Project-> Gradle -> which gives me a Java project with Gradle that I can debug. However, when I try to create an artifact (.jar file) I receive errors. I assume the errors stem from mistakes I made in the project structure settings.
Buildfile: build.xml does not exist!
Build failed
or
Error: Could not find or load main class Main
My project is such a mess at this point, maybe I should create another project, then copy/paste the Main.class and Gradle's dependencies from the old project onto the new project.
If this is my best option, how do I correctly create the project this time?
Create new Gradle (not Java) project. Be sure to select Java option in the dialog. Click Next.
fill GroupId, ArtifactId and version
Choose your gradle distribution. You can safely use the reccommended option.
Choose project name and location
Click finish
You put your java classes to src/main/java folder. When using third party libraries, make sure you declare them as Gradle dependencies.
You build your sources using Gradle tab → tasks → build (double click)
You can see the result of the build in the Run tab
In case of error, you can see details by clicking the following button:
Just incase you run into no main manifest attribute problem where the executable Jar file is not running, I do the following.
1: go to your build.gradle and add the following at the bottom.
jar {
manifest {
attributes 'Main-Class': 'your_package_name.YOUR_MAIN_CLASS'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
go to View > Tool Windows > Gradle
A panel at the right side will be shown, now click the build for more task. Under the build task double click the build option and wait until the task is done.
Now, go to your project directory and open the build > libs and the executable Jar file will be there.
I'm not sure if this is the right way.
No need to accept if it works, hope this help the others.
Step 1: Add these lines on your build.gradle
jar {
from {
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'YOUR MAIN CLASS'
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
Step 2: clean and build .
I'm sure it will work , Regards
If you are using Intellij you can just open the Gradle plugin (it is on the right side of your IDE) and execute a command: bootRepackage. With this you will have a jar in: your_project_folder/build/libs.
I am trying to make my application work in a stand alone jar. The problem is, a jar is generated for my program, and a bunch of other jars are generated for the libraries. Is there any way to get these jars to get inside one? I am using Gradle if that helps.
The IntelliJ IDEA artifact config:
The output directory:
What I expected (and want) to happen:
You need a fat-jar (jar file with all it's dependencies inside). It's not a big problem for Gradle, you just need to make one additional task of type jar, which will collect all the dependencies and zip it alltogether
There are many examples, how you can do it, here is one of them. Take a closer look at task fatJar:
task fatJar(type: Jar) {
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}