Igor Nekrestyanov yesterday wrote a very important blog post on native packaging for JavaFX applications. Some of you have tried out and commented on our previous blog post about FX Experience Tools, which used native installers. The jfxtras project has likewise created such native installers. The native application bundle approach to deployment is a new mechanism that we’re rolling out for both JavaFX and hopefully in the near future also for Java SE applications (such as Swing and AWT).
Starting with the iPhone, the industry has been moving more and more toward app stores, with app stores being the only distribution mechanism for some platforms for native apps. Apple has even gone so far as to distribute entire new operating systems through the app store, which demonstrates their commitment to the concept. Microsoft is following suit with the Windows app store, as also have all the mobile operating system platforms.
Native app deployment is, in my opinion, the easiest and most natural way to deliver desktop applications. This is particularly true when the JRE and all libraries needed by the application are bundled with the application. Although this leads to larger download sizes, in a world where folks are downloading HD movies over their internet connection, it is becoming less and less of an issue. That doesn’t mean we have carte blanche to just make app downloads huge, indeed, we need to work on making it much smaller than these first prototypes are today. Java 8 modularity will be the first order optimization, such that you can omit modules (via proper tooling). We also would like to see some obfuscation and stripping capabilities added to the toolchain such that (much like you could do in JavaME for years) you can create a subset of the JRE / JavaFX platform that contains only those features and functions that your app actually requires.
The goal with native app bundles is to deliver desktop (and mobile) applications in the manner that is natural for the host OS. For example, you should have a .dmg and .app for Mac OS, and .msi and .exe for Windows, .rpm and .deb for Linux (and .zip / .tgz for platforms not supporting rpm or deb). By delivering Java applications using native formats, we make it really easy to deliver applications using normal workflows. For example, an enterprise IT department can take the .msi and push new versions of your app onto different desktops.
Although the user’s life becomes much simpler (they don’t have to have admin rights, they don’t have to have Java preinstalled, they don’t have to worry about what version of Java is installed, they don’t get blocked from running applets by their browser, etc, they just run the application installer and off they go, just like any other native application), the developer’s life becomes a little more complicated. Well, more or less. The truth is that deploying JNLP applications wasn’t trivial either, so maybe its a wash. But in any case, whereas before you would produce a jar (or set of jars), now you have to wait a little longer while the build process produces native executables. You have to offer up the right executable to users depending on what platform they are on. It isn’t very difficult, but it is some extra leg work. On the upside, the application executable / installer that you give to users is just gonna work. It will work the way users expect and are accustomed to. And by far (in my mind) the greatest advantage is that your application runs with exactly the same version of Java that you qualified your application against. You won’t be burned by updates to Java / JavaFX which cause regressions. You don’t have to worry about older versions of Java installed on the system than what you support. Everything is cobundled, making deployment a cinch.
We’re building this toolchain support into javafxpackager now, but will also be getting IDE support in the future as well as expanding the capability of app packaging to Swing / AWT / other Java apps as well.
Now, we have a great solution here for distributing and installing JavaFX applications. But what about upgrades? One of the advantages of WebStart is that it has auto-updating capabilities. Of course, in an app store scenario, it is unnecessary (prohibited even) for an application to auto-update itself outside the app store. And for IT department installed MSI files, you also won’t require auto-update since the correct way to distribute application updates is by producing a new MSI and giving it to the IT department. But for a broad swath of applications which neither are distributed via app stores nor through a corporate IT department, having some form of auto-update is going to be important.
In the Mac world, this is almost always done by the use of a 3rd party open source framework called Sparkle. Google has developed two different frameworks for this for Chrome and other Google apps (Omaha which is apparently windows only and Update Engine for the mac). Of these, I think Sparkle more closely matches what we want to do for auto-update, but it unfortunately isn’t cross platform. My current feeling on it is that we ought to write a 99% pure java update tool very similar to Sparkle, but that uses JavaFX UI for the dialogs and uses as little native code as possible (mostly just for doing the OS calls to swap the downloaded update with the current application and relaunching). I’ve been talking with our deployment team and with Dan Zwolenski (zonski) who has started a prototype on windows with auto-update capabilities. We’ll be discussing this shortly on the openjfx-dev mailing list.
I’m excited about this work, I think it represents a significant new direction for Java deployment which will make it trivial for end users to download and use Java and JavaFX applications, which in turn makes it much easier for developers and companies to invest in JavaFX clients for their desktop application development needs.
The direction of travel looks good to me and I am sure that a bunch of developers will be ready to grab a viable solution with both hands. Buidling distributable apps would go from a chore to another automatied phase of a build. I’m all for canning up the complexities for ordinary mortals.
I think that, on Windows at least, the free standing JRE does put off some people when you say that an app has been developed using Java. We’ve hjd various versioning troubles that absorb time and effort.
sounds a bit ambivalent to me. On the one hand you’re talking about native support, and on the other hand you’re saying something about auto-update.
Take for instance Linux. It has a very strong security/role model, and every distro comes with some sort of package management. You will definitely have a hard time getting your foot into that door with your auto-update approach.
Java is an alien on the Linux desktop because it never integrated into the Linux model. And it’s not because Linux distributions are shy of starting a program with some command line options, like java -jar blabla, and putting that into a script. I think you’re drawing the wrong conclusions.
To sum it up, for the centralized software deployment workflow that we see in all areas (you partly mentioned them yourself: marketplaces, IT departments, package managers in Linux), I think you should forget about the auto-update approach rather quickly.
my comment was on the article not on the comment. Sorry I hit the wrong button.
You’ll notice I outlined two mechanisms for distributing an application — one is to use an app store (or in Linux, you could use whatever mechanism is natural for your distro). However there is no question that auto-update is crucial for most application developers on Windows / Mac, so it cannot be ignored.
I’m not following this.
Why doesn’t WebStart already satisfy these requirements? Why reinvent the wheel?
Web Start still requires you to install a JRE. That’s often a pain if you aren’t in an environment where you can install system-wide software. And as the article mentions, Web Start isn’t an option in the world of app stores.
Web Start isn’t a bad choice if you can run it, but your users will prefer having exactly one file/bundle to deal with.
The other issue with WebStart is the same as with Applets, which is that, because it is a shared JRE (meaning any random app can run using it), for security reasons we must update the JRE to the latest as often as possible. However doing so also makes it hard for compatibility because you tested your app with JRE version X, but we’ve updated to JRE version X + 1 (or maybe the user manually down-rev’d to JRE Version X – 1). Now you are hosed.
…because a yaris wheel wont fit on a lexus 😉
Sparkle, as I investigated, is an RSS based package distribution. I already used its approach some years ago and thats the way I distribute my Java AWT based updates.
What I simply did, when my app starts, it checks the RSS and tells the user about new updates. If the user accepts to update, I quit the app and launch another one which downloads the new jars and substitutes the older ones only if all downloads are successful.
After that I take back the (main) app.
The choice of distribute native packages where everything is boxed is a great step because it will let the Java app to take advantage of native update mechanism in my opinion. But as OS X apps have been doing for many years, Sparkle offers a simple and clear mechanic for doing updates in an indipendent way from App Store or whatever.
The developer, anyway, has to take care in some way to notify and publish the updates, through an App Store portal or updating the RSS and packages on its own website.
The approach of one system or another depends in my opinion on how is boxed the app: if you can still access the jars or other files, a Sparkle approach is still possible; if the app looks like a black box maybe the native O.S. update system is required.
I can’t wait to see the package tool for AWT/Swing, hopefully as an Eclipse plugin. Then we will see which way is the best.
I’m glad to hear that. In Devexperts we’ve been doing native packaging of Java application for years. Take a look, for example, at thinkorswim trading platform (which now belongs to TD Ameritrade). It’s a [currently Swing-based] application for Active Traders. You can check it it out at https://mediaserver.thinkorswim.com/installer/install.html
However, since thinkorswim is a living application which updates with new feature multiple times per year, we don’t bundle the Java application itself, but bundle a launcher and a custom downloader that uses JNLP protocol to check for updates on each start. There are several key differences of thinkorswim downloader from WebStart, though. It understands the concept of “application version” (in addition to “file version” as in JNLP) and caches a fully-constructed jars for a particular application version in human-friendly way (unlike WebStart, whose jar cache is cryptic). It can keep multiple version in cache, so that rollbacks can be performed without any download requirements.
I already posted that comment on oracle post, but doesn’t seem to appear for now.
Our javafx app’s deployment is really the most crucial and touchy point for our start-up launching.
Bundles support is the hope a new breath for us.
Indeed, on my old home Windows XP I just can’t make my 100% correct jnlp work.
From JSE 6u31, no automatic update worked, I had to manually install jre7 (horrible for end user).
And then with jre7u4… nothing worked properly. Simply impossible to have it working under firefox or chrome.
And I’m not talking about a school level deployment trial, it’s a professionnal work by a competent java dev team.
My point :
But I was wondering how we could integrate a native bundled applet, as one of our offers is applet based. Something like a one time native installation that could be reused everytime the user opens the applet page.
Has something like that ever been discussed ?
Galera Parabéns por tudo que vocês veem fazendo pelo JavaFX….
I think the problem of deployment need more entanglement with Jigsaw for better deployment (and embedded support with his low memory footprint constraints).
JavaFX have a rich API (and increasing on rich text, I hope). But a real application will always use specific parts of the API. When the application is deployed as a native package, we know some parts of the code will not be used but Jigsaw modules will only help for modules used or not (webview, charts, etc.).
The application will have many API largely or fully unused (like drag and drop which will be used on only some widgets). The application will have one or a small list of skins but not use all skin possibilities. The unused parts of API are very important. Currently it seems many features are lazy-initialized reducing clearly memory footprint, but I think world-deployment need more features particularly in embedded space.
Building specific widgets for each application is unmanageable costly but inherently much more performing:
– a bound property unmodifiable replaced by its value cost one object less and many virtual dispatch less being easier for JIT compiling of code using it (good for memory and CPU).
– removed lazy-initialized remove fields of an object, allocated even if they are always null (good for memory).
Having specific API is clearly much faster. Attaining this objective without increasing cost of development need to automatically apply simplifications to the generic code for removing all parts unused of each feature. The JIT can not do this globally because it can only process a small window of code and does not understand the lifecycle of an object (JIT is inherently local, and can not transform long-living objects). A tool like ProGuard is very good in this job.
Preprocessing with Proguard all the code of an application and Oracle copyrighted libraries has two big defaults: it will create many headaches to Oracle’s lawyers 🙂 and it will be bad for updates (need another preprocessing of all the code then a full replacement). Given that, it will be useful if we can use Jigsaw deployment in own repository for calling preprocessing ProGuard-like tool with suggested optimisations to create in a cached-location in Jigsaw repository an optimized module corresponding to the single application deployed on this JVM. This will not reduce disk-footprint (even increase it), but executing this preprocessed code will reduce memory-footprint and improve performance, then it is very good for embedded deployment.
Given JavaFX has the usecase (single-application on JVM), the need (low-footprint devices), the heavy API (big ratio of public/private methods, too cold hotspots for good JIT needing global optimisation of code and not only local optimisation like JIT can do: many simple code with variable-targets virtual methods, many small objects with too long lifecycle for being escape-analyzable), I have posted this on your blog (choice of JavaFX-side and not on Jigsaw-side), even if Jigsaw is probably more concerned (but collections are probably the only API needing this sort of treatment in current JDK; and Swing applications are probably not a real driver usecase for Jigsaw).
Is the following scenario feasible with native-deployment ?.
1) I package up my javafx based app and an end-user downloads/installs it from an app-store.
2) Launch this app via java-webstart ?.
A follow up to my earlier post.
I supposed one could make a “wrapper” for the app and that could be launched via webstart. The question is will the security model (sandbox etc) prevent this and/or cripple this ?.
Does the JNLP api address this scenario ?.
Please where can I download the JavaFX runtime for version 1.3. And secondly, after writing a JavaFX application, I am not able to package it for deployment. I use NetBean 6.9 Beta and when I click Build Project, it say it has finished build. When i locate the jar file in the dist folder in order to run it, it gives a Java Exception………….(reported by the JVM). Please how can i solve this problem and how can I also package a program to become self-contained application? Please help me