Handling specific Java version for desktop application - java

What is the best way to handle situation, when a Java desktop application (executable JAR) requires specific (or newer) version/update of Java, to not get some NoClassDef exceptions?
Details: I have JavaFX 8 desktop application, build with Maven and com.zenjava.javafx-maven-plugin to executable JAR. I'm using new features of JDK 8u40. I would like to nicely handle situation, when someone is trying to run it with older Java version.
First, most low-end approach is to check
System.getProperty("java.version");
at the start of main function, parse it with a couple of "ifs" to extract is it major >= 8 and update >= 40, if not show some popup instead of app. But it seems to me like mediocre solution.
I wonder are there better ways? I'd love to know more about direct code solutions, external libs, additional jar launchers or Maven options for this purpose.
Edit: additional info - I would like to avoid platform-specific solutions

The solution which mostly works: just create a native bunde with included JRE. This is the default when calling mvn jfx:native, so you shouldn't worry about the class being there, because you bundled that specific version.
That is the main reason why some are using that option. Just imagine the situation you are require Java 8 but the user just uses Java 7 and so on, it makes the bundle bigger, indeed, but it preserves you from such problems.
Disclaimer: I'm the maintainer of the javafx-maven-plugin, there are example-projects ;) but no cookies yet.

Related

running java code form terminal getting error

