Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Packing a single executable fat-Jar does not work #264

Closed
sap-ali opened this issue Apr 3, 2024 · 2 comments · Fixed by #265
Closed

Packing a single executable fat-Jar does not work #264

sap-ali opened this issue Apr 3, 2024 · 2 comments · Fixed by #265

Comments

@sap-ali
Copy link
Contributor

sap-ali commented Apr 3, 2024

Hi team,

We have a runnable fat-jar and when I tried to configure the buildpack to simply pack it and run it, I keep running into the buildpack detecting it as an exploded Jar. In other words, I could not configure it to reach

jarPath, props, err = findExecutableJAR(appPath, executableJarGlob)
. I forked the repository and commented out the exploded Jar detection if and everything worked fine.

Expected Behavior

Allow packing a single executable fat-Jar.

Current Behavior

Only performs to pack an exploded Jar.

Possible Solution

I can see a few possibilities to fix it:

  • Adjust the condition that detects whether it is an exploded Jar
  • Make the buildpack participation conditions disjuctive, that is, if a runnable jar is detected, then it is a jar, if not, require a MANIFEST.MF and treat it as exploded Jar

Steps to Reproduce

  1. Create an executable far-Jar
  2. Define project.toml as:
[_]
schema-version = "0.2"
id = "com.test.jar"
name = "Test Fat Jar"

[[io.buildpacks.group]]
uri = "gcr.io/paketo-buildpacks/sap-machine"

[[io.buildpacks.group]]
uri = "gcr.io/paketo-buildpacks/syft"

[[io.buildpacks.group]]
uri = "gcr.io/paketo-buildpacks/executable-jar"

[[io.buildpacks.build.env]]
name = "BP_JVM_VERSION"
value = "21"
  1. [this step is required only due to the activation conditions] Extract jar's MANIFEST.MF into META-INF/MANIFEST.MF
  2. Build the package by running:
pack build example:latest \
  --descriptor project.toml \
  --builder paketobuildpacks/builder:base
  1. Run the image by:
docker run --name example --rm example
  1. The following error is received:
Error: Could not find or load main class [class name in the extracted MANIFEST.MF]
Caused by: java.lang.ClassNotFoundException: [class name in the extracted MANIFEST.MF]

Looking at the generated image layer, the contents of the layer seem as expected:

Permission     UID:GID       Size  Filetree                                     
drwxrwxrwx   1000:1000      76 MB  └── workspace                                
drwxr-xr-x   1000:1000       68 B      ├── META-INF                             
-rw-rw----   1000:1000       68 B      │   └── MANIFEST.MF                      
-rw-r--r--   1000:1000      76 MB      └── example.jar

Motivations

I cannot use the buildpack to package my jar file and for me renders the buildpack unusable, however, as I have read in the tests, this is one of the desired usecases of using this buildpack. It would be great if we can either fix the issue or clarify the detailed conditions in which it can be used in such a scenario.

@dmikusa
Copy link
Contributor

dmikusa commented Apr 3, 2024

Sorry, I'm not completely following your steps to reproduce so taking a guess here.

What you're seeing might be due to the way that the pack cli works. When you point the cli to a pre-compiled JAR file (or any zip archive), it will first extract everything and then pass the contents along to the build environment. By the time buildpacks run, there's not any JAR file in the working directory. The working directory has the contents of the JAR file.

There's unfortunately no flag for pack to tell it not to do this. What you have to do instead is to put your JAR file inside a directory, then point pack to the directory that contains your JAR file. Then pack will pass the contents of that directory (i.e. your raw JAR file) along to the buildpacks.

If you're doing this and you've gotten the JAR file into the container properly, then you should move past the logic you referenced and the buildpack should be able to look for the executable JAR.

Having said all that, if you have an executable JAR file that's self-contained you shouldn't need it to be a JAR in the build environment. The buildpack knows how to take the exploded JAR and run that (it is actually a bit faster, cause there's nothing to extract). If I remember correctly, we added the ability to run from the JAR for Quarkus apps, which are packaged up slightly differently. If your app can be java -jar run locally (and it doesn't depend on anything outside of the JAR), then it should work just fine with the standard behavior of the buildpack.

@sap-ali
Copy link
Contributor Author

sap-ali commented Apr 3, 2024

@dmikusa Thanks for getting back to me.

Yes, indeed we have a Quarkus app, however, we see a different behavior when the JAR is exploded in the image. Could be as what you said due to how Quarkus packages, or also due to the modified classpath that might cause conflicts with whatever additional classpath the environment has.

Therefore, it would be great if we can simply have the exact artifact in the image and not have it manipulated in any way.

I have fixed the issue in a PR #265, so if you could please have a look when you have some time, it would be greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants