FULL PRODUCT VERSION :
ADDITIONAL OS VERSION INFORMATION :
All operating systems
A DESCRIPTION OF THE PROBLEM :
Prior to Java 6, webstart would check for updates by sending a HEAD request
to get the timestamp of the resources that make up the application. These resources include the jnlp file and the jar files. If the timestamp of the resource on the web server is newer than the timestamp of its counterpart on the client, webstart would send a GET request to fetch the resource from the web server.
The HEAD request was processed by the web server while the GET request was processed by the JnlpDownloadServlet.
This changed in Java 6. Instead of sending HEAD requests to get the timstamp, webstart now sends GET requests with an "if-modified-since" header variable. This header variable instructs the web server to return the resource only if its timestamp is newer than the variable's timestamp value. This means that only GET requests are now sent with all requests handled by the JnlpDownloadServlet.
The current version of the JnlpDownloadServlet ignores the "if-modified-since"
header variable and processes the GET request by simply returning the resource as it always has. This means that all resources will be downloaded each time the application is launched.
A few changes to the servlet are required to handle the possible inclusion of
the "if-modified-since" header variable. It should work with both Java 6 and earlier versions.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Try any webstart app that uses the JnlpDownloadServlet to return the jnlp file and jar files or packed jar files. Webstart 5 works as expected. Webstart 6 will download the resources each time.
EXPECTED VERSUS ACTUAL BEHAVIOR :
JnlpDownloadServlet should handle the "if-modified-since" header variable and return a standard 304 type response if unmodified.
jar resources are downloaded each time instead of only those that have been modified.
This bug can be reproduced always.
CUSTOMER SUBMITTED WORKAROUND :
A few changes will fix the problem.
Added a class variable to hold the value of "if-modified-since" if it is present in the request.
Added a method to return a HttpServletResponse.SC_NOT_MODIFIED (304) response.
In constructResponse(), compare request's timestamp with resource's. If same, return a 304 response.
For older versions of webstart, the timestamps will never be equal so execution will continue as per normal.
Posted Date : 2007-01-18 08:05:30.0
Even though the servlet does not understand if-modified-since header that we set, our code still checks the last-modified and content-length before doing actual download. If those matches, we won't download again. And the servlet does pass back correct last-modified and content-length.
I tried again and I still cannot reproduce the problem. I will contact the submitter for more information.
Posted Date : 2007-01-18 22:53:13.0
customer testcase shows 2 problems:
1. multiple GET requests to the same JNLP file.
2. subsequent launches will cause download window pop up with no progress bar.
For 1, need more investigation to see why we make multiple GET requests to the same jnlp file.
For 2, The reason why you see the download dialog is because we didn't see the 304 respond, and is entering the download code. But before we do actual download, we check the last-modified and content length against the cached entry. If it matches, it won't start the actual download. That's why there is no progress bar, and if you dig into the cache, you will see the cache entry is not modified.
I agree we should update the sample servlet to handle the if-modified-since header. With that, you should probably not see the download dialog pop up anymore.
Posted Date : 2007-01-19 00:22:02.0
Submitted On 10-FEB-2007
In case anyone is unable to wait for Sun's fix, you can download my patched version here (I'm the original submitter). It includes the new jar file and source code with a README. I've tested this quite thoroughly and it should work for all versions but you should double check anyway.
Submitted On 08-MAR-2007
This is really good, but there is a problem with the code, when the web site is wishing to provide pack200 jar's.
The problem occurs within your JnlpDownloadServlet constructResponse() method. Notice that if neither "if (jnlpres.isJnlpFile())" nor "if (dreq.getCurrentVersionId() != null && jnlpres.isJarFile())" are true, then the fallback is to construct a completely new JnlpResource and construct the file download response from that. Your if-modified-since test is not performed on that one, and should be.
The quick and dirty solution is to simple copy your if-modified-since test to just after the new JnlpResource has been constructed.
A better way would be to refactor the JnlpDownloadServlet code so that there is a single method that constructs a JnlpResource, then place your time-since test in the handleRequest() method.
Thanks for providing the code - it helped me a lot.
Submitted On 20-APR-2007
Any chance that Sun could also release a fixed jnlp-servlet jar to the maven2 repo?
Submitted On 20-APR-2007
I noticed that the files in the zip, for example JnlpDownloadServlet have an earlier date then the one in my jdk1.6.0 samples dir. Are you sure that that zip is build upon the latest jdk jnlpdownloadservlet version?
Submitted On 18-DEC-2007
It seems to be we have reproduced this situation.
Currently we are using the JBoss AS: tomcat which is part of jboss generates the jnlp-descriptor by means of SERVLET.
The problem occured then we installed the JRE 1.6.0_03 at customer computers.
As far as I understand each time the JWS client requests the jnlp-descriptor it retrieves the new file (with new TIMESTAMP). E.g. EACH TIME I lOUNCH the application the old cache-file removed new file created (of cource we do see the download dialog popup). But from my point of view we have the same jnlp-descriptor and therefore the same cache-file.
This contradict to your statement "That's why there is no progress bar, and if you dig into the cache, you will see the cache entry is not modified."
Or may be it is tomcat behaviour? Tomcat uses the mentioned
JnlpDownloadServlet, isn't it?
Submitted On 24-OCT-2008
I downloaded the JDK 6 JnlpDownloadServlet and installed it in OC4J 10.1.3.4.0. I have two filters, one for a SSO, and one to take the parameters on the URL and put them as arguments in the JNLP download (this is the primary purpose of the second filter). This all worked in Java 5, and in Java 6 update 1. It hasn't worked in any Java 6 that I know of beyond update 1. I have tried changing the order of the filters. When I take SSO out of the equation, there isn't a problem. SSO redirects from the JNLP page to another server which sets a cookie and returns to the JNLP page.
The end result of all of this is that the HTML from the SSO is treated as the the JNLP, and the application doesn't launch. When I take out SSO, the application launches fine.
If I don't specify any parameters, the application launches fine. I have tried a couple of different options on my filters. Here is the body of my filter:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException
log.debug("Called doFilter in OIDVJnlpDownloadFilter");
ServletOutputStream out = res.getOutputStream();
OIDVJnlpResponseWrapper jnlpResWrap = new OIDVJnlpResponseWrapper((HttpServletResponse) res);
HttpServletRequest httpReq = (HttpServletRequest) req;
HttpServletResponse httpRes = (HttpServletResponse) res;
//String file = httpReq.getRequestURI().substring(httpReq.getRequestURI().lastIndexOf('/'), httpReq.getRequestURI().length());
// filtering jnlp response
byte bytes = jnlpResWrap.getData();
if (bytes.length > 0)
log.debug("Calling fixupJNLP ");
String fixedupJnlp = fixupJnlp(httpRes, httpReq, bytes);
// This breaks IE.
//this is the up-to-date check...
catch (Exception e)
// if theres an exception....return original res?...
log.error("Error fixin up jnlp...", e);
log.debug("Done calling doFilter");
PLEASE NOTE: JDK6 is formerly known as Project Mustang