Version 1.2
Java Web Start includes a servlet in the developer's pack that can be used to package a JNLP file and its associated resources in a Web Archive (.war) file. The purpose of the servlet is to provide a simple and convenient packaging format for JNLP applications, so they can be easily deployed in a Web Container, such as Tomcat or a J2EE-compliant Application Server.
The download servlet supports the following features:
The packaging support consists of one servlet: JnlpDownloadServlet
. The servlet is packaged into the jnlp-servlet.jar
file.
Below are two examples of how to use the servlet followed by a detailed description of the functionality of the servlet.
The first example shows how an application can be packaged into a WAR file without using the version-based download. The JnlpDownloadServlet
is used to insert the exact URL into the JNLP file at request time. The second example shows how to add support for version-based download as well.
WAR file without use of version-download protocol
Theexample1.war
contains:
/index.html
/app/launch.jnlp
/app/application.jar
/app/images/icon.gif
/WEB-INF/web.xml
/WEB-INF/lib/jnlp-servlet.jar
/WEB-INF/lib/<jar files for XML parser> (not needed if the servlet container is running J2SE 1.4+)
TS: 2002-04-23 19:21:05
<?xml version="1.0" encoding="UTF-8"?>
<jnlp codebase="/javase/technologies/desktop/javawebstart/1.2/docs/$$codebase">
<information>
<title>Example 1</title>
<vendor>Myself</vendor>
<description>just an example</description>
<icon href="/javase/technologies/desktop/javawebstart/1.2/docs/images/icon.gif"/>
</information>
<resources>
<j2se version="1.2+"/>
<jar href="/javase/technologies/desktop/javawebstart/1.2/docs/application.jar"/>
</resources>
<application-desc/>
</jnlp>
TS
tag contains the timestamp that the servlet will return for the JNLP file. The format of the timestamp is in ISO 8601 format. If the line is omitted, the timestamp of the file in the WAR file is used. The $$codebase
string is modified by the JnlpDownloadServlet
to be the actual URL for the request.
The web.xml
file instructs the Web container to invoke the JNLPDownloadServlet
for all requests to a JNLP file.
<web-app>
<servlet>
<servlet-name>JnlpDownloadServlet</servlet-name>
<servlet-class>com.sun.javaws.servlet.JnlpDownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JnlpDownloadServlet</servlet-name>
<url-pattern>*.jnlp</url-pattern>
</servlet-mapping>
</web-app>
JnlpDownloadServlet
requires an XML parser in order to work. If your servlet container is running J2SE 1.4+, there is already a XML parser integrated in it. Otherwise please add jar files that implement a Java XML parser to the WEB-INF/lib
directory. The reference implementation of the parser can be downloaded from here.
WAR file with use of version-download protocol
Theexample2.war
contains:
/index.html
/app/version.xml
/app/launch.jnlp
/app/application.jar
/app/lib__V2.1.jar
/app/images/icon.gif
/WEB-INF/web.xml
/WEB-INF/lib/jnlp-servlet.jar
/WEB-INF/lib/<jar files for XML parser> (not needed if the servlet container is running J2SE 1.4+)
/app
directory contains two JAR resources: application.jar
and lib.jar
. The lib.jar
uses a naming convention to associate the version-id 2.1, i.e., the version information is associated on a per-file basis. The version of the application.jar
file is described in the version.xml
file, i.e., on a per-directory basis. The version.xml
file looks like this:
<jnlp-versions>
<resource>
<pattern>
<name>application.jar</name>
<version-id>1.1</version-id>
</pattern>
<file>application.jar</file>
</resource>
</jnlp-versions>
TS: 2002-04-23 19:21:05
<?xml version="1.0" encoding="UTF-8"?>
<jnlp codebase="/javase/technologies/desktop/javawebstart/1.2/docs/$$codebase"
href="/javase/technologies/desktop/javawebstart/1.2/docs/$$name">
<information>
<title>Example 2</title>
<vendor>Myself</vendor>
<description>just an example</description>
<icon href="/javase/technologies/desktop/javawebstart/1.2/docs/images/icon.gif"/>
</information>
<resources>
<j2se version="1.2+"/>
<jar href="/javase/technologies/desktop/javawebstart/1.2/docs/application.jar" version="1.1"/>
<jar href="/javase/technologies/desktop/javawebstart/1.2/docs/lib.jar" version="2.1"/>
</resources>
<application-desc/>
</jnlp>
web.xml
file configures the JnlpDownloadServlet
to be invoked for all requests into the /app
directory.
<web-app>
<servlet>
<servlet-name>JnlpDownloadServlet</servlet-name>
<servlet-class>com.sun.javaws.servlet.JnlpDownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JnlpDownloadServlet</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
This section shows how to configure a WAR file to include the JnlpDownloadServlet
and also how the servlet can be configured.
Adding the Servlet to a WAR archive
First the necessary servlet code must be made available to the servlet container. This is done by populating theWEB-INF/lib
directory. The servlet is added to a WAR archive by including the jnlp-servlet.jar
file in the WEB-INF/lib/
directory. The servlet needs access to an XML parser. If your servlet container is running J2SE 1.4+, there is already a XML parser integrated in it. Otherwise JAR files implementing a Java XML parser must also be added. They can be downloaded from here.
Once the servlet code is available, the Web container must be told to invoke the servlet on the right set of JNLP and JAR files, or on a given subdirectory. This is all configured in the WEB-INF/web.xml
file inside the <web-app>
tag:
<web-app>
...
</web-app>
<servlet>
tag:
<servlet>
<servlet-name>JnlpDownloadServlet</servlet-name>
<servlet-class>com.sun.javaws.servlet.JnlpDownloadServlet</servlet-class>
</servlet>
web.xml
file:
<servlet-mapping>
<servlet-name>JnlpDownloadServlet</servlet-name>
<url-pattern>*.jnlp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JnlpDownloadServlet</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
See also example1 and example2 for examples on how to configure the servlet.
Logging
The servlet has built-in logging capabilities to monitor its behavior. Logging messages are generated in 4 different categories:version.xml
file. logLevel
and logPath
. The log level can be set to either NONE, FATAL, WARNING, INFORMATIONAL, or DEBUG. The log path specifies a file where the output will be written to. If no path is specified, logging is done to the standard log for servlets (using the ServletContext.log
method). For example:
<servlet>
<servlet-name>
JnlpDownloadServlet
</servlet-name>
<servlet-class>
com.sun.javaws.servlet.JnlpDownloadServlet
</servlet-class>
<init-param>
<param-name>
logLevel
</param-name>
<param-value>
DEBUG
</param-value>
</init-param>
<init-param>
<param-name>
logPath
</param-name>
<param-value>
/logs/jnlpdownloadservlet.log
</param-value>
</init-param>
</servlet>
Configuring file extensions and MIME types
The servlet treats JNLP and JAR files specially. JNLP files will be macro-expanded as described in a section below. A version-based request for a JAR file might result in the generation for an incremental update. The servlet uses extensions to determine if a file is a JNLP or JAR file. The default extension of JNLP files is.jnlp
and for JAR files is .jar
. These default extensions can be overwritten by the initialization parameters: jnlp-extension
and jar-extension
. For example:
<init-param>
<param-name>
jnlp-extension
</param-name>
<param-value>
.xjnlp
</param-value>
</init-param>
Extension Default MIME type
-------------------------------------------
.jnlp application/x-java-jnlp-file
.jar application/x-java-archive
.jardiff application/x-java-archive-diff
<mime-type>
element in the web.xml
file. For example:
<web-app>
...
<mime-mapping>
<extension>jnlp</extension>
<mime-type>text/ascii</mime-type>
</mime-mapping>
...
</web-app>
Application resources such as images, JAR files, and JNLP files are stored in the WAR file. The WAR file itself is a hierarchical directory structure, and the location of a resource inside the WAR file determines what URL will be used to look it up.
Assume that the WAR file (or servlet) has been configured so it handles all URL requests that starts with http://www.mytool.com/tool/
. If the following requests is made: http://www.mytool.com/tool/app/launch.jnlp
. Then the JnlpDownloadServlet
will look for the launch.jnlp
resource in the app/
directory in the WAR file.
No version information
A resource that has no associated version information, such as a JNLP file for an application, is simply just added to the WAR file. For example, given the above example, then the WAR file should included the following file:/app/launch.jnlp
Version information and more
The version-based and extension-based download protocols in the JNLP specification allows a resource to be looked up based on version-id, operating system, system architecture, and locale. TheJnlpDownloadServlet
provides two mechanisms for associating this information with a resource. It can be done on a per-file basis, using a naming convention, or by a per-directory basis, using a configuration file. Both methods can be used for the same directory.
The following information can be associated with a resource:
/app
launch.jnlp
1.1.0
SunOS Linux
x86
da da_DK
The path is specified by the location of the resource in the WAR archive. The rest of the information is either specified by the use of a naming convention or in the version.xml
file.
Resource Naming
The file naming convention is used if a double underscore (__) marker is found in the filename. The filename is parsed according to the BNF notation shown below:file ::= name __ options . ext
options ::= option ( __ options ) *
option ::= V version-id |
O os |
A arch |
L locale
application__V1.2__Len_US__Len.jar
application.jar
has a version-id of 1.2, and the following associated locales: en_US
and en
.
The version.xml
file
version.xml
file can be placed to describe the additional properties, such as a version-id, for files in that particular directory. This is an alternative to the file naming convention.
For example, placing the file application-1_2-us.jar
in a directory, along with a version.xml
with the following content:
<jnlp-versions>
<resource>
<pattern>
<name>application.jar</name>
<version-id>1.2</version-id>
<locale>en_US</locale>
<locale>en</locale>
</pattern>
<file>application-1_2-us.jar</file>
</resource>
</jnlp-versions>
application__V1.2__Len_US__Len.jar
in the directory.
A resource can also be specified with a platform version-id in the version.xml
file. Such a resource is used to match a particular platform request for a JRE. A resource with a platform version-id is specified using the <platform>
element. For example:
<platform>
<pattern>
<name>J2RE</name>
<version-id>1.3</version-id>
<locale>en_US</locale>
<locale>en</locale>
</pattern>
<file>j2re-1_3.0-us.jnlp</file>
<product-version-id>1.3.0</product-version-id>
</platform>
The complete document type definition (DTD) for the version.xml
is shown in the following:
<!ELEMENT jnlp-versions <resource*, platform*)>
<!ELEMENT resource (pattern, file)>
<!ELEMENT platform (pattern, file, product-version-id)>
<!ELEMENT pattern (name, version-id, os*, arch*, locale*)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT version-id (#PCDATA)>
<!ELEMENT os (#PCDATA)>
<!ELEMENT arch (#PCDATA)>
<!ELEMENT locale (#PCDATA)>
<!ELEMENT file (#PCDATA)>
<!ELEMENT product-version-id (#PCDATA)>
The JNLP specification defines four different kinds of download requests that Java Web Start (or more generally, a JNLP Client) can make to a server when requesting a resource:
Last-Modified
field of the response is used to determine if an update is available on the server. The basic download request can be used for all resource types.<jar>
, <nativelib>
, and <icon>
, when the version
attribute is included.<j2se>
or <extension>
elements. In addition to the version information, it also contains information about operating system, system architecture, and locale.A request is initially processed by the JNLPDownloadServlet
, and it extracts the following information from the request:
version-id
parameter or platform-version-id
parameter)current-version-id
parameter)os
parameter)arch
parameter)locale
parameter)Consider example2, and assume that it is being hosted at http://www.mytool.com/tool2/
. If the following requests is made: http://www.mytool.com/tool2/app/lib.jar&version-id=2.1
. Then the path of the resource would be, app/
, the name would be lib.jar
, the version string would be 2.1
, and the lists for os, architecture, and locales would be empty.
A request to a directory, e.g., http://www.mytool.com/tool2/app/
, will get appended the default filename: launch.jnlp
. Thus, it would be the same as http://www.mytool.com/tool2/app/launch.jnlp
.
Handling a basic download request
A request for which no version-id is specified (neitherversion-id
parameter or platform-version-id
parameter is specified in the request) is handled as a basic download request.
The request is first checked to see if it contains a double underscore (__) or is a request to the version.xml
file. If so, the request is rejected and a HTTP 404 error code is returned.
The JnlpDownloadServlet
will then try to locate the resource with the given path and name in the WAR file, and if found return it. If the resource is not found, a HTTP 404 error code is returned for the request.
If a match is found and it is a JNLP file, then it is preprocessed as described below before returned.
Handling a version-based download request
The resource lookup for resources with a version-id is uniform across the version-based download protocol, the extension download protocol, and the platform-version download request.First, the JnlpDownloadServlet
will build a database of all the resources that are located in the WAR file directory that the URL request is accessing (based on the path in the request). The database is built by scanning the version.xml
file (if present), and the list of files in the directory that is using the naming convention described above. The servlet caches the information internally. It only does a re-scan if the timestamp of the version.xml
file is more recent than at the last scan. Thus, if you add a file using the naming convention, make sure to touch the version.xml
file to force the servlet to do a re-scan.
Secondly, the servlet will scan through the entries in the database to find a match for the given request (the match rules are described below). For a non-platform request, first the resource
entries in the version.xml
file are scanned in the order they are specified, and then secondly the entries that are specified using the naming convention. For a platform-version request, the platform
entries in the version.xml
file is scanned in the order they are specified. If several entries matches the request, then the entry with the highest version-id is returned. If multiple matches is found with the same highest version-id, then the first one specified is returned.
The matching rules are as follows:
x-java-jnlp-version-id
returned in the response is the version-id for the matching resource, except for a platform request where it is taken from the <product-version-id>
field in the version.xml
file.
If a match is found and it is a JNLP file, then it is preprocessed as described below before returned.
Automatic JARDiff generation
The servlet will automatically generate and return incremental updates to JAR files, if possible. If thecurrent-version-id
parameter is included in the request and the servlet can find both a match on the current-version-id
and the requested version (given the above matching rules) and the request is for a JAR file (e.g., the target resource has the .jar
extension), then a JARDiff file will be generated by the servlet. The JARDiff file is returned as long as its size is less than that of the requested version.
The JARDiff file is generated and stored in a temporary directory that is specific to the given Web container. The servlet locates the temporary working directory using the javax.servlet.context.tempdir
context attribute.
The JnlpDownloadServlet
will automatically macro-expand certain template values in a JNLP file and replace them with URLs that are specific to the current request. This will enable JNLP files to be written and deployed without containing hard-coded URLs.
Macro expansions
The servlet will automatically substitute certain fixed keys in the JNLP file (prefixed with$$
) with URLs that are based on the current request. The keys are designed so location-independent WAR files can be created and deployed into a Web container.
The table below shows the 3 keys that the servlet will look for and substitute:
Pattern Value
----------------------------------------------------------------
$$codebase Complete URL for request, except name of JNLP file
$$name Name of the JNLP file
$$context Base URL for the Web Archive.
http://www.mytool.com/tool
. Thus, a request to http://www.mytool.com/tool/app/launch.jnlp
will return the JNLP file. The values of the macro-expanded keys would be:
$$codebase = http://www.mytool.com/tool/app/
$$name = launch.jnlp
$$context = http://www.mytool.com/tool/
The servlet does not validate the format of the JNLP file nor that the XML is well-formed. The value substitution is purely textual.
Explicit Timestamps
An explicit timestamp can be included in a JNLP file to ensure that a consistent timestamp will be returned from the Web Server. This is especially useful if a JNLP file is replicated onto multiple Web servers that are serving the same URL in a round-robin or load-balancing fashion. Note that a similar method is not provided for JAR files. The version-based download protocol should be used instead.An explicit timestamp is included in the JNLP if the first-line starts with TS:
. If so, it is parsed accordingly to the ISO 8601 formatting of timestamps ( see below). The first line is also removed from the contents.
See example1 and example2 above for sample JNLP files using the TS:
element.
YYYY-MM-DD hh:mm:ss
YYYYMMDDhhmm
23:59:59Z or 235959Z
+hh:mm, +hhmm, or +hh
-hh:mm, -hhmm, or -hh
12:00Z = 13:00+01:00 = 0700-0500