Customizing generated Java Web Start JNLP for app clients in GlassFish Server 3.1

For some time, GlassFish has allowed you to deploy application clients to the server - either by themselves or as part of an EAR - and then launch them using Java Web Start. Every Java Web Start application must be described by a Java Network Launch Protocol (JNLP) document, and GlassFish generates this JNLP document automatically for any application client you deploy.


In past releases, you could customize very few parts of the generated JNLP: the vendor name and the download and icon images, for example.  But the rest of the JNLP was off-limits.


GlassFish Server 3.1 changes that radically.  Now you can customize the generated JNLP almost completely by following a few simple steps:



  1. Write a JNLP fragment which contains the customizations you want to use and package it into your application.

  2. Add a reference to that fragment in your glassfish-application-client.xml (formerly sun-application-client.xml) descriptor.

  3. Deploy the application.


There are some parts of the JNLP which GlassFish still has to control, but most of the document is open to your customization.  GlassFish will combine its generated content with your fragment to come up with the JNLP it will use to launch the app client.


You can put your JNLP fragment almost anywhere you want in your application.  Then adjust your glassfish-application-client.xml descriptor to include the new <jnlp-doc> element like this


   <java-web-start-access>
<jnlp-doc>custom/myInfo.jnlp</jnlp-doc>

if your fragment is in the app client module itself, or like this


    <java-web-start-access>
<jnlp-doc>other/myLib.jar!custom/myInfo.jnlp</jnlp-doc>

if your fragment is in another JAR (other/myLib.jar in this example) that's in the same EAR as the app client module.



GlassFish will combine each part of your fragment with its own generated JNLP in one of three ways, depending on the specific part of the JNLP document:



  1. replace the generated content with your content (called "defaulted" content because GlassFish provides defaults which you can override)

  2. merge the generated content with your content (called "merged" content because GlassFish merges your content with its own)

  3. use only the generated content (called "owned" content because GlassFish owns those parts and ignores anything you provide)


It's fairly involved to describe unambiguously what the rules are for which parts of your content are used and how (mostly because of the bits that GlassFish still needs to control). The complete discussion is part of the "one-pager" describing this feature which I won't repeat here.  But there are a few parts of the document you might especially want to customize.


JNLP documents contain <information> sections which define the vendor name and images which Java Web Start will display while it downloads the application or creates a desktop icon for it.  There can be multiple <information> elements so you can use different data for different operating systems, computer architectures, platforms, and locales.  GlassFish generates default settings for the <information> data with none of these special settings assigned.  So, here are two key types of customizations:



  • Override, for <information> elements with no attribute settings for os, arch, platform, and locale, the GlassFish defaults for child elements. (These children can be <title>, <vendor>, <description>, <icon>, etc.)

  • Add <information> elements with os, arch, platform, or locale settings and children of such <information> elements.

Another important part of the JNLP document you can customize is the <resources> area which (among other things) lists the JARs used by the application.  As with the <information> section, the JNLP document can contain multiple <resources> sections which apply to different operating systems, architectures, or locales.  An element with none of these special settings is the default and GlassFish generates this for you.  So you can:


  • Add child elements under the GlassFish-provided <resources> element. (The GlassFish-provided <resources> element does not specify os, arch, or locale.)

  • Add new <resources> elements that specify at least one of os, arch, or locale and children under such <resources> elements.


In particular, this flexibility allows you to add JARs to the
application (including platform-specific native libraries) and set
properties to control the behavior of your clients.  Note that you do not need to spell out all the JARs your client needs.  GlassFish will automatically include the ones listed in the app client JAR's manifest Class-Path setting and any JARs from the EAR's library directory, plus the JARs from GlassFish itself needed to run app clients.


As you write your JNLP fragment, keep in mind that you need to include surrounding XML elements to place your custom content correctly in the resulting document.  For example, suppose your client relies on a platform-specific native library when run on Windows and that's the only customization you need to supply.  You need to write your JNLP fragment like this


<jnlp>
<resources os="Windows">
<nativelib href="windows/myLib.jar"/>
</resources>
</jnlp

so that GlassFish knows where in the resulting JNLP to "plug in" your content.  If you just included the <nativelib> element by itself GlassFish would not know where to insert it into the final JNLP. 


