At my company we are using Java Web Start to distribute client software to the customers. They are using different Windows versions: XP, Vista and 7.

We've deployed a version through JWS with minimal problems in the past. Our latest release includes several file changes, some jars are gone, other's appeared, etc.

We found out that upgrade on Windows XP machines fails because JWS still tries to look up jar files which are'nt available anymore on the web server. I've checked my HTTP server's log and the JNLP file never gets accessed from XP machines during application startup. If i try the same on Vista or Windows 7 everything works fine, JWS fetches the JNLP descriptor and downloads the differences when an update is available. So on XP machines only the known jar files gets updated and JWS throws an error if it doesn't find something from the cached JNLP's fileset.

I've written a servlet which manually generates the JNLP file. I'm using the following header config in my servlet code.

This makes the JNLP file always outdated which should trigger recheck of the file every time the client gets started through JWS. I can even see this date in the cache viewer on XP:

I've found a never resolving problem about this on Oracle's bugreport site: Bug ID: 6189106 Just tested the same with Java7 on Windows XP but this problem still exists. But only on XP because of the white space characters in the deployment cache's path ("Documents and Settings" you know). Somebody says there that if i change the deployment cache's path to something which don't have space characters in, it will solve the problem. Well it's not an actual solution because users can hardly ever write to locations other than their profile.

Because this bug exists for such a long time i guess there should be some kind of workaround. I don't like to tell the customer every time to clear the Java cache and reinstall the application from web. We like to move to a more faster release cycle in the future which will make this even worser. I hope someone has a good idea for this. :|

2 Answers
2

The problem is in the path to the cachedir of the java webstart. If it contains spaces (that is exactly the case in XP) then the path is passed in a wrong format to the javaws and this will block the update check of the jnlp file.

Change this path in deployment.properties file like this:

deployment.user.cachedir=C\:\your\path - this path should not contain spaces.

I've accept this answer because it actually do the trick. However we can't really do this because organization administrators have to change the configuration on every workstation which is not a walkable way. To partly solve this problem we changed our project structure to pack everything needed into one JAR. This way it doesn't matter that XP caches the JNLP file, because file list will be always the same. We tell customers to redownload the project once again. Not an elegant solution but it works.
–
NagyIDec 24 '11 at 14:27

Put a version number in your JNLP file, passing it as an argument to your main method (e.g. <argument>1.0</argument>). Alternatively you could pass an explicit timestamp.

Check a) the java.version or javawebstart.version system property to see if your app is running on anything between 1.6.0_22 and 1.7.0_2 (inclusive); and b) check the deployment.user.cachedir system property to see if it has any spaces in it. If a) and b) are not both true, there's probably no point in continuing with the steps below, as Java Web Start should have checked the JNLP file for updates itself.

On startup, before showing any forms, download your JNLP file into memory (e.g. using new URL(jnlpUrlString).openStream() etc.). I pass the URL of the JNLP file into my app as an argument from the JNLP file itself, like for the version number.

Check the JNLP file to see if it contains the version number that was passed into your main method (e.g. a simple string search for "<argument>" + versionNumberPassedIntoMainMethod + "</argument>"). If it does, you're good, as you're running the latest version. If not, continue:

Save the JNLP file in the temp directory (e.g. using File.createTempFile(...)).

Get the system to open the JNLP file from the temp directory, e.g. with java.awt.Desktop.getDesktop().open(jnlpFile) if you're targeting Java 1.6+.

System.exit(0) to close the out-of-date version of the app and let the updated one take over.

I also store and check the last-download date in the registry (using java.util.prefs.Preferences) to prevent multiple downloads or re-opens in short succession. The idea being to reduce the chances of a bug in my code causing something too nasty like an infinite loop of open-check-reopen-check-reopen-check etc. And I download the JNLP file with a timeout so a slow connection can't prevent the app from opening for too long. But those are just optional extras.

As my app runs with <security><all-permissions/><security/>, it has no problems downloading the JNLP file, saving it to the computer, and opening it with the default program. It might be possible to find workarounds for each of those steps using the javax.jnlp library so you didn't need all permissions, but I'm not too sure about that.

Overall for me this approach seems to be working very well. But I'm still hoping for a day when Java Web Start bugs like this are a thing of the past, as this sort of hacky nonsense really shouldn't be necessary.

Thanks for sharing it! I does sounds really tricky :/ I'll definitely give it a try if our current solution (see the comment by the accepted answer) fails for some kind of reason.
–
NagyIJun 24 '12 at 16:35