Skip to main content

Is there a standard way to deploy a Java application?

Posted by robogeek on October 24, 2008 at 8:50 AM PDT

I've been thinking about this a bit recently and a comment on the javaposse google group tipped me into blogging mode. While discussing the recent shipping of JDK 6u10 Reinier Zwitserloot said On windows, and on linux, there is no java at all. It has to be installed separately. This is supremely annoying. There are odds the linux user has e.g. debian/ubuntu openjdk-6 installed, and on windows there's a chance that the manufacturer has shipped an auto-updating JDK out of the box, but there's no certainty there. On macs, at least, you know there's always a java, and a well integrated, if non-standard, way to deploy. ... outside the obvious statement of it would be nice for Java to be there in the operating system so it can be an assumed part of the infrastructure (thanks to OpenJDK we're moving in that direction for free OS's) this thought that there is a 'standard' way to deploy a Java app strikes me as being a little odd.

On Windows applications usually deploy as a .exe which hopefully doesn't contain a virus and which you run an installer which weaves registry entries and drops .DLL's into the DLL Hole and so on ..

On Linux you have several packaging paradigms, from .tar.gz to .rpm to .deb .. The Linux distros have varying policies for packaging Java app's and dropping them on the file system. And while there is a long standing issue about whether the Java VM implementations are LSB compliant at least with OpenJDK the distros can take care that the VM is installed correctly on the OS.

On Solaris is a similar problem but the package format is different.

On Mac there's several ways to install an app, usually a .dmg and you drag a .app to /Applications. It's real simple. For Java the installation of the Java VM is more than a little screwy but there is a JDK style directory tree buried somewhere under /System/Library/Frameworks

My point here is there doesn't seem to be any standard way to deploy a Java app (and have it properly integrated with the OS) .. and that it the root cause is outside the hands of the Java ecosystem to resolve. The root cause is that the OS vendors do not have a universal application delivery mechanism. The OS vendors all have their own ideas of how best to package and install and deploy applications.

For most cases a Java app can be deployed as a .jar (depending on the requirements of external dependencies) and running the app is done with "java -jar file.jar" or in some cases you can double click it's desktop icon. Maybe this is the 'standard way to deploy a Java app' ?? If so this way to deploy is not nicely integratable with the OS preferred way to deploy applications.

With 6u10 we have this idea of deploying a Java app via a packaged JNLP which you drag onto the desktop. That may improve the deployment of applications for some cases.

Related Topics >>

Comments

I hope that Sun would come out a modulized JRE so that it can be bundled with desktop applications. I also believe that the only way to make your application run right is to bundle it with the Java version that works right. The recently release of 6u10 has a bug with XOR painting even with D3D set to false, which causes performance degradation in the applications use that feature. The release 6u7 doesn't have this problem.

> Historically Sun has done a terrible job of listening to the developers. And all signs are such that this will continue. > That may be improving I don't think so.

@twe has hit the nail on the head with the versioning problem. The very first thing that should have been available from Sun was a standard way to detect existing JRE versions and select one. You could throw in automatic download if a required version doesn't exist. Instead, Eclipse does a disk search to find all the installs, fer God's sake. Historically Sun has done a terrible job of listening to the developers. That may be improving, but we've got a ways to go yet.

Typo: "double click it's desktop icon" --> "double click its desktop icon"

@nim_nim: okay, some of the other languages have package repositories. My experience with them has been less than good .. installing CPAN modules usually ends in utter frustration. Not all CPAN modules are in distro package repositories and that means you sometimes have to install them by hand which, as I said, usually results in an abysmal experience. I don't have much experience with python but had an strange journey once due to needing to install mercurial inside a shared hosting account (no root access) and learning of this strange hack that is 'virtual python' that let me install mercurial in my home directory.. http://davidherron.com/blog/topics/648-installing-mercurial-shared-webho... ... but the fact that it is sometimes nicely integrated with the install system on Linux is a tangent to my real point. The install mechanisms vary across the OS's .. even inside the confines of the Linux ecosystem there are variations in the install mechanism. (.deb, .rpm, .tar.gz) It means that a creator of a given package has to learn the widely varying installer paradigms for all OS's. @grandinj: What you're talking about is really a different problem. Ideally it shouldn't matter which JDK version your app runs on so long as it is newer than the one you tested on. But of course platform behavior varies from version to version. This happens for all software platforms, not just Java. When an OS vendor upgrades the OS isn't there a chance your apps will break? Of course we test the JDK very carefully but in practice there is a limit to what any quality team can do to assure quality in their application. This is true for every piece of software out there. The truism in the quality industry is "Testing is never finished, only exhausted". In any case ... the JIUL license allows you to do your own compile and take bits and do what you wish with it, so long as it is for use inside your organization ... the OpenJDK allows you to do your own compile and do what you wish with it so long as you abide by the GPL+Classpath. AND.. have you seen the "Silent Installation" feature? http://java.sun.com/javase/6/docs/technotes/guides/deployment/deployment...

