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.
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)
When invoked, the goals will:
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.
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.
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>
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>