What's the Best Way to Distribute Java Applications

What's the best way to distribute Java applications?

There are a variety of solutions, depending on your distribution requirements.

  1. Just use a jar. This assumes that the user has the the correct java version installed, otherwise the user will get "class-file format version" exceptions. This is fine for internal distribution inside a company.

  2. Use launch4j and an installer like NSIS. This gives you a lot more control, although the user can still do stupid stuff like un-installing the java runtime. This is probably the most popular approach, and what I currently use.

  3. Use Webstart. This also assumes that the user has the correct java version installed, but it's a lot easier to get going. My experience is that this is fine for tightly controlled intranet environments, but becomes a pain with larger deployments because it has some many weird failures. It may get better with the new plug-in technology in Java 1.7.

  4. Use a native-code compiler like Excelsior JET and distribute as a executable, or wrap it up in an installer. Expensive, and it generally ties you to a slightly older version of java, and there is some pain with dynamic class-loading, but its very effective for large-scale deployment where you need to minimise your support hassles.

How can I package a Java desktop application?

Users of your Java app must have the JRE installed in order to run it.

You can either tell them to install Java first, or distribute JRE with your app, as Processing does.

Note, however, that your packaged program will be heavy if you include JRE with it. And, if you want to do that, users will need to download the appropiate package for their platform.

Executable Java Wrappers

They take your Java app as input and wrap them in an executable (for a specified platform). You can customize them as you like;
and if the user doesn't have Java installed, the download page will open.

Some examples are Launch4J, JSmooth and Jar2EXE.

 

Installers

They are independent applications configured to copy your app files to the user's computer and (optionally) create a shortcut.

Some installers are written in Java, so they're multiplatform. In this case, the installer is a .jar.

Some others are platform-dependent, but you have the advantage that you don't need to wrap them.

Java installers: IzPack, Packlet, PackJacket, Antigen, …

 

Java Web Start

It's a Java feature that allows you users to easily run your apps. You give them a .jnpl file,

they open it, and Java downloads the latest version of your app and runs it. No packaging troubles!


See the complete list of resources here.

How to distribute Java Application

Distribute the Source Code and let
users compile it themselves, or
provide make files, etc..

This is probably ok for open source projects, but very unusual for anything commercial. I'd recommend providing it as an option for the techies, but distributing JARs also

Package it into a JAR

I'd call this the best practice

and have self extracting archives

How about making the jar executable instead?

I'm hoping for some explanations about
the most common options (and one's I
haven't thought of) and in particular,
do they require a user to have a JVM,
or can it be bundled with one -
personally I'm not too fond of an
installer which halts due to a lack of
JVM.

I don't think it's legal to bundle JREs. That said, it's rather obvious that a java-based solution won't work without Java. OpenOffice and many others fail to install without an installed JRE. I'd say that's understandable and OK.

IzPack seems to be a good solution to create Java-based installers.

My primary motivation for this
question (which I appreciate is
similar to others) is to find
solutions that don't require the user
to already have a JVM installed

As I wrote, I think it's not legal to bundle the JRE [UPDATE: it is legal, read this document for reference] (and also not a good option, as you'd have to bundle many different OS / architecture combinations). So the only other way would be native compilation (can't help you with that, sorry).

I want to distribute a Java application

I would recommend JSmooth as a really good open source program to create an exe from a jar. It also has the functionality to check for a JRE when executed which is important when distributing your application.

How are Java applications deployed in the real world ?

It depends on the application. There are many options depending on how you want your users to use your app. Usually it's packaged as a jar or a specialized jar (war, ear).

In theory, you could zip the raw directory structure with your .class files in it and provide a shell script/instructions that run the java command for the user. I don't recommend this because it's kind of unprofessional and requires you to maintain a shell script for each OS you want to be able to run the program on.

Jar files are used to package libraries but you can also have a manifest file in it that says, "When someone double clicks/executes this, run this class". That class can start up a GUI or be a headless task that responds to the parameters, etc.

You can have applets, like you said. These programs are run in the user's browser.

You can have a war file, which is a way to package a web application. You give this to a web server and it knows how to deploy it so that you can visit the web pages. An example web server/container is tomcat or jetty.

You can have an ear file which can contain other war files inside it. This is used for applications that need other parts of the javaee functionality (ejbs, jms queues, etc.). An example of an application server is jboss or glassfish.

There's also java web start apps. These are apps you can run by visiting a webpage, but they get downloaded to your computer and run on the user's computer (instead of on the server's backend, like in a war/ear).

There's also javafx. I don't know anything about that though. By skimming the FAQ, it appears to be Java's answer to Adobe's Flex. You configure UI components with an xml configuration. I'm not sure what format JavaFX apps use, but it does say, "Deploy on the desktop or in the browser".


As Sotirios Delimanolis mentioned in a comment below, you can build these files with build systems like Ant or Maven. You can also build them "by hand" with the tools that come with the java/javaee sdk. For example, you should have a jar command in your path if you installed the sdk. Here are some details of these build systems:

  • Maven
    1. High level (you tell it what to build, not how to build it)
    2. Much more than just a build system. It also has dependency management, etc.
    3. Opinionated (it uses convention over configuration, each config file generates 1 artifact, etc.)
  • Ant
    1. Low level (you tell it how to build things)
    2. Flexible
    3. Config files can do whatever you want, build as many artifacts as you want
    4. Easy to learn
  • SDK tools
    1. Always up to date. EG: Very rarely, maven/ant may not be able to set a configuration option
    2. Difficult to remember commands
    3. Very low level
    4. By itself, not repeatable (EG: unless you build a script, you will have to type the jar command yourself each time)

How to distribute Java application with library dependence chain?

You can use maven-assembly-plugin with it you can build a bundle zip for distribute you java project.

for example

in the pom.xml

<dependencies>

<!-- foo dependencies -->
<dependency>
<groupId>com.company.bar</groupId>
<artifactId>bar</artifactId>
<version>1.0.0-RELEASE</version>
</dependency>

</dependencies>

<build>

<finalName>foo</finalName>

<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>../lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Build-Time>${maven.build.timestamp}</Build-Time>
<Build-Host>${agent.name}</Build-Host>
<Build-User>${user.name}</Build-User>
<Build-Maven>Maven ${maven.version}</Build-Maven>
<Build-Java>${java.version}</Build-Java>
<Build-OS>${os.name}</Build-OS>
<Build-Label>${project.version}</Build-Label>
<Build-Path>${basedir}</Build-Path>
<Build-Number>${buildNumber}</Build-Number>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/asembly/asembly.xml</descriptor>
</descriptors>
<!-- <finalName>${project.artifactId}-${project.version}.jar</finalName> -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

you must give the specification of what it's in the bundle into the asembly.xml

<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly- plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">

<id>dist</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target</directory>
<outputDirectory>./bin/</outputDirectory>
<includes>
<include>foo.jar</include>
</includes>
</fileSet>
<fileSet>
<includes>
<include>readme.txt</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/lib/</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>

when you do mvn clean install then in the target forlder, must appear the bundle as foo-dist.zip

in the zip you will have in the /lib folder bar.jar and every other jar declared as dependency and in the forlder /bin foo.jar.



Related Topics



Leave a reply



Submit