paketo-buildpacks / executable-jar

A Cloud Native Buildpack that contributes a Process Type for executable JARs.
Apache License 2.0
15 stars 7 forks source link

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

Closed sap-ali closed 4 months ago

sap-ali commented 7 months ago

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 https://github.com/paketo-buildpacks/executable-jar/blob/50bd25d87a7ce37cb10fef4b9084d9489bab071c/executable/executable_jar.go#L56. 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:

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"

3. [this step is required only due to the activation conditions] Extract jar's MANIFEST.MF into META-INF/MANIFEST.MF
4. Build the package by running:

pack build example:latest \ --descriptor project.toml \ --builder paketobuildpacks/builder:base

6. Run the image by:

docker run --name example --rm example

7. 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
<!--- How has this issue affected you? What are you trying to accomplish? What is the impact? Providing context helps us come up with a solution that is most useful in the real world. -->
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 commented 7 months ago

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 commented 7 months ago

@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 https://github.com/paketo-buildpacks/executable-jar/pull/265, so if you could please have a look when you have some time, it would be greatly appreciated.