Replies: 6 comments 8 replies
-
Java modules are mainly useful for building a custom JDK. For most ordinary developers, you just need ordinary dependencies (jar files) and not a custom JDK. The main advantage of building a custom JDK is reducing the size - by declaring that you only need a subset of the JDK, you can get the file size down quite a bit. It's all very confusing - I wrote an article about it, in case you are interested. https://changenode.com/articles/fomo-java-modules You don't really need to build a custom JDK just to add a dependency on commons-cli. For that, you just need to add a Maven dependency, e.g. by adding the info from this page to your pom.xml file. https://mvnrepository.com/artifact/commons-cli/commons-cli/1.5.0 Anything you include in the resources folder will be included in the build by default. For more information on how that works, check out the Maven Resources plugin. If you are truly just trying to build a command-line app, you probably don't need/want to do a full jpackage installer and create a GUI app. For modern GUI apps, they usually listen to events from the underlying OS for things like file open, file print, etc, not command-line arguments. For example: Good luck and feel free to post any other questions/thoughts. |
Beta Was this translation helpful? Give feedback.
-
Thanks for your ideas. As I mentioned, the first thing I tried was to translate your template for my code and run it. It died with jlink saying it can't handle an automatic module. Your "FOMO" article says: "The only reason an Java developer should care about modules is if they want to use jlink to create slimmed down JVMs for their application. This is actually pretty cool for certain server applications - just ship a tiny prebuilt JVM with ultrafast boot times. It’s also very cool (of course) for distributing Java desktop apps." I currently deliver a ZIP file. It contains instructions that tell users to install Java, install JavaFX, unzip my file, define a few environment variables, and run a complicated command in a terminal window. If you're on Windows, I can tell you how to create an icon that runs the app and how to place it on the desktop. If you're on a Mac or Linux, I haven't a clue. This is just not viable. I need a normal installer. I'd certainly prefer a smaller download. All that prevents this is the commons-cli file. I can convert the commons-cli file manually and then run jlink. The jlink runtime image is 157 MBytes, so it's not that small. This includes the jfxwebkit, which I understand will be another problem. Reading your FOMO article, I also see: "By using a combination of the Maven copy dependencies, running jlink, and then running jpackage… it all just works. The installers are still nice and small, and everything works as expected by a Maven developer. Just… declare dependencies in Maven as normal, and then it all gets bundled and runs fine." This sounds great, but that's kind of how I started. It's been a while now, but my app didn't start out modular because when I began, I didn't know Java had added a module system. I was getting some sort of major error trying to get things to work; making my application modular solved that problem, but maybe introduced others. I'm not sure what would happen if I removed my module-info.java file, but I could give it a go. If you are truly just trying to build a command-line app, you probably don't need/want to do a full jpackage installer and create a GUI app. For modern GUI apps, they usually listen to events from the underlying OS for things like file open, file print, etc, not command-line arguments. My application is a GUI app. Like many, many GUI applications (e.g. Firefox), it has command-line options, but is still a GUI app. The command-line options are sometimes useful. On Windows, anyway, I could create various icons which bring up the application in different initial states. You don't really need to build a custom JDK just to add a dependency on commons-cli. For that, you just need to add a Maven dependency, e.g. by adding the info from this page to your pom.xml file. Hmm...I do have a dependency in my pom.xml file for commons-cli. That part works fine. I wind up with a non-modular commons-cli.jar in my target folder and jlink doesn't care for it. Anything you include in the resources folder will be included in the build by default. For more information on how that works, check out the Maven Resources plugin. Hmm...My pom.xml includes the resources plugin. I've tried a lot of plugins in the last few weeks, though... I think it either didn't do what I needed, or I couldn't figure out how to make it do what I needed and wound up using the assembly plugin. I find a lot of Maven documentation is written with the assumption that you already know what something is and how it works. When I see the word "resources", I think of my resources folder, which is for resources that wind up in my JAR file. I need to ship files that are user-accessible and outside the JAR file. Maybe the resources plugin supports that, maybe it doesn't. The documentation is completely muddy; as with most plugins, one has to try them to see what they do. And if how they work is unclear, it is really hard to determine if they can carry out some particular task. I remember playing around with this. I don't remember why I'm not using it. By the way, my app is at https://github.com/freixas/gamma. The pom.xml is probably a bit out of date. I couldn't see the point of pushing out the latest changes as I haven't really figure out anything. The version on GitHub should produce a ZIP file that can be installed as per my instructions. Once again, thanks for your time and thoughts. |
Beta Was this translation helpful? Give feedback.
-
Hey, thanks for taking a look. I'll give it a spin and see what happens. IIRC all of the stuff in resources gets embedded into your app executable. In the context of Java, I take "app executable" to mean an executable JAR file, which is what I would have thought. As I said, I can't have files stored in the JAR; they have to appear in the regular file system, so the resource plugin is out. The assembly plugin is fine, but the sequence needs to be jlink (for the runtime image), then assemble (combining the runtime produced by jlink with other files), then jpackage (which claims to package any any files that you have lying around in the runtime image). Anyway, I'll give it a try and get back to you. Thanks! |
Beta Was this translation helpful? Give feedback.
-
I gave it a go. It built an installer package, which is a lot further than I've managed. I guess that's the difference between knowing what you're doing and making educated, but mostly blind, guesses. I got an error because I didn't have the src/packaging folder. I copied yours and got past that error. The next error was because my ICO was in a different location. I fixed that and an MSI file appeared with Maven claiming "BUILD SUCCESS". My notes:
Overall, I'm very impressed. Thanks so much! In the Q&A, you say: GitHub won't allow cloning a template if the source has files over 10mb in size. The javafx.web components basically bundle a full native web browser under the covers. As of JavaFX 15 the javafx.web.jmod is roughly 25mb in size. If you need it, you can download it and install it in the JavaFX projects in your local project. I'm not sure I understand this. Are you saying that if the javafx.web.jmod is present, then the GitHub Action won't run because it clones the template? And that the solution is to 1) not put javafx.web.jmod into the artifact and 2) modify the GitHub Action so that it downloads and adds the javafx.web.jmod? Or are you saying you can only build locally and not using GitHub? I may be able to get rid of this dependency, which might be the best solution. |
Beta Was this translation helpful? Give feedback.
-
RE: the javafx.web.jmod, you can just add it to your project next to the other jmods for each platform (match version!) and commit to GitHub and it should be fine. For some reason GitHub doesn't want a GitHub Template to include a large file, but you can certainly use it in your project. Just download and commit. You might have to use Git LFS, which if you use GitHub Desktop it'll notice the large file and offer to set it up for you with a click. |
Beta Was this translation helpful? Give feedback.
-
It's been an exciting morning. The installer asked no questions because the windows-jpackage.txt file didn't tell it to. I looked up the jpackage options to add this behavior and it now works. I also added verbose mode and I see there are a few warnings I need to check out. I removed the launch feature, which removed the one error that showed up in the log file. I used the dependency module to copy all my extra files to target/dependency. The files now get installed, but under the "app" folder—not ideal, but I can live with it. You misunderstand these files; they are not user files—the user is not supposed to change them at all. I even figured out where the odd timestamp version came from and fixed it. I couldn't have reached this point today if not for your help. Thanks again! The next grim step will be trying to build a Mac version on GitHub (or even a Windows version). RE: the javafx.web.jmod, you can just add it to your project next to the other jmods for each platform (match version!) and commit to GitHub and it should be fine. For some reason GitHub doesn't want a GitHub Template to include a large file, but you can certainly use it in your project. Just download and commit. You might have to use Git LFS, which if you use GitHub Desktop it'll notice the large file and offer to set it up for you with a click. OK, I see. A GitHub Template and a GitHub Project are two different things. I had assumed (not being familiar with GitHub) that you were using the word "template" in a generic sense. |
Beta Was this translation helpful? Give feedback.
-
There's certainly a need for some easy way to create full installers for Java apps.
I'm new to Java modules, jdeps, jlink, jpackage, Git, GitHub, GitHub Actions and Maven. You seem to have done a good job toward providing a framework to go from Java code to an installable application, so thanks!
I've run into a few problems which I'm trying to work through. My ignorance of all the tools is making it difficult.
The first is the fact that I use Apache commons-cli, which is not a modular application. My first attempt to adapt your approach let to a jlink error. I can manually create a module-info file for commons-cli, compile it, and add it to the JAR file. How I make Maven do all this is a mystery at the moment.
Should you (ha, ha) have some spare time, perhaps you might consider adding commons-cli (which just parses command line options) to your sample program. This might make it more useful to others. If I've misunderstood and your tools already have a solution for automatic modules, please let me know!
Because I've not progressed much beyond this step, the other extension to your template might actually turn out to be easy. I ship some files with my application—these cannot be resources (i.e. in the JAR file), but must be accessible to the end user with normal tools (a web browser, a text editor, etc.). The assembly module may be sufficient for this task, although that's not clear.
The basic steps that need to happen are (as best I understand them):
Not having really made it even to the first bullet, it's hard for me to see the shape of the solution. In particular, I'm not sure if I can actually sequence things so they happen in the right order (I'm a Maven neophyte, remember?).
In case I've not been clear, what I'm suggesting (as an enhancement—since I'm new to GitHub, I'm not sure how I mark this as an enhancement request), here's a summary:
It would be OK with me if the module-info.java file for commons-cli was manually created. It just needs to be compiled and inserted into the commons-cli.jar file using Maven.
I don't really expect you to drop everything and work on this. I'll keep plugging along. If I figure out anything useful, I can let you know. It would make your template more useful.
Beta Was this translation helpful? Give feedback.
All reactions