As in previous releases of GlassFish, you won't find the resulting JNLP document anywhere on -disk.  The document is generated in-memory when you deploy the application or when the server restarts.  So if you want to change your JNLP customizations you just edit your fragment file, repackage your application, and redeploy it.  The customizations live with the application, not as a separate file or step you need to apply after you deploy the application.


Comments:

Hi Tim,

JWS in Glassfish is a really great feature. Is also possible to distribute non-ACC java applications via Glassfish JWS without application client libraries? ACC jars have very large size and for applications that do not need them are superflous. Thank you.

Posted by Stan Svec on March 04, 2011 at 09:17 PM CST #

Yes, but GlassFish cannot help with the generation of the JNLP document in that case.

You create and package all the required files - JNLPs, JARs, etc. - into a web app (or an EAR containing a web module) and deploy that to GlassFish.

In your application you will probably want to include the sample JNLP servlet (in the sample/jnlp/servlet directory in a JDK installation) which replaces placeholders in your JNLP document with the actual host and port used to serve the JNLP. That way you don't have to hard-code the host and port into your JNLP, which obviously would vary from one installation to the next or even among different instances in a GlassFish cluster.

Posted by Timothy Quinn on March 05, 2011 at 03:42 AM CST #

JNLP servlet works great. Thank you for advice.

Posted by Stan Svec on March 06, 2011 at 07:39 PM CST #

Tim, this is great stuff, but I have one question for which I can't seem to find the answer. Can glassfish digitally sign the automatically generated JNLP content? (Or similarly, JNLP generated by servlet/jsp)? We have a valid Thawte certificate installed in glassfish and it automatically signs all of the JARs, but our Web Start clients are still presented with a security warning because the JNLP is not signed. Thanks!

Posted by Dan on January 13, 2012 at 01:09 PM CST #

Dan, this is a result of a behavior change in Java Web Start. To make this work we would need to enhance GlassFish in a non-trivial way. The JNLP would need to be inside the main program JAR for the app client launch to meet the newer Java Web Start restrictions. But parts of the JNLP can change at the time of the HTTP request which requests the launch. So, potentially, each launch would need to regenerate the JNLP (which GlassFish does already), then if the JNLP has changed add it to the generated client JAR file so that the updated JAR would be downloaded.

All of this is certainly possible but would take some time and effort.

Probably someone needs to open an issue for this!

- Tim

Posted by Tim Quinn on January 17, 2012 at 05:52 AM CST #

Hi Tim,

With Glassfish 3.1.1, jnlp-doc structure is <jnlp-doc href="..." /> not <jnlp-doc>...</jnlp-doc>.

I have an application client and I want to add log4j to it. My JNLP fragement is this one :

<jnlp>
<information>
<vendor>Override !</vendor>
</information>

<resources>
<jar href="log4j-1.2.16.jar" />
</resources>
</jnlp>

and my glassfish-application-client.xml is this one :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-application-client PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Java EE Application Client 6.0//EN" "http://glassfish.org/dtds/glassfish-application-client_6_0-1.dtd">
<glassfish-application-client>
<java-web-start-access>
<vendor>before override !</vendor>
<jnlp-doc href="META-INF/override.jnlp" />
</java-web-start-access>
</glassfish-application-client>

My fragment is never read...:(
I tested several directories, strutures etc...no result

What may be the cause please ?

Posted by Olivier on July 17, 2012 at 05:10 AM CDT #

Olivier,

It is not true that "With Glassfish 3.1.1, jnlp-doc structure is <jnlp-doc href="..." /> not <jnlp-doc>...</jnlp-doc>."

Here is the documentation link:

http://docs.oracle.com/cd/E18930_01/html/821-2418/beakv.html#gkmbs

The DTD contains some comments about using href, but those comments are incorrect.

Please try <jnlp-doc>path-to-your-custom-jnlp</jnlp-doc> as documented and see if that works.

Normally, if you want to make a JAR such as the log4J JAR available to the client you either place the JAR into the lib/ directory in the EAR or add an entry in the client JAR's manifest Class-Path: entry referring to the JAR.

Either way users could launch your client using both the appclient command or

Java Web Start and the necessary log4J JAR would be present. Adding the <jar> element to the JNLP as you described will work only for Java Web Start launches.

- Tim

Posted by Tim Quinn on July 17, 2012 at 08:49 AM CDT #

Hi Tim,

unbelievable it works ! :)

