Problems creating executable jar using IDEA "Artifact" definition (while Gradle/Kotlin is used as build tool)

Answered

Using IntelliJ IDEA 2022.2.5 (Ultimate):

I have decided to create a Spring Boot project using Gradle build tool with the Kotlin DSL (as the Gradle manual says: "Android Studio and IntelliJ IDEA users should consider using Kotlin DSL build scripts for the superior IDE support when editing them.")

Now I have a minimal amount of code that compiles and runs. It does nothing, it is just the intial "tacos" skeleton application from the book "Spring in Action". Note that the book prefers maven as build tool.

Now I want to package the application as an "executable jar" I have these options:

Possibility 1: Add a gradle task to build the jar and run Gradle

I can add a Gradle task to the script build.gradle.kts and run the task from the IDE (or using the gradlew executable from the command line).

I have added the following, but it doesn't work ... yet (need to dig further, but let's disregard this problem and move to possibility 2)

// https://docs.gradle.org/current/samples/sample_building_kotlin_libraries.html#assemble_the_library_jar

tasks.jar {
manifest {
attributes(mapOf("Main-Class" to "tacos.TacoCloudApplication"))
}
}

Possibility 2: Define a jar 'Artifact' in IDEA and generate that

According to

https://www.jetbrains.com/idea/guide/tutorials/hello-world/packaging-the-application/

  1. Mouse into "File" > "Project Structure"
  2. In the left bar, select "Project Settings" > "Artifacts"
  3. Bonk on "+" to create a new artifact, in this case "taco-cloud:jar"
  4. In the "Output Layout" tab, if you select the "taco-cloud.jar" toplevel entry, you can add "manifest" file properties

The manifest file location is chosen and the "main class" is given as "tacos.TacoCloudApplication".

A file "MANIFEST.MF" shows up at the expected place, which is under "src/main/resources/META-INF/MANIFEST.MF", with the following content:

Manifest-Version: 1.0
Main-Class: tacos.TacoCloudApplication

So far so good.

Let's generate the executable jar then.

Mousing to "Build" > "Build Artifacts" gives us a popup and so we execute the build command

The "taco-cloud.jar" can now be found in "$PROJECT_TOPLEVEL/out/taco-cloud.jar"

However!

In that jar, the "META-INF/MANIFEST.MF" is not the correct one. In fact it is the one for Jackson FasterXML,which is surprising:

Manifest-Version: 1.0
Bundle-License: https://www.apache.org/licenses/LICENSE-2.0.txt
Bundle-SymbolicName: com.fasterxml.jackson.core.jackson-core
Implementation-Vendor-Id: com.fasterxml.jackson.core
Specification-Title: Jackson-core
Bundle-DocURL: https://github.com/FasterXML/jackson-core
Import-Package: com.fasterxml.jackson.core;version="[2.15,3)"...

Evidently the jar won't be executable with that.

$ java -jar ./IdeaProjects/taco-cloud/out/taco-cloud.jar 
no main manifest attribute, in ./IdeaProjects/taco-cloud/out/taco-cloud.jar

So something is going wrong, but what?

 

 

0
6 comments

Thank you for the detailed explanation.
Unfortunately, it is still not clear what is a root cause of the issue.
Is it possible to share a sample project to try and reproduce on our side?

I tried reproducing with project: https://github.com/theEmperorofDaiViet/taco-cloud, but couldn't.
MANIFEST.MF file contains correct attributes:

Manifest-Version: 1.0
Main-Class: tacos.TacoCloud2Application

Also, I see you are using an older version of IntelliJ 2022.2.5 - if possible update to the latest release as lots of bugs has been fixed in the meantime: https://www.jetbrains.com/idea/download

0

Thank you Ivan,

I typed in the taco-cloud project from the book, it is very minimal at this point.

So I updated to 2023.1.2 (Ultimate)