I found some reference that says I can add #!/usr/bin/java --source 12 at the beginning of the file and run the file directly from the terminal.
I am able to run using this on my local machine, however, when I tried the same on Github action I'm getting the error error: invalid value for --source option: 12
I'm not really an expert in shell scripting or java, can someone help me understand what this --source means is it the java version, I tried setting up the same version (jdk18) on Github action but still did not work.
java (the runtime executable) can only run class files. Until, that is, java12, where a normal JDK distribution (and not the bizarro JREs that some packagers like Azul publish ^1) has a java.exe that can run java files straight up. It's simple sugar - the compiler is still involved, of course. It's just that java will execute it for you.
You don't need --source 12; just java MySourceFile.java is fine. Edit that comment at the top of your source file, it should just be #!/usr/bin/java. The thing you do need is that java on your command line PATH is a java v12 or higher, and it is not. There isn't anything your java source file can do about this, you're going to have to impose on your users to have at least java12 installed or this simply does not and can not be made to work. It looks like you're on some linux distro or other; apt or yum or snap or whatever package manager you have will tell you how to fix this: Install java17, and uninstall the rest or use java-alternatives or whatever mechanism your package manager has to set the default executable (the one /usr/bin/java links to). Read the documentation of the package supplying java17, possibly following some links to the generalized java infrastructure package, it should tell you.
Mostly this is a red herring, this just isn't how java files are distributed. It's virtually pointless because:
Java is not a language that tends to be used for quick shell script-esque things. Such things tend to be self-fulfilling prophecies: Because nobody does this, library authors aren't thinking about it when they develop their APIs and the users of their libraries won't file enhancement requests for this either. Because common libraries aren't convenient when used for quick off-the-cuff shell scripts, java isn't used for it, thus perpetuating the cycle.
Any serious java app would definitely involve packages, dependencies, and more - and such apps cannot be run like this.
Class files are as platform agnostic as source files are. There is no sane reason to distribute java-written shell-script-esque tooling as a source file instead of a jar, except for off-the-cuff editing off them, which gets you right back to point #1 and #4.
The java core APIs work on a model of lowest common denominator: If there is a major OS that cannot or doesn't work in a certain way, then java simply does not expose this at all. For example, on all posix systems (i.e. pretty much every major OS except windows), you have your usual TERM, KILL, HUP, etc signals. Java core libs don't let you interact with them (unless you dip into hidden sun.misc.* API which doesn't reliably work in the first place). This makes java extra unsuitable for quick command line scripting where you want a different model: If at least one OS can do it, the language should have a library for it, and that library should simply fast-crash if you attempt to use it on an OS that doesn't support it. One easy way around this is a third party library that adds support for OS-specific stuff, but your model of distribution (stick #!/usr/bin/java at the top and distribute a source file) cannot include dependencies.
Java as a runtime model is mostly focused on running things eventually very quickly, at the cost of starting off slowly. This is fantastic for web servers which need to run efficiently but will be running for quite some time. It's utterly unsuitable for shell scripting, though.
CONCLUSION: You don't want to stick #!/usr/bin/java at the top even if you could make it work.
[1] A JRE is a java distribution without compilers and other development tools like jstack. These cannot run java SomeSourceFile.java, obviously; they do not have a compiler. However, JREs died - there are no JREs anymore; JDK8 is the last one that shipped with an official JRE. The JRE serves as a distribution model: The end user installs a JRE, and you ship your jars to them. This model is obsolete (you are now responsible to get something that can run your class files on the deployment machine), and therefore JREs died. However, some packagers of OpenJDK builds, such as Azul, still publish them, confusing matters. Hence, 'bizarro'. Azul and co have relatively good reasons for doing it, but, you shouldn't be using these unless you really know what you are doing.

How do I upgrade to jlink (JDK 9+) from Java Web Start (JDK 8) for an auto-updating application?

Java 8 and prior versions have Java Web Start, which auto-updates the application when we change it. Oracle has recommended that users migrate to jlink, as that is the new Oracle technology. So far, this sounds good. This comes with a host of benefits:
Native code on Windows, Mac and Linux
Modularization of the code (although Proguard does this as well)
The use of new, supported technology.
The problem: I can't find the canonical Java solution to auto-update with jlink.
One would think that Java Web Start could continue to be used, especially if one casually reads this document. Notice the fact that Java Web Start continues to be prominently listed. But there's a fly in the ointment: Oracle is deprecating Java Web Start. It's slated for removal in JDK 11. So, what's the official path forward. Failing that, is there a standard way that people proceed?
For the purposes of this question the following are out of scope:
Paying huge amounts of money yearly to someone with an feature-packed enterprise solution. The application to be distributed is already packaged into a single jar that is smaller than 50MB.
Forcing users to run an InstallShield style app to reinstall the new version, and then manually uninstall the old version every time an update is pushed. That's sooo 1990's.
Porting the entire app to be a webapp, rewriting the UI and client side logic to fit in a browser and dealing with all the incompatibilities that entails. The authors of the application worked on GWT and know exactly what web browsers are capable of. Unfortunately, they also know the level of effort required.
Allowing users to continue to run old versions of the application. That, too, is sooo 1980's. Modern apps update quickly, and supporting every version of the application ever released is not tenable. That's what my father's COBOL application had to deal with, and he didn't enjoy it. I'm hoping technology has progressed.
Continuing to use Java Web Start. Until/unless Oracle changes its mind, Java Web Start is a doomed technology.
In May 2019 commented to watch the OpenWebStart project.
Now (October 2019) it is time to give OpenWebStart serious consideration. While not yet feature complete, a alpha beta release of OpenWebStart is now available for download under a "GPL with Classpath exception" license.
The OpenWebStart Technical Details page states:
OpenWebStart is based on Iced-Tea-Web and the JNLP-specification defined in JSR-56. It will implement the most commonly used features of Java Web Start and it will be able to handle any typical JWS-based application. We plan to support all future versions of Java, starting with Java 11. In addition to Java 11, the first release of OpenWebStart will also support Java 8.
The page goes on to state that OpenWebStart will support interactive installers with auto-update, and non-interactive installers. Some JNLP features will be supported, and it will include a replacement for the Java Control Panel. A more comprehensive list of planned features1 and their implementation status is provided in the feature table.
1 - If you have a requirement that is not on their feature list (e.g. jlink support), you could contact the OpenWebStart team, and offer a suitable incentive (e.g. money to pay developers) to implement the feature for you. They also offer commercial versions of the software for paying customers.
Disclaimer: I have no connection with the OpenWebStart project, the company (Karakun) or the project sponsors. This is not a recommendation.
I had a similar problem in a past project. We needed to migrate from Webstart to another technology.
The first approach was to install IcedTea. It is directly bundled with the AdoptOpenJDK Project.
But as far as I understood the problem, Java wasn't meant to be installed on the Client side like this anymore and we didn't want problems with all of our customers.
Our solution was then building an own specific Executable, which connects to the server, ask for enviroment settings from the server side, and then download and extracts the JLink Java. So we could use the old technologies and just wrapped it in an Executable.
Last thing done then was redirecting to the download location of the Executable when calling the jnlp-URL.
Do you use maven?
I've resolved my similar problem with maven (I need to update an EAR).
My main app (the ear package) has a pom.xml with listed the dependencies and repositories.
The dependencies have the <version> tag with a range (documentation) as in this example
<version>[1.0.0,)</version>
That means : get version 1.0.0 or newer of the dependency. (You can put also an upper bound to the version, [1.0.0, 2.0.0) so if you develope a new version, it is not used in old app)
In the repository section I added my personal repository.
Now, in the remote machine I need only to rebuild my ear package with maven : the compiler download the newer version of my jar and put it together.
You need a system to check if there are newer dependencies version and warn the user to update the app and also lock its work (you can't work if you don't update). Maybe you need a little app to make users do the rebuild process easily. It's 1990's but a lot of desktop-app works in this way
PRO
This schema can be used in a lot of different projects.
CONTRO
You need to build the app in the remote machine, so the client must have a JDK and access to your repository (like artifactory);
You must write code in different jars and add them like dependencies in the main archive.
You must change JAR version each time and publish on the repository (this could be a good practice)

Which JRE should I use for a stand alone application?

I've taken some java classes to learn programming, but I haven't actually built a fully functional java application. I want to build a fairly simple form-based application for my own uses on a single pc with a MySQL back end (using Eclipse as the IDE). So, I went to create the new project and I'm a little stumped on which JRE to choose. And a quick Google search just confused me more. There are 3 choices:
1. Use an execution environment JRE (with a list of options that seems to default to OSGi/Minimum-1.2
2. Use a project specific JRE (has a dropdown with a single option: 'jre1.8.0_31')
3. Use default JRE (currently 'jre1.8.0_31')
Does it matter which JRE I choose? I don't want to go through the process of building a whole application then discover I can't run it as a stand alone application because I chose the wrong thing here.
Sorry about my noob question, but I'm just trying to get up and running and then hopefully I will be good to go.
If you are willing to develop your own applications, consider using JDK instead. It will as well provide you support for running applications.
I am currently using build "1.8.0_144"; however, you can get the latest release at Oracle's web page

Create Android library jar to work with non-Android project

I am working on a library that ideally will have a strictly-Java component and added functionality for Android-specific projects, with the intent to be most useful for Android apps, but also work with other Java apps.
But my question is: how should this be designed? I do not plan on needing resources, so I want to compile it into a JAR, but would I need to make two JARs, one of the Java stuff and another for the Android stuff? Or would a Java-only application be able to use a single JAR so long as it does not use the Android components?
If you make a library that uses pure java and does not use any android apis. It will work on both standard java and android java. However if the library uses any android apis it can't be used in a standard java project.
As far as I know, the JAR would be good for both types of aplications. It seems to mee that both JARs (just Java and android) are totally identical and thus equally compatible. If you don't use any of the android components, including Resources there should not be a problem at all.
You should still check whether you depend on libraries which are available on android and any normal Java distribution or -if not- either tell the user to preinstall the depending libraries or ship them whitin your JAR package and build path. Be carefull not to use libraries which are not available on android because the user has no or really few options to install them on himself.
What I don't understand is why you think your library is more usefull to android developers. I can not think of any example where this could happen. If the problem is really specific for android, you should consider developing the library android-only. If the problem is more general the lib will be usefull to all developers that might come to this problem, not just android.

are there java based auto-updating tools other than WebStart & Eclipse P2?

I am working on a java based application and we are looking to ease our deployment of updates. Up until now, we've always simply sent out new install packs & had the sysadmin's on our customer sites roll out the upgrades - painful for a large number of users.
what I'd like to do is something similar to java webstart (or eclipse p2) - when the application starts, it checks for updates in a specified location and then downloads the updates prior to starting.
But here's my problem - I want more control over what's done outside of the scope of plugins & jar files. For example:
I'd like to be able to upate my JVM (we ship a modified version with additional security features).
I need to install DLL's - possibly local to the jar files, sometimes to windows
Occasiontally run MSI's to install windows components (e.g. printer drivers).
I need to modify config files & the registry.
I have found a few applications that support this (such as AppLifeUpdate at http://www.kineticjump.com/) but they tend to be .NET focused and it seems a bit perverse to introduce a .NET dependancy on a java application ;)
I know I could write my own here, but if there is already a 3rd party library out there that supports this kind of facility, then it would make my life a lot easier.
So, has anyone else had a similar problem & knows of some products I could look at?
Thanks, Brian.
I have done similar things but on Linux/Unix, so can't suggest any specific products for Windows. But I always found helpful to either package everything in OS format and distribute everything that way (rpms, debian pkg, Solaris pkg, ...) or have the platform deployed through OS mechanisms and have the application deployed through Java mechanism (Web start).
The reason is that sysadmins typically don't like things that magically update themselves without them knowing or in a way that does not follow standard practices. That is: you can't expect to make your life easier if you are not sure that you are not making their life more difficult...
Also: whatever work I do at the OS level, I do it with OS tools. If on Windows it means using .NET, I would very much consider using that...
Hope this helps!

Categories