In fact just followed the DTD and try <jnlp-doc href="..." /> not <jnlp-doc>...</jnlp-doc>.

Since first post, I used some JARs references in manifest file indeed and it works fine.

Actually, with <jnlp-doc>...</jnlp-doc> I have some DTD error :

Multiple annotations found at this line:
- The content of element type "jnlp-doc" must match "EMPTY".
- Attribute "href" is required and must be specified for element type "jnlp-doc".

It compiles and works but I have a red cross on glassfish-application-client.xml and therefore on my project.

Is there a way to suppress this "error" ? I can suppress DOCTYPE but it's ugly...

Thank you

Olivier

Posted by guest on July 20, 2012 at 03:59 AM CDT #

Hi, again, Olivier.

I'm glad it is working now.

There is only one way I know of that you can eliminate the error. The DTD for the <jnlp-doc> element marks the href attribute as required even though the code does not use it. This is definitely a bug we need to fix.

The DTD is in $installDir/lib/dtds/glassfish-application-client_6.0-1.dtd. Although I cannot officially recommend this you might try editing that DTD to remove the #REQUIRED setting for the href attribute on the jnlp-doc element.

- Tim

Posted by Tim Quinn on July 20, 2012 at 06:21 AM CDT #

Ok Tim thank you again.

In my case, this is just a personnal project and for now, I use manifest file instead of JNLP fragment so no worries. Just wanted to know why this didn't work with DTD ;)

Nice blog JNLP fragment isn't elsewhere well documented.

Cheers

Olivier

Posted by Olivier on July 20, 2012 at 07:02 AM CDT #

Hi Tim,

It's been nearly two years since I first asked, and I'm wondering if you're aware of any efforts to have Glassfish sign its auto generated JNLP content for Enterprise Application Clients?

With the latest Java Web Start update, we are now unable to run our application because the "loader.config" system property in the JNLP will not be passed to the application (for security reasons). Sounds like if the JNLP were signed, it would continue to work. There's a discussion about it here on stackoverflow: http://stackoverflow.com/questions/19634899/java-web-start-doesnt-work-after-java-version-7u45-npe

Any thoughts or suggestions would be much appreciated.

Dan

Posted by Dan on November 19, 2013 at 04:56 PM CST #

Tim,
Great atricle. I've used it to try and override the
required java version for a JWS application. My JNLP fragment is being used, the the <java java-vm-args="" version="1.6+" /> default content is not being replaced. My entry is just added.

<jnlp>
<resources>
<java java-vm-args="" version="1.6">
</resources>
</jnlp>

result fragment below:

<resources>
<java java-vm-args="" version="1.6"/>
<java java-vm-args="" version="1.6+"/>

Any thoughts?

Thanks in advance,
David

Posted by David on February 12, 2014 at 09:59 PM CST #

In response to Dan's comment from November '13…

As of late last year (December 2013) GlassFish contains the required logic to sign the generated JNLP documents, as described in some detail here: https://java.net/jira/browse/GLASSFISH-20711

The latest promoted development builds are here: http://dlc.sun.com.edgesuite.net/glassfish/4.0.1/promoted/ Note that those builds should not be considered release-quality.

Posted by Tim on February 13, 2014 at 03:08 PM CST #

In response to David's comment…

Internally, GlassFish has its ideas of what parts of the generated JNLP the developer can add to or replace and which parts are off-limits. The <java> element - in particular the version attribute - are not ones that GlassFish lets developers customize (as you described).

I have created a new GlassFish issue to track this: https://java.net/jira/browse/GLASSFISH-20985

Posted by Tim on February 13, 2014 at 03:20 PM CST #

Tim.

My research indicates that there are three types of content in the JNLP file:

Owned — GlassFish Server owns the content and ignores any custom content
Merged — Automatically generated content and custom content are merged
Defaulted — Custom content is used if present, otherwise default content is provided

Table 10-2 in the following oricle document indicates that <java version> is "Defaulted" JNLP content.

http://docs.oracle.com/cd/E26576_01/doc.312/e24930/java-clients.htm#gkmco

Therefore, shouldn't it be replaced? I'm thinking this is a bug.
David

Posted by DAvid on February 13, 2014 at 04:28 PM CST #

The new issue I mentioned earlier is indeed marked as a bug.

Posted by Tim on February 13, 2014 at 04:47 PM CST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

News and musings on the technology I work on at Oracle.

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today