This seems to have gone quite smoothly (I can even move the toplevel directorioes of the toolbox and the IDE around with no ill effects, well done!)

But building the jar has not improved.

Again, under "File" > "Project Structure", then "Project Settings" > "Artifacts".

  1. I deleted the existing "taco-cloud.jar" artifact
  2. Bonk on "+" > "Jar" > "from Module with dependencies" to recreate it
  3. "Module" left as "<All Modules>"
  4. "Main Class" set to "tacos.TacoCloudApplication"

IDEA proposes as "Directoy for META-INF/MANIFEST.MF" the directory "/home/aloy/IdeaProjects/taco-cloud/src/main/resources".

Good!

Hitting OK brings us the following which looks good:

Note the output directory "/home/aloy/IdeaProjects/taco-cloud/out/artifacts/taco_cloud_jar"

But mousing to "Build" > "Build Artifacts" and building the artifact does nothing at this point. Not even tool output.

It must be something completely simple.

How do I attach the exported project zip?

... If you extract the tail of the attached jpg like so:

dd if=AliceAndTheZipFile.jpg bs=1024 skip=24 of=taco-cloud.zip

You get the project zipfile, but there must be a better way.

0

Thanks for the additional information.

Actually, I just remembered there is a known issue with building artifacts in the new UI: https://youtrack.jetbrains.com/issue/IDEA-316889
It will be solved in the next release 2023.2, and it is actually already solved in the EAP version: https://www.jetbrains.com/idea/nextversion

As a workaround you can press Shift key two times to invoke Search Everywhere > type 'build artifacts' in search box.
As another workaround, you can switch back to the 'old' UI - Settings (`⌘ + ,` or `Ctrl + Alt + S`) > Appearance & Behavior > New UI > disable option 'Enable new UI' > restart IDE.

Sorry for not telling you before.
Yes, I forgot to mention that you can upload your project zip via: https://uploads.jetbrains.com, just provide the uploaded file ID.

0

Thank you Ivan.

As a workaround you can press Shift key two times to invoke Search Everywhere > type 'build artifacts' in search box

Yes, using this as a way to start the artifact build works.

Ok, so now I have indeed the taco-cloud.jar, but it still doesn't have the correct MANIFEST.MF seems to be the one for io.micrometer.observation.

Let me upload my super-minimal taco-cloud.zip

Upload ID: 2023_06_15_xgv4icnj9emWws5SGiShjv

 

0

Thank you for the exported project.

I managed to reproduce the issue and it looks like it is conflicting with the gradle configuration. I will have to check further what is the exact root cause.

Basically, when using Gradle or Maven in the project, IntelliJ takes build.gradle or pom.xml configuration as a single source of truth. It takes precedence over the IntelliJ build feature and UI settings get overwritten when a gradle project reload is performed. Also, build tools such as Gradle are a lot more flexible and configurable than the IntelliJ UI for building projects/artifacts etc, so it is recommended to use it for bigger projects.

To make the jar with Gradle you can add following to your build.gradle.kts file:

tasks.withType<Jar> {

duplicatesStrategy = DuplicatesStrategy.EXCLUDE

manifest {
attributes ["Main-Class"] = "tacos.TacoCloudApplication"
}
configurations["compileClasspath"].forEach { file: File ->
from(zipTree(file.absoluteFile))
}
}

and run the build task in Gradle tool window. It will create the build/libs/taco-cloud-0.0.1-SNAPSHOT-plain.jar file which contains the manifest.mf with main-class property:

0

Thank you Ivan.

Yes, that works fine, getting

taco-cloud-0.0.1-SNAPSHOT.jar
taco-cloud-0.0.1-SNAPSHOT-plain.jar

inside the build/libs directory.

The "plain" jar is executable, the other one seems to have no "tacos" package (?).

So, got it: Rely on Gradle (or Maven, as the case may be).

Best regards,

-- David

 

 

 

 

0

Please sign in to leave a comment.