Fork me on GitHub

JNLP goals overview

This document describes the functioning of the family of goals that generate JNLP files, and provides a configuration overview.

Note: The plugin produces its own artifact.

Input/Output

Here is the list of files/directories you might want to be familiar with before starting to use the plugin.

pom.xml                             (Configures the webstart plugin)
src/main/jnlp/template.vm           (Template for the jnlp file to be generated)
src/main/jnlp/resources/            (Location where all resources are taken, all contents are copied into the work directory)

target/jnlp/                        (Work directory)
target/jnlp/*libPath*               (Library directory, may be the same as work directory if not configured otherwise)
target/jnlp/launch.jnlp             (Generated jnlp file. Name is configurable, this is the default)
target/jnlp/version.xml             (Generated version.xml, used by the Download Servlet)
target/${artifactId}-${version}.zip (Zipped version of the work directory that will be installed in your local repository)

Functions

When invoked, the goals will:

  • Create the work directory
  • Copy the resources
  • Copy the JARs marked as dependencies into the working directory (if necessary)
  • Unsign signed dependencies if requested
  • Sign the JARs using an existing (or on-the-fly created) keystore file
  • If required, use pack200 algorithm to create packed and packed gzipped versions of the JARs
  • Generate a JNLP file
  • Generate a version.xml (when using the jnlp-download-servlet goal)
  • Create a zip of the resulting files (except the jnlp-download-servlet goal)

Optimizations

Unnecessary signing of JAR files can slow down the build. The plugin tries to reduce the number of operations to be performed, so it will only resign/repack the JAR files that have changed since the last run. In consequence, if you change your signing key or your POM, it will be necessary for you to clean your project before rebuilding. Otherwise strange results may happen.

JNLP file generation

The JNLP file is generated by taking a user-specified file in which some placeholder tokens are replaced by the plugin. The plugin comes with default inbuilt JNLP templates, different for the jnlp goals and the jnlp-download-servlet goal.

The templates are built using Velocity, so they look very similar to the final JNLP file. Examples of template files can be taken from under src/test/projects/.

The following placeholders are parsed and replaced:

$dependencies
$mainClass
$outputFile             from user input if specified, default otherwise (one can use $$name when using the JnlpDownloadServlet)
$project                maps to the Project Model (i.e. POM) (can be used to retrieve project.Name, project.Version, etc..)
## some aliases named after the JNLP file structure
$informationTitle       alias for $project.Name
$informationDescription alias for $project.Description
$informationVendor      alias for $project.Organization.Name
$informationHomepage    alias for $project.Organization.Url
## explicit timestamps for use with JnlpDownloadServlet (see JnlpDownloadServlet Guide at http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/downloadservletguide.html#processing)
$explicitTimestamp      explicit timestamp in local time zone, for example "TS: 2007-06-19 18:09:56+0300"
$explicitTimestampUTC   explicit timestamp in UTC time zone, for example "TS: 2007-06-19 15:09:56Z"
## Other properties
System properties (All properties taken from System.getProperties())(Note: properties containing dots ('.') might not be passed properly. This is due to the nature of the Velocity parser which treats dots as delimiters.)
Maven project properties (All properties taken from pom.properties section)  (Note: properties containing dots ('.') might not be passed properly. This is due to the nature of the Velocity parser which treats dots as delimiters.)
Extra config properties (All properties taken from config.properties section) (Note: properties containing dots ('.') might not be passed properly. This is due to the nature of the Velocity parser which treats dots as delimiters.)

See the Velocity User Guide for more information on how to retrieve fields from the Maven POM.

Note: The template generation doesn't know if a placeholder was not replaced. So if you put a $outputFile in your Velocity template, but forget to specify the <outputFile> element in your plugin configuration in the pom.xml, there won't (currently) be a failure.

jnlp goals configuration overview

Here's a full example of a POM used to generate a Web Start application bundle.

<!-- Test war project which signs a dependency and it's runtime dependencies. -->
<project>
  <modelVersion>4.0.0</modelVersion>
  <artifactId>jar-mng-1130-1</artifactId>
  <groupId>org.apache.maven.plugins</groupId>
  <version>1.0</version>
  <packaging>pom</packaging>  <!-- pom when your project doesn't contain sources, jar otherwise -->
  <name>Test Case for MNG-1130</name>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>webstart-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>jnlp</goal> <!-- use jnlp, jnlp-inline or jnlp-single as appropriate -->
            </goals>
          </execution>
        </executions>
        <configuration>
          <!--outputDirectory></outputDirectory--> <!-- not required?? -->

          <!--
          Set to true to exclude all transitive dependencies. Default is false.
          -->
          <excludeTransitive>false</excludeTransitive>

          <!-- The path where the libraries are stored within the jnlp structure. not required. by default the libraries are within the working directory -->
          <libPath>lib</libPath>

          <!-- [optional] transitive dependencies filter - if omitted, all transitive dependencies are included -->
          <dependencies>
            <!-- Note that only groupId and artifactId must be specified here. because of a limitation of the Include/ExcludesArtifactFilter -->
            <includes>
              <include>commons-logging:commons-logging</include>
              <include>commons-cli:commons-cli</include>
            </includes>
            <!-- excludes>
              <exclude></exclude>
            <excludes-->
          </dependencies>

          <!--resourcesDirectory>${project.basedir}/src/main/jnlp/resources</resourcesDirectory--> <!-- default value -->

          <!-- JNLP generation -->
          <jnlp>
            <!-- default values -->
            <!--inputTemplateResourcePath>${project.basedir}</inputTemplateResourcePath-->
            <!--inputTemplate>src/main/jnlp/template.vm</inputTemplate--> <!-- relative to inputTemplateResourcePath -->
            <outputFile>app.jnlp</outputFile> <!-- defaults to launch.jnlp -->

            <!-- used to automatically identify the jar containing the main class. -->
            <!-- this is perhaps going to change -->
            <mainClass>org.apache.commons.cli.BasicParser</mainClass>
          </jnlp>


          <!-- SIGNING -->
          <!-- defining this will automatically sign the jar and its dependencies, if necessary -->
          <sign>
            <keystore>fillme</keystore>
            <keypass>fillme</keypass>  <!-- we need to override passwords easily from the command line. ${keypass} -->
            <storepass>fillme</storepass> <!-- ${storepass} -->
            <!--storetype>fillme</storetype-->
            <alias>fillme</alias>

            <!--validity>fillme</validity-->

            <!-- only required for generating the keystore -->
            <!--dnameCn>fillme</dnameCn>
            <dnameOu>fillme</dnameOu>
            <dnameO>fillme</dnameO>
            <dnameL>fillme</dnameL>
            <dnameSt>fillme</dnameSt>
            <dnameC>fillme</dnameC-->

            <verify>true</verify> <!-- verify that the signing operation succeeded -->

            <!-- KEYSTORE MANAGEMENT -->
            <keystoreConfig>
              <delete>true</delete> <!-- delete the keystore -->
              <gen>true</gen>       <!-- optional shortcut to generate the store. -->
            </keystoreConfig>
          </sign>

          <!-- BUILDING PROCESS -->

          <pack200>true</pack200>
          <gzip>true</gzip> <!-- default force when pack200 false, true when pack200 selected ?? -->

          <!-- causes a version attribute to be output in each jar resource element, optional, default is false -->
          <outputJarVersions>true</outputJarVersions>

          <!--install>false</install--> <!-- not yet supported -->
          <verbose>true</verbose>

        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.0.4</version>
    </dependency>
    <dependency>
      <groupId>commons-cli</groupId>
      <artifactId>commons-cli</artifactId>
      <version>1.0</version>
    </dependency>
  </dependencies>
</project>

jnlp-download-servlet goal configuration overview

Here's a full example of a POM used to generate a Web Start application bundle compatible with the JnlpDownloadServlet.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.codehaus.mojo.webstart.it003</groupId>
    <artifactId>webstart-it003-parent</artifactId>
    <version>1.0</version>
  </parent>

  <artifactId>webapp</artifactId>
  <packaging>war</packaging>
  <version>1.0</version>
  <name>WebstartDemoWebApplication</name>
  <url>http://maven.apache.org</url>

  <description>
    Web-application to demonstrate the WebstartMavenPlugin.
  </description>


  <organization>
    <name>MyCompany</name>
    <url>http://www.mycompany.org</url>
  </organization>

  <dependencies>
    <dependency>
      <groupId>org.codehaus.mojo</groupId>
      <!--groupId>com.sun.java.jnlp</groupId-->
      <artifactId>webstart-jnlp-servlet</artifactId>
      <version>1.0-6.0-02_ea_b02-SNAPSHOT</version>
      <scope>runtime</scope>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>webstart-maven-plugin</artifactId>
        <version>testing</version>
        <executions>
          <execution>
            <phase>process-resources</phase>
            <goals>
              <goal>jnlp-download-servlet</goal>
            </goals>
          </execution>
        </executions>

        <configuration>
          <outputDirectoryName>webstart</outputDirectoryName>

          <!--
          Set to true to exclude all transitive dependencies. Default is false.
          -->
          <excludeTransitive>false</excludeTransitive>

          <jnlpFiles>
            <jnlpFile>
              <templateFilename>jnlpTemplate.vm</templateFilename>
              <outputFilename>launch1.jnlp</outputFilename> <!-- when there's only one jnlpFile, can be optioanl and defaults to launch.jnlp -->
              <jarResources>
                <jarResource>
                  <groupId>org.codehaus.mojo.webstart.it003</groupId>
                  <artifactId>hello-world</artifactId>
                  <version>1.0</version>
                  <mainClass>org.mycompany.webstart.HelloWorld</mainClass>
                </jarResource>
              </jarResources>
            </jnlpFile>
            <jnlpFile>
              <templateFilename>jnlpTemplate.vm</templateFilename>
              <outputFilename>launch2.jnlp</outputFilename>
              <jarResources>
                <jarResource>
                  <groupId>org.codehaus.mojo.webstart.it003</groupId>
                  <artifactId>hello-world</artifactId>
                  <version>1.0</version>
                  <mainClass>org.mycompany.webstart.HelloWorld</mainClass>
                </jarResource>
              </jarResources>
            </jnlpFile>
          </jnlpFiles>

          <sign>
            <keystore>${project.build.directory}/keyStore</keystore> <!-- path or URI (if empty, the default keystore ".keystore"-file in the user-homedir is used) -->
            <keypass>password</keypass>  <!-- we need to override passwords easily from the command line. ${keypass} -->
            <storepass>password</storepass> <!-- ${storepass} -->
            <alias>webstart</alias> <!-- alias of the key to  use -->

            <!-- the following key-settings are only used if the keystore and key has to be generated at build-time -->
            <!--storetype>jks</storetype>
            <validity>365</validity>
            <dnameCn>Firstname Lastname</dnameCn>
            <dnameOu>OrganisationalUnit</dnameOu>
            <dnameO>Organisation</dnameO>
            <dnameL>Location</dnameL>
            <dnameSt>State</dnameSt>
            <dnameC>CountryCode</dnameC-->

            <!-- KEYSTORE MANAGEMENT -->
            <keystoreConfig>
              <delete>true</delete> <!-- delete the keystore at build time -->
              <gen>true</gen>       <!-- generate keystore and key at build time -->
            </keystoreConfig>

            <verify>false</verify> <!-- verify the signature after signing -->
          </sign>
          <unsign>true</unsign> <!-- unsign already signed packages and sign them with own key -->

          <verifyjar>false</verifyjar>
        </configuration>
      </plugin>
    </plugins>

    <finalName>webapp</finalName>
  </build>
</project>