Packr – Packages Java apps for distribution on Windows, Linux and Mac OS X
github.com
github.com
- The more apps you've obtained this way, the more copies of JVMs you have on your hard drive.
- These per-app JVMs aren't getting patched when the mainline JRE does.
In a lot of ways, this undermines the purpose of the way Java is structured. If you're going to be statically compiling your product, why not use a more suitable platform?
The biggest attack surface for Java is from the web, so that should limit the disadvantages of embedding a JVM. So long as you aren't using your embedded JVM to load external code, you should be okay.
Packaging a jvm is the right move for consumer apps. It's lower friction for people downloading and using it, and harddrive space these days are dirt cheap.
For most other purposes, a simple .jar or .jnlp file works fine.
Naked JAR files aren't much better. In order to best integrate with the OS, you will probably have some runtime-specific settings that you'd like to apply (such as memory, or GUI specific-settings). If you just distribute a JAR, that can't be easily set.
For Linux and Mac (command-line only) I've gotten into the habit wrapping up a JAR in a shell script to make one single file to distribute. The shell script can set all of the JVM flags that I need, and it can be run just like any executable. This doesn't solve the problem of adding icons, or the like for GUIs, but for command-line programs, it works great.
There is a Maven plugin to do this:
https://github.com/brianm/really-executable-jars-maven-plugi...
We use it for things like the Presto CLI.
Why is this specific to Linux/Mac and command line. Windows has .bat files which can accomplish the same goal, and every filemanager I have used will recognize a script file and execute it when you try opening it.
I don't know if this works on Windows or not... Never tried - it's been a long time since I've used Windows. And even then, if I needed to do command line work, I would install Cygwin. I don't know why it wouldn't work with batch files though. Do they get a reference to their own name as an argument?
The simplest solution is to have the JAR itself do this, relaunching the JVM if necessary.
Packr itself is distributed as a single JAR file, which I find a bit ironic.
The only solution I found till now that is remotely in the direction for Java EE is Cargo (http://cargo.codehaus.org/) but it seems to be more directed toward integration testing automation than deployment automation.
Puppet was my hope but it is not even trying to be Java / JEE friendly from what I've seen.
Oracle need to define a very opinionated, standard method of deploying, starting and stopping Java EE servers (JMX doesn't cut it yet) and IBM, and other vendors should comply, because eventually banks will ditch WebSphere / WebLogic toward things like Akka, Spary, DropWizard, TomEE etc. and IBM and Oracle will have nothing left to sell.
I haven't; but it's been around for a while and seems to be fairly well used judging by the mailing list archives.
"SmartFrog is a powerful and flexible Java-based software framework for configuring, deploying and managing distributed software systems."
To be honest if you respect the deployment conventions in java (i.e. think about them whilst building your product rather than retrospectively apply them) it's pretty easy.
As for WiX and MSI, it throws out bundles as well (.exe containing MSI bootstrapper) if you want to do anything complicated which means you're up shit creek anyway.
http://docs.oracle.com/javafx/2/deployment/self-contained-pa...
Don't let the JavaFX references fool you, it is also applicable for other types of desktop applications.
Sadly, the stripped implementations was dropped in Java 8, but might came back in later versions.
All in all, I agree with you. Sun never knew how to do desktop development properly, projects like JDIC and JAI were left to rotten and deployment with scripts was always a second class deployment.
They never understood what desktop developers and users what of their systems, letting the field open to .NET and frameworks like Qt/wxWidgets.
In the Java world, your application dependencies are managed at the (gasp!) application level. You run Maven, Gradle, or whatever... and get a self-contained web archive (i.e. WAR file), with all of the application dependencies bundled. It's just a plain ZIP file, with a standard directory layout.
With a light app server such as Tomcat or Jetty, you literally just drop that file into a particular directory, and it's deployed! You just delete the file (and any contents that the app server unzipped), and it's undeployed!
If it's a console or GUI application rather than a web app, then you just create a JAR file in similar fashion. Maven has its "shade" plugin, and all of the other build systems have similar counterparts... which will bundle up all of the application's dependencies into the JAR file as well. You then ship that monolithic JAR file anywhere, just as you would a ".exe" file. Assuming that you declared a main class when you built the JAR, you can execute it on any system by typing "java -jar file_name.jar"... or by simply double-clicking it in a desktop environment.
Whenever I've dabbled with Python, Ruby, or NodeJS... I've been STUNNED to learn that they follow the ancient Perl convention, of managing application dependencies at the global interpreter level. If I want to write two applications with conflicting sets of dependencies, then I have use a tool such as "virtualenv" (or its Ruby equivalent), to trick my environment into thinking that it's running in a completely different interpreter. NodeJS is somewhat more sane, in that "npm" supports local and global dependencies... but you still have to ensure that you haven't installed a dependency in the wrong place, and that your target machine will have what you need in the correct place.
The current state of distribution and deployment for "dynamic" languages is so insane, that people are actually excited about the idea of shipping an ENTIRE CHROOT JAIL as a deployment unit (i.e. Docker). People are using that in production environments, even though the Docker devs themselves tell you that it's not ready for that yet, because in half-baked form it's still better than the traditional options.
Java has many drawbacks, but distribution and deployment are NOT among them. Most of the people who upvoted this probably just reject Java as old and stuffy, and have not actually done significant work with it. If they had, then there might be at least one comment on this thread pointing out that Packr is a clone of Launch4j (http://launch4j.sourceforge.net)... which has been around for almost a decade now.
In fairness, a docker-like chroot jail helps you encapsulate the whole JVM and app server into an immutable unit, which is arguably more manageable than relying on Chef or Puppet or Ansible to keep its configuration stable and versions up to date.
In Java land, you can accomplish that by:
1) Embedding the application server in your own binary; eg, Tomcat and Jetty et al have simple APIs that you can use to run the app server, or
2) Simply packaging them up in a single directory next to each other, or
3) Treating the app server as a deployment fabric (ala Amazon Elastic Beanstalk) and versioning the app server and the wars separately, which has some mighty fine maintenance and deployment advantages.
The only thing you have to do is wire your server into the platform's init scripts, and everything else is self-contained.
Containers are exciting precisely because they don't care about how good or crappy your language interpreter or app server happens to be, whether you run your own data center or use a cloud, etc.
I was aware of launch4j, but it only targets Windows (and if you include icons, you have to do that on Windows cause it calls into the win32-API last time i checked). Packr allows you to bundle for any platform from any platform.
It's just insane.
As an alternative suggestion to launch4j -- on end-user desktop installations where one wants native packages -- I think AOT-compilation with tools like RoboVM are ultimately the future:
I might agree about desktop apps (the problem OP is trying to solve), but building a WAR or EAR and dropping it in a directory to deploy a webapp is about as easy as it gets.
All dependencies are usually in the WAR (which is just a zip file, really), and it can usually be deployed to any servlet container or app server (including cloud offerings like Elastic Beanstalk) and work exactly as it did on your local box.
- If the user has a (sufficiently new) JVM installed in their system, or if there is a JVM in the program's directory (see below), then it executes the jar with that JVM,
- Otherwise, shows a simple "OK/Cancel" dialog prompting the user to download the JVM. Downloads it (to the program's directory without install, as in packr) and runs the jar.
This would accomodate non-tech-savvy users without a JVM fine (and without making them install Java in their system), while saving space for those that already have Java.
I have been wanting this for years... I'd do it myself, if only I found the time...
AFAIK JRE is under GPL, so it should be OK, but I am guessing Oracle still retained some copyright? (I am genuinly curious - it's been a long time since I touched non-Android Java)