grandinj: "That is the only way I can be sure that I have __exactly__ the right version, and the only way I can be sure that no-one attempts to upgrade the JRE from underneath me, thus breaking me." Actually it isn't the only way. A JNLP file can specify the exact version of the JRE that you want to use (or a range of versions) nim_num: "Except you don't need to deduce it there is an actual published standard you only need to bother reading. http://www.pathname.com/fhs/" Actually I have read it, but many others appear not to have read it or have chosen to ignore it.

I've been developing and deploying __Java__ desktop apps for 8 years, and desktop apps in general for 14. Java stands alone as being the most painful language to deploy BY FAR. I don't mean to be rude, but Sun just __doesn't__ seem to get it, and this blog post is pretty typical. I __don't__ need OS integration I __don't__ need auto-update of the JRE. I __don't__ need something cross-platform - I have totally different platform installation and maintenance tools, because the platforms all work so differently. On Windows, what I need is the ability to take my java app, take the relevant bits of the JRE, and install them as ONE LUMP into a private directory. That is the only way I can be sure that I have __exactly__ the right version, and the only way I can be sure that no-one attempts to upgrade the JRE from underneath me, thus breaking me. Really, what Sun needs to supply here is some command-line tools so that the various installer-generators like InstallShield can include the correct bits from a JRE, and install them easily into a private location.

> The everything in a private directory approach has the advantage that it used to work in most > environments and the paths relative to your private root were always the same. It never really worked under Linux. It doesn't really works on windows either (that's one reason there are so few successful desktop java apps whereas J2EE strived; J2EE app servers imposed some sanity on app authors). The only way a private directory can cope with upgrades is by wiping everything and unpacking a new directory, which happens to kill any local configuration (wars and jars that have built-in temp or config files are not better in this regard BTW) > There is no common sane file standard --- because Windows, Linux, Solaris and others all have > to be accommodated. Other languages like perl cope with it nicely. Probably because they didn't start from 'it can't be done' but 'how should it be done'. And it's not rocket science, you just need to analyze the file trees you need under each platform, and then define a set of variables that tell apps on install where each tree is to be found on a particular platform (so one platform can say all the file trees are under the same root, and another something else) > As for Linux, you would be hard put to deduce the standard from the actual structure of a typical > installation Except you don't need to deduce it there is an actual published standard you only need to bother reading. http://www.pathname.com/fhs/ And it's not even Linux specific > The Java JRE/JDK doesn't stand out as unusual in this company. It does.

"Every single language community had the same hurdles to resolve and most of them managed it very well, thank you very much." Some of them seemed to have "solved" it by splitting into Windows only and Linux only communities. That approach is not appropriate for Java. The everything in a private directory approach has the advantage that it used to work in most environments and the paths relative to your private root were always the same. There is no common sane file standard --- because Windows, Linux, Solaris and others all have to be accommodated. As for Linux, you would be hard put to deduce the standard from the actual structure of a typical installation; there would appear to be a whole host of (historical?) exceptions. The Java JRE/JDK doesn't stand out as unusual in this company.

> On Linux you have several packaging paradigms, from .tar.gz to .rpm to .deb .. The Linux distros > have varying policies for packaging Java app's and dropping them on the file system. And while > there is a long standing issue about whether the Java VM implementations are LSB compliant at > least with OpenJDK the distros can take care that the VM is installed correctly on the OS. [...] > My point here is there doesn't seem to be any standard way to deploy a Java app (and have it > properly integrated with the OS) .. and that it the root cause is outside the hands of the Java > ecosystem to resolve. The root cause is that the OS vendors do not have a universal application > delivery mechanism. The OS vendors all have their own ideas of how best to package and install > and deploy applications. That's utter bullshit (sorry but it had to be said). None of those problems are Java specific. Every single language community had the same hurdles to resolve and most of them managed it very well, thank you very much. A perl or python or C or C++ or php or whatever developper does not have to wonder if his app will be deployed on Debian or Fedora or OpenSuse using rpm of deb or whatever else. Because people know how a perl or python or C or C++ or php or whatever app is supposed to look once deployed, so rpm and dep packagers just implement the same thing. Linux package deployment techs are highly flexible and can cope with apps written in many different languages, yet they all seem to choke on Java. You have to be pretty disconnected from reality to think something that's clearly Java specific is "out of the Java ecosystem to resolve". Other language communities made the effort to specify file locations and integrate with the FHS. Sun ignored it for years and then pushed /usr/java which was an obvious attempt to ignore it some more. The current de-facto JVM deployment standard had to be specified JPackage-side (and mostly consisted of trying to deploy the JVM mess SUN and other vendors gave us in FHS-compatible locations). Any semi-competent engineer could have written something similar in a few days if there had been a will vendor-side. Other language communities made the effort to specify a dependency and resource discovery mechanism that Linux package systems could map to. Java has hardcoded classpath strings and nothing else (or more exactly a bunch of competing proposals, that won't be ready before Java 7, and try to help finding exotic ways to deploy in random file locations instead of specifying a common sane file layout standard - hello JSR 277). So here you are. Linux distros are given bunches of files with no obvious structure (since there is no file layout standard every java app writter just bundles everything he needs in a private directory), that are clearly not-satisfying, try to make the best of them, and all invent their own different workarounds. But the problem is not that different workarounds exist. The problem is that they had to be invented, because the "Java ecosystem" didn't want to think about file layout and software dependencies, and just dumped his mess on others. If a solution is to be found it can only be found "Java ecosystem" side.

The problem with generating packages directly from Maven/Ivy/etc. is that the maven repository doesn't meet the basic standards for open source software distributions - it doesn't distribute corresponding source code for most artifacts. So depending on what you do, you'd be either generating packages distributions couldn't accept (no one knows whether the Maven repo has been trojaned, for example), or violating the licenses of the software involved (if you distribute them along with GPLd software).

There is also the JDIC Packager project https://jdic.dev.java.net/documentation/packager/example.html

>But the desktop users, those ultimately paying us programmers, don't care, and don't want >platform independence. They want that it looks native, and behaves like a native application. >Only small variations of the "same old, same old" are accepted. E.g. to convince a user to click >on a .jar instead of an .exe for installation can already be a major issue. Yes, everybody agree with this but how it is connected to packaging and deployment? Nothing prevents you from adding small platform-dependent standard piece to installer/uninstaller that puts links in menus and system install/uninstall tools. Nothing prevents you from making your every single customer happy. But how it all is connected to system layer which is hidden from your every single happy user and that behaves java-way on every OS? I do not want to build my app for Fedora, Ubuntu, FreeBSD, Solaris, Windows at least by some separate maven plugin and distribute tens of variants of jars. I want standard installer and dependency resolver for every supported platform that handles the job right way. That makes every single office blondy happy and does not create stupid problems for me as developer. I want single maven-like repository for all platforms for dependency jars. I want right version checking and so on and so on. Will office blondy see all this? No, I guess.

>Bzzzzt. Game over no its just the beginning. Wrap your download link in the deployment tookit and the problem is solved.

@jwenting > Grand is part of the problem with his insistence that his applications MUST > use a very specific (and from what he writes apparently modified by him) Hmm, Sun came up with the extension mechanism. Which is nothing else than modifying a JRE installation. This is the only official way to add optional packages to a JRE. And Sun's idea is so dumb, that it forces you to either do a private JRE installation with the particular extensions (to ensure the right versions are used for your application and no interference with already installed applications), or you at least keep the optional packages private. The later still exposes you to JRE changes done to suit other applications. Also, Sun provides per-JRE configurations in jre/lib, and often there is no other way than to modify the JRE config, because no API exists to do it on application level. One example: If you need to get a native (non TrueType, OpenType, not Unicode encoded) font mapped into Java's Unicode system. And if you can't repack that font to TrueType (e.g., because for licensing reasons), and if you can't change the global JRE (e.g. again for licensing reasons, if you have licensed the font just for your particular application), then it's once again private JRE time. In fact, you have to hack two config files in lib/jre if you also want proper maping for PostScript printing. Oh, and Sun defined a number of optional parts one doesn't need to deploy when deploying a JRE. To bad if the already installed JRE misses some optional parts your application needs. > If a Java application is properly written it > will work on any more modern JVM, thank you very much. The bug parade is full of examples where properly written applications fail with a later version of a JRE (look for "regression" in the bug parade). And it happens the other way around, too. If you have to decide to deliver your application now, making it work with a hack, or waiting until a JRE bug you ran into is fixed, you go for the hack. The hack might interfere with a later JRE version. You can consider that improper, but that is state-of-the art in application development. @mbien The existence of inadequate tools doesn't fix the inherent architecture problem: > there are "standard" ways to install your java apps. > just check out > http://izpack.org/ > for the classic install expearance From the izPack Website: >> IzPack-generated installers only require a Java virtual machine to run. Bzzzzt. Game over, failure to fulfill a basic requirement: Should works under all normal circumstances on the target platform. Since the existence of a VM is not guaranteed on common platforms (e.g. Windows) you can't give this to Joe Enduser. @lurkin > Java must be OS-independent But the desktop users, those ultimately paying us programmers, don't care, and don't want platform independence. They want that it looks native, and behaves like a native application. Only small variations of the "same old, same old" are accepted. E.g. to convince a user to click on a .jar instead of an .exe for installation can already be a major issue. Sun has used platform independence as an excuse to do nothing or rather strange things (webstart with the java control panel) for application deployment. If Sun would't misguided a lot of effort into JavaFX we'd be better off.

Well, java apps are quite different from native apps in meaning of packaging, dependencies and so on. If we take a look at packages provided by Fedora or other Linux community, we'll see packages that are almost unusable with standard JDK. So what it means? I can not just reboot in Windows and use tha same Java app. I can not have shared network disk or repository for java applications. And so on... My opinion is: Java must have it's own standard ecosystem developed such way that java apps can be run everywhere. It means version and library dependence resolving, JRE or JDK autoupdates, filesuystem structure, repositories, .... Fedora approach kills main Java idea: "write once, run everywhere" and any tight OS packaging integration will kill the idea too. Java must be OS-independent to be compatible with all OSes. Remember ideas of IP protocol? It is a bit complicated because you must assign right IP address. But IP runs everywhere because it does not depend on hardware or software.

there are "standard" ways to install your java apps. just check out http://izpack.org/ for the classic install expearance or check out e.g the "opends online installer" (i am sure it has an other name ;-)) http://www.opends.org/ some see online installers are the future anyway, combine them with the deployment toolkit and you have always latest jre @ install time + your app of course. another option is to deploy your app directly into the webstart cache but this makes of course only sense for a subset of apps. If you already know that java is installed on the system a jnlp is enough anyway to get your app running (and even trigger jre updades).

Grand is part of the problem with his insistence that his applications MUST use a very specific (and from what he writes apparently modified by him) version and patch level of the JRE. If a Java application is properly written it will work on any more modern JVM, thank you very much.

To make a "standard" deployment system you'd have to dumb down the things Java can be used for substantially. Those "standard" deployment tools for say Windows aren't standardised at all. Things like Installshield might create installers with a standard look and feel, but each does its own thing. The tools to create those installers are often extremely complex, usually containing their own scripting languages to make them flexible enough to build pretty much any installer you'd like. It's quite possible to create such tools for Java, and I think they already exist (never used them, they're simply not needed to build an ear-file which is deployed in an application server, usually by just dropping it into place. How's that for standardisation?).

And of course to have such a "standard" tool that works not just for every possible application one can imagine but also works for every possible operating system and hardware architecture imaginable (and, this being Java, creates an installer that works on all those operating systems and hardware architectures) is just not going to happen. Except of course it effectively has already happened, it's called JNLP. And before that we had the executable jar.

grandinj: I completely agree 100% with you on this. I posted several questions on the Java Kernel forum regarding tools to support a private JRE, zero answers. I too develop desktop apps since at least 5 years. David, you are completely missing the point: if Java doesn't fit well in the __platform__ ecosystem it has no point in being there in the first place. My customers don't care if the software runs on another platform they are not running. They just want the smoothest, most seemless and most "native" integration with their platform possible without any problems whatsoever. On Windows this means .exe, start menu links, control panel integration and specific task manager process for example with minimal overhead start time for a small app (still waiting for update 10 here...) and a shiny own icon in the taskbar when they launch it, not a Java icon. And yes, this also means a private JRE to avoid any possible update versioning problems. Java for the desktop is dying very, very hard at the moment as I see it, because Sun is not stepping up to the plate and deliver the best integration possible for every platform it runs on. Please don't focus on JavaFX, it's too little too late and RIA's are overhyped. We don't need another Weather Gadget thingy, we need real solid applications we can do stuff with. Desktop apps will rule for a long time to come, because they are still the best way to deliver the best possible end user experience for most common tasks. And I will not let my customers start a bygone DOS era commandline batch file to run "java -jar bla.jar" for my apps.

>> nim_nim: "Except you don't need to deduce it there is an actual published standard you only need >> to bother reading. http://www.pathname.com/fhs/" > mthornton: Actually I have read it, but many others appear not to have read it or have chosen to ignore it. That everyone is not choosing to apply the FHS fully does not mean everyone has no read it and does not try to converge on something that looks like it. For example it took a few years before the Xorg people killed /usr/X11. That does not mean they were not aware of the target all along. Java and SUN people are about the only actors I know that pretend it does not exist and they don't have to consider it. > robogeek: okay, some of the other languages have package repositories. My experience > with them has been less than good .. installing CPAN modules usually ends in utter > frustration. Not all CPAN modules are in distro package repositories and that means you > sometimes have to install them by hand which, as I said, usually results in an abysmal > experience. No software ecosystem will ever fully be in distro repositories because packaging stuff means taking responsibility for it, tracking new versions, interfacing between users and upstream, performing a legal audit, etc. That being said there is no comparison possible on the purely technical part of packaging. On one hand you have a software ecosystem with well-defined and strictly applied deployment rules (so strict in fact you have scripts that create working distro packages automatically in 30s from CPAN sources), on the other hand you have a massively confused and messed-up ecosystem where packaging any software component is days of manual tweaking. Whatever you think of other languages (and no software is perfect) you need to realise that for the average third party, Java components are several orders of magnitude worse and harder to deploy. (The exception being of course J2EE apps where the app server imposes a set of deployment rule utterly missing otherwise.)

First, Java has a massive versioning problem. A JRE versioning problem: How to safely ensure multiple JRE versions can be installed in parallel *and* applications can *reliably* find their right JRE version - across multiple platforms, without manual user interaction required? Sun should have defined a standard, but they didn't. An extension / library problem: How to ensure multiple versions of an extension can be installed in parallel, and the right one be reliably found by an application? Sun defined a Standard (the extension mechanism). It was hopelessly inadequate when it came to versioning and allowing an application to select a version. It got renamed to "optional packages". That didn't fix the problem. Now, if you combine both version management issues, multiple versions of an extension to be installed for multiple different JREs, and an application to be able to find the exact right combination, you are halfway into a desaster. Finally, if you consider multiple extensions with multiple version combined with multiple JREs you have a full-blown desaster. And we haven't even talked about interaction with the OS application manager. We haven't been talking about a common, trustworthy repository for extensions. And we haven't even talked about the very bad idea of configurations which can only be done on JRE level (so applying to all applications using that JRE), instead of being done on a per-application level (see the contents of jre/lib directory). And we haven't talked about the way webstart applications are managed, which is so counter-intuitive to normal users, it hardly counts as management. Users don't want to manage application "caches". They don't even know what a cache is. They don't want to select a default JRE, they haven't, and can't have, any idea about the implications of selecting one over the other. The result: Private JRE installations, one per application, are the only reasonable way in this mess. And an own installation package for every supported platform, using tools typical for that platform - not JNLP and webstart. I have to agree, Sun doesn't get it.

It would be nice though if the JDK would provide stubs to start java applications as if they were native (on windows a .exe, a service, and dreaming further a screensaver). Stubs that could then starts the apps using JNLP descriptors...

An application installed via JNLP (WebStart) does appear in the standard Windows uninstall applet in the control panel.

I think for any such scheme to truly gain traction, it would have to be abstract enough to integrate with the package management system of each platform. ie, you get an uninstall option in the Windows control panel, you have things managed by RPM on RedHat/Fedora, etc. My personal best guess at the way to do this is by writing Maven plugins for each platform to generate a native installer for that platform. This might also involve enhancing the Maven manifest metadata to support more of the information desired. I would like to see a yum sever automatically generating and serving up RPM's for every package in the core Maven repo :)