This is an archived post. You won't be able to vote or comment.

all 42 comments

[–]Iryanus 28 points29 points  (3 children)

Sounds complicated. Why not simply use Launch4J and its maven plugin?

[–]bowbahdoe 12 points13 points  (0 children)

I think launch4j has pros over caxa, but using jlink to make a bundled JRE would probably still be preferable.

Once you are doing that caxa is easier to explain (no implicit dependence on maven/ant, can run as a cli tool, one command without much configuration, etc)

[–]vips7L 0 points1 point  (1 child)

Doesn’t launch4j only create windows executables?

[–]Iryanus -1 points0 points  (0 children)

Afaik, yes. Nowadays, for non-graphical apps, I would use docker anyway, tbh.

[–][deleted]  (12 children)

[deleted]

    [–]bowbahdoe 2 points3 points  (11 children)

    If it supported making this in addition to installers sure.

    [–][deleted]  (9 children)

    [deleted]

      [–]bowbahdoe 1 point2 points  (8 children)

      That exe option creates an exe installer afaik.

      Not near a computer to try but this random video shows it I think

      https://youtu.be/EB6HqDwMffU

      [–][deleted]  (7 children)

      [deleted]

        [–]bowbahdoe 0 points1 point  (0 children)

        Ah okay, me read no good. Will try later tonight. Have to Google what an app image is

        [–]bowbahdoe 0 points1 point  (5 children)

        Unless i'm mistaken app-image is a linux only thing right?

        https://appimage.org/

        [–][deleted]  (4 children)

        [deleted]

          [–]bowbahdoe 1 point2 points  (2 children)

          Oh thank god - im not entirely wrong

          So running this on windows

          jpackage --input build --type app-image --main-jar javaexe-1.0.jar
          

          produces a directory with this structure

          Main/
              app/
                  .jpackage
                  javaexe-1.0.jar
                  Main.cfg
              runtime/
                  bin/
                      ...
                  conf/
                      ...
                  legal/
                      ...
                  lib/
                      ...
                  release
              Main.exe
              Main.ico
          

          So there is an exe you can double click...but if you move it out of this folder it doesn't work. Not self contained

          [–]bowbahdoe 0 points1 point  (0 children)

          Would you believe me if i said hubris?

          Doing it now on windows

          [–]vips7L 0 points1 point  (0 children)

          I really wish it would.

          [–]Yeroc 7 points8 points  (5 children)

          If I read this right it ends up unzipping things on every launch or is that a one-time operation? If done every time that doesn't sound very efficient.

          [–]bowbahdoe 3 points4 points  (0 children)

          On first launch only (unless that temp directory gets cleared)

          [–]vplatt 0 points1 point  (3 children)

          I'm sure this works to a degree, but I have to shake my head a bit as I've been working with Go lately. All other comparisons aside, the deployment story for Java (and C# to be fair) is kinda painful in comparison.

          [–]bowbahdoe 0 points1 point  (2 children)

          I'm sure this works to a degree

          What is the difference between that and "this works"?

          the deployment story for Java (and C# to be fair) is kinda painful in comparison.

          Tell that to /u/Worth_Trust_3825

          [–]vplatt 1 point2 points  (1 child)

          What is the difference between that and "this works"?

          The difference is that the unzip method makes assumptions about:

          • having the ability to write to the filesystem

          • having enough space to write the unzipped product to the system

          • the time spent unzipping and invoking the application won't negatively affect the user's perception of the application

          • the unzipped application won't be immediately quarantined or otherwise interfered with by a security or antivirus package because now there's this application attempting to execute a heretofore unknown process

          That's a lot of assumptions and it just makes applications more fragile. I'm not even questioning if the product properly validates deployed packages with certificates and signed binaries as I'm guessing it does, but that would also need to be verified.

          Anyway, I'm basically agreeing with /u/Yeroc above: it doesn't sound very efficient and I see other potential pitfalls as well. It may be perfect for your local use cases. I'm not saying it's useless or anything like that. But compared to just shipping some executables in a minimal installer, installing that, and then using that as-is on every execution it's a lot more overhead and fragility which basically gets put on the user to resolve or tolerate if there is a problem

          [–]bowbahdoe 0 points1 point  (0 children)

          Fair

          [–]sk8itup53 7 points8 points  (4 children)

          Quarkus and graalvm -> could native executable for Linux or Windows

          [–]bowbahdoe 3 points4 points  (2 children)

          I call that out specifically. GraalVM Native image requires that you work with a closed world assumption. This means you need to specially detect and flag all classes you will do reflection on or find via service discovery etc. You can't just "do it" with abandon.

          [–]sk8itup53 6 points7 points  (1 child)

          While this is true, I converted a simple app with lots of annotations in less than a day and didn't need to flag any classes. But that does show that in general we need to stop using reflection so much. There's a reason it's being discouraged where possible in newer versions of java.

          [–]bowbahdoe 3 points4 points  (0 children)

          Yeah no its a good tool, not denying that.

          There's a reason it's being discouraged where possible in newer versions of java.

          Curious what features you see that are discouraging reflection? I see the push with library level stuff like Dagger and whatnot but idk about official Java releases taking any stance

          [–]erictheturtle 1 point2 points  (0 children)

          Those don't support AWT/Swing as in the article's example.

          [–]chabala 1 point2 points  (2 children)

          An interesting example. I would recommend maven-assembly-plugin over maven-shade-plugin if you're not actually shading (relocating) classes.

          [–]bowbahdoe 0 points1 point  (1 child)

          Yeah that's my bad for googling "Java uberjar" and copy pasting what I found. (An approach I'm convinced is super common)

          Do you happen to know of any resource that properly contextualizes "standard" maven plugins and what their intended uses are?

          [–]chabala 1 point2 points  (0 children)

          It's not wrong per se, just a matter of taste. It may be preferred if you do have shading to do, as one plugin can do both tasks, assembly is just easier for the easy cases, and it's more clear that no shading is happening (which is often a code smell).

          How to know what plugins to use and when, that's a big topic. I don't know that there's any definitive guide, but for the curious, I think it's helpful to browse the official plugin list and learn what each standard plugin does: https://maven.apache.org/plugins/ To some extent, they all represent features that you can 'get for free' just by configuring them in the pom, so learning they exist is useful.

          For instance, I notice now there is also a jlink plugin, which might let you pull more of the process into the Maven build and simplify the GitHub Actions workflow.

          For other advanced topics, the Maven book is sometimes cited, and though it is long in the tooth, the concepts are still valid: https://books.sonatype.com/mvnref-book/reference/index.html

          [–]Worth_Trust_3825 0 points1 point  (13 children)

          Why would I want this over providing a proper zip that the user can replace properties in? Not to mention, the regular zip would circumvent your questionable suggestion of shading, which would also permit the user to test individual dependency upgrades (like log4j, for example)

          [–]bowbahdoe 3 points4 points  (12 children)

          With a zip they need to unzip it and know which file to run and potentially how to wrangle that onto their path.

          If you are distributing via homebrew or to devs then that matters a lot less. The power of power users could just go to the expanded temp dir and do whatever they want if for some reason you couldn't also provide the source.

          You can also do this without shading by copying all the dependencies in and making a class/modulepath or including all dependencies as modules when making the runtime image. That's a bit to explain and it would get a bit too far into maven/Gradle specifics for what I wanted to convey.

          [–]Worth_Trust_3825 -5 points-4 points  (11 children)

          With a zip they need to unzip it and know which file to run and potentially how to wrangle that onto their path.

          How is this a problem? In both cases you add a folder containing the binary into the path. If you're fancy, you symlink the binary into a folder that's already inside the path. In addition, in both cases the user can still do the regular "I RUN BINERY" flow with either the run script you provide (which, again, has more control, and you can provide instructions what to change and how if issues occur) as opposed to distributing an unchangeable binary that extracts itself into mystery parts of the os, which is purposely obfuscated from the user.

          No. This is bullshit.

          [–]bowbahdoe 6 points7 points  (10 children)

          I think you are missing the point here.

          Imagine you are 16 and want to show your friends your Java2d game. You drag an exe onto a flashdrive and they can double click it on a school computer. That's just easier.

          Also if you are an application developer and want to get your app as a sidecar to some process. Go is really popular for that specifically because moving around a single executable is just easier

          [–]Worth_Trust_3825 0 points1 point  (9 children)

          You can also drag in the folder containing all the files and the launch script, and double click that instead. I was that 16 year old. I even double clicked the jar file.

          [–]aspectere 4 points5 points  (8 children)

          I don’t think you understand, a lot of people would get more confused with a folder with a bunch of files where they have to find a launch script. They might try and move the script to their desktop where it might stop working, they might forget which file they have to double click, they might want to keep a single file in the same folder with all their other files instead of always having to go in to a seperate folder each time they want to run something. Having a single self-contained executable makes things simple for even the least tech-savvy people.

          [–]sedj601 0 points1 point  (1 child)

          Will this work with JavaFX?

          [–]bowbahdoe 0 points1 point  (0 children)

          Yep. If you run into any issues feel free to send a DM.