Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Packr – Packages Java apps for distribution on Windows, Linux and Mac OS X (github.com/libgdx)
131 points by zdw on May 5, 2014 | hide | past | favorite | 40 comments


Java distribution is one of the biggest pains I've experienced in my development career. In all its forms, whether than be an applet, a J2SE application or J2EE enterprise deployment it always seems to be 10x harder than it should be. Somehow the Java ecosystem manages to make it much harder than it could be. If Sun had brought out a tool in the late 90's as simple as Packr seems to be it could have made a huge difference in the popularity of Java.


With Java 7 onwards there is a packager as part of the standard JDK as well.

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.


I doubt they would have been satisfied with the mechanism Packr uses. Packr distributes a static copy of a JVM with every build, which results in some less-than-desirable side effects:

- 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?


Most of the Java security issues only affected applets, not standalone apps. And the larger and the more sophisticated a standalone app is, the less desirable is running it on the system-default JRE.


You can easily distribute the JRE, but also autodetect if there is an existing JRE installation, and use that instead.

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.


In that case, why not just have your installer check if Java is installed, and install a shared JRE if it's not? This is the case with most .NET applications I've had to install on Windows.


So in essence you're saying that if I want the advantages of static linking, I shouldn't be using java? Isn't there a middle ground somewhere?


You have the same advantages and disadvantages with static-linking in general. If you want an easily distributable application (non-enterprise), then I think something like this is a great middle ground.

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.


The difference between this being that normally you're only linking specific libraries that you need, instead of an entire runtime and standard library. There's a lot of potential energy hiding in each of these packages.


I completely agree, and I think if someone is looking for startup ideas, than Java EE one click distribution to WebLogic, WebSphere, JBoss clusters will be really worth the while. There is a huge enterprise market that is not ready yet to fully go to the cloud, or has their own "local" clouds (banking, insurance).

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 wonder if you've tried http://www.smartfrog.org/ ?

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."


Are you serious? Easy deployment is the primary thing to LIKE about Java, much more so than the actual language.

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.


Hi, author of packr here. Totally agree with your points, it's one of the reasons i'm drawn to JVM land. However, for end-user apps like games people want to pretend their app is native. Distribution on Steam is also easier this way.

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.


Ah, that's a great improvement. Thanks for clarifying, and thanks for working on the project!


I'm glad you posted this; it AMAZES me that not only has this simple idea -- managing dependencies at the application level -- not been more widely adopted, but that there has been a massive investment in complex "chroot" jails like Docker to hack around it.

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:

http://www.robovm.org/


All very good points. It is amazing how easy people will curse Java without understanding why it is still used so widely.

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 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.


1 and 2 are fine points, point 3 to me is what I was getting at, just with a more portable system rather than something cloud-provider specific

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.


A couple of days spent trying to use WiX to build something that bootstraps .Net, VSTO and works on all windows platforms will make Java packaging look like bliss.

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.


Wix is horrid, if you don't need msi take a look at Inno Setup.


Everyone needs MSI eventually. It's the only thing that works properly with SCCM / MOM and you WILL end up with some corporate deployment that requests an MSI.

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.


I don't think so, Inno Setup supports silent installs, this has never been a deal breaker for me.


This sort of installer should only be required for apps that require some native code and/or tight integration with the Desktop Environment.

For most other purposes, a simple .jar or .jnlp file works fine.


Simple JARs and JNLP files have a very poor user experience. No one knows what to do with them. If you click a web-start link, your browser might start up your app, or download the jnlp file. If it just downloaded the file, you now have another few steps: 1) find the newest jnlp file, and 2) click it.

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.


>For Linux and Mac (command-line only)

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.


Can you do the trick where the actual binary is embedded in the .sh with batch files? I think that's what he's talking about.


Exactly... I was talking about cat'ing the JAR file to a shell script. It's a pretty simple ant or maven task. (Or just 'cat script.sh myjar.jar > executable')

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?


As far as I remember, yes you can, but it required an external tool to do it.


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.

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.


> For Linux and Mac (command-line only) I've gotten into the habit wrapping up a JAR in a shell script

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.


> In all its forms, ... or J2EE enterprise deployment it always seems to be 10x harder than it should be.

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.


I originally thought this was about Packer[1], just in case anyone else gets confused.

[1]: http://www.packer.io/



Don't forget about packer: https://github.com/keenerd/packer


For the ruby/node guys, pkgr do the same thing: http://pkgr.io/


Wow I didn't know about this project, really amazing. I see they have packaged Discourse which was a fairly complicated app.


A good idea, but I would find even more useful a program that wrapped the jar into an executable that:

- 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...


I wonder if there are some legal ramifications to this. As far as I understand Packr redistributes Sun/Oracle JRE - does license allow them to do that?

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)


I m under the impression that sun (and oracle) lets you freely redistribute the JRE runtime.


packr author here. I don't distribute any JRE. Doing so for the original Sun/Oracle JRE is indeed a problem. Doing so for OpenJDK is not.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: