The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


Why can't we get rid of JNLP @codebase?

Posted by kohsuke on July 27, 2009 at 2:57 PM PDT

Java Web Start demands that the JNLP file contains the codebase attribute on the root <jnlp> tag, but this is really problematic.

The reason this is problematic is mainly because of the difficulty for a web application to know its own URL. Think about a web app like Hudson, which can be deployed anywhere, and thus doesn't have any a'priori knowledge of its URL. The closest it gets is the Host header and request URI line, but even this isn't necessarily what the browser has sent to you, for example if a reverse proxy is involved (and this is a very common set up.)

So I was thinking about filing a bug, and started to dig bit deeper into understanding why the codebase attribute is necessary. The first authoritative information I found was "Codebase Determination for JavaSE 6u10", and in it it simply says this is so "for technical reasons."

I eventually found out the root cause in the bug parade:

The Browser downloads the jnlp file into a temp directory on the client. The browser then launches Java Web Start with that file as an arg. Java Web Start has no way of knowing where that file was downloaded from.

This also reminds me of another annoying usability issue with Java Web Start, namely it clutters your desktops with *.jnlp files.

It's bit hard to believe that there's no way to retrieve the original URL from the browser — I can see why it can't be done if JWS depends on the "associated application" mechanism, but shouldn't there be more/better ways to integrate with browsers? After all, this seems like a fairly generally useful capability.

In any case, until then, the only solution is for the application to ask the user to enter the URL. Bummer.

Related Topics >> Java Enterprise      
Comments
Comments are listed in date ascending order (oldest first)

The moment someone downloads the application, you can have a small piece of javascript determine the location. You can then either encode that in the download URL of use ajax to send it to the server. That works even if a revered proxy is involved.

I usually just have the JNLP dynamically generated anyway.

r_spilker: if you rely on the referer to pass in the URL of JNLP (for example as a query string), the downside is that it clutters the URL. malachid: it doesn't matter if you dynamically generate it or not. Consider reverse proxy.

You can do better in the browser with a plug-in or extension, like Microsoft does with the “Microsoft .NET Framework Assistant” on Firefox for ClickOnce, but look where that got them: http://www.google.com/search?q=.net+framework+assistant+firefox

The only proper solution is to open .jnlp from browser plugin, instead of downloading it do disk and opening it like regular file. In this case, plugin is aware of .jnlp file URL. Or just declare JNLP application in HTML page with object tag (as applets), like,

The only proper solution is to open .jnlp from browser plugin, instead of downloading it do disk and opening it like regular file. In this case, plugin is aware of .jnlp file URL. Or just declare JNLP application in HTML page with object tag (as applets), like,

like <object type="jnlp" .../>

like

The correct solution seems obvious to me: the browser shouldn't be downloading the jnlp file at all, it should be delegating that to javaws. i.e. Whenever the browser sees a URL like jnlp+http://example.com/my-spiffy-app.jnlp it should let javaws handle it.

Good post--this has been an annoying mess for many years. Indeed, one of the reasons that Adobe is eating our lunch is that they have put the engineering resources into a reliable and unobtrusive browser plugin, whereas we have two half-assed, fragile, and gratuitously different mechanisms (applets and JNLP). Historically, JNLP made sense, as a mechanism that Microsoft would have a harder time sabotaging. But those times are long gone. We have a browser plugin, i.e. the applet handler, and it could be engineered to handle out-of-browser applications in a sane way. Maybe now that the JavaFX folks share the pain, things will improve.

IMO, this has been the biggest drawback to JNLP deployment since its inception. Developers shouldn't have to rely on dynamically generated JNLP to get this behavior.

Another problem of JAWS is that the JNLP file will appear in the download window of your browser, and may request user confirmation to be launched. It's a disgrace of user experience even after 6u10. Suggestion: improve the Java Depolyment Toolkit and JavaFX Deployment Toolkit, so the webpage contains a call to a JavaScript function that will fetch the JNLP file and launch JAWS without requiring any temp file (perhaps just pass the whole content of the JNLP as a parameter, or with some other mechanism). Change the JRE installer so the option Advanced>Miscellaneous>Place Java icon in the system tray is disabled by default. Only developers need that. Eliminate JavaFX's stupid first-run EULA dialog. Make Java and JavaFX as transparent and non-intrusive as Flash and Silverlight.

@nzcarey: oh, so that's what that was all about. I saw a lot of posts about how to remove it, but never saw what it intended to do. That's a very good point --- and it's fairly expensive if we have to write an extension for every major browsers out there separately. OTOH another benefit of doing this as a browser extension is that JWS no longer has to maintain its own authentication, proxy, or cookie settings, so it improves the user experience. @cayhorstmann: JavaFX seems to be mostly concentrated on enhancing applets so far, so I'm not holding my breath, but indeed it'd be nice if they could improve this, too.

@gkbrown: like I wrote to malachid, generating JNLP file on the fly doesn't entirely fix the problem, in the presence of reverse proxy. @opinali: good point about the download window, although now that I think about it, I find it useful as I can quickly relaunch the app without going back to the page, so maybe it's not all bad.

@kohsuke: To relaunch the app you can just use the icon that JAWS can be configured to create in your desktop. Picking a JNLP file from your download window, temp dir or browser history is not something we should expect from common users. It's a usability failure - the more clicks and confusing dialogs you need to launch a web application, the worse. The only good implementation is: (1) User clicks a Launch button, (2) User waits for the download, (3) App is running. Any extra step simply blows. BTW, Step 2 is also screwed up by JAWS's usage of two different temporary dialogs: first the "Java loading..." dialog, then a second "Downloading application..." dialog. This is a completely unnecessary transition; JAWS should present a single dialog, perhaps adding a download progress bar dynamically after checking that the app is not fully cached. Sun makes massive efforts like JDK 6u10 to fix "core" problems, but consistently fails to fix pretty basic usability issues... BTW, another suggestion: the JRE installer should also set Advanced>JNLP File/MIME Asociation to Always allow, by default. (Current default is Prompt user.) The configurations that produce smoother user experience should all be the defaults, except when there's some security tradeoff.

@opinali: agreed.

I also had a problem with codebase when I tested JavaFX. As you're not allowed to distribute JavaFX, the solution is to distribute your JavaFX program with a JNLP file to start it. But JNLP doesn't accept codebase="." So you need to set it to codebase="file:///C:/Program%20Files/MyProgram" which of course you can't know before the user install it.

Documentation about JNLP applets and more

Starting in release Java SE 6u10, applets can be deployed using JNLP and have capabilities similar to Java Web Start applications (without the hassle of specifying the codebase). If applets will satisfy your business needs, check out the newly released Deployment Tutorial to learn more. The Deployment Tutorial contains the following lessons: