Why does Java WebStart application refuse to start if JNLP url contains %? - java

I've noticed a curious thing while trying to dynamically generate JNLP files based on URL parameters passed to a HTTP server. If I have something like this in my HTML code, it works:
<embed type="application/x-java-applet;" launchjnlp="dummy.jnlp"/>
If on the other hand I have a % character in the launchjnlp attribute, the plugin simply won't do anything:
<embed type="application/x-java-applet;" launchjnlp="dummy%3f.jnlp"/>
No error messages, no default Java splash screen, nothing, it silently fails. (Without even attempting to retrieve the JNLP file.)
Is this some kind of security feature? If it is, what is it supposed to guard against?
Or could it be a straightforward bug?
Update: Using the % entity instead of a % sign doesn't work either.
Update 2: I tried and failed to find any documentation on the exact semantics of the launchjnlp attribute, but the entire tag is generated by deployJava.launchWebStartApplication(jnlp), which is supposedly the "official" way of launching a Web Start application from a browser.
Update 3: Just to be absolutely crystal clear about this: the above example is just that: an example. You can observe the described behaviour with absolutely any URL (relative, absolute, file://, http://, you name it), any url-encoded character, or even an invalid escape sequence (though in that case it's more or less justified), the existence or absence of an actual JNLP file is irrelevant, because we don't even get to the point where the plugin would attempt to load the JNLP file.

Is this some kind of security feature? If it is, what is it supposed
to guard against? Or could it be a straightforward bug?
From what I can uncover, 'straightforward bug' is the answer. Here's the issue page:
https://bugs.openjdk.java.net/browse/JDK-8043409
It looks like it's not scheduled to be fixed until the release of JDK 9.
I'd suggest trying a different JDK implementation, but that seems unlikely to change anything given the amount of code shared between the Oracle and OpenJDK implementations and the fact that the WebStart code appears to be proprietary/closed-source.
So the workaround you devised with base64-encoding is probably the best option for now. If you have to do this often, maybe the encoding step can be rolled into the deployJava.launchWebStartApplication(jnlp) JavaSript API so that it happens automatically if/when needed.

Related

java 8u31 plugin causes signed applets to load much slower

i have noticed that signed applets are loaded much slower with the latest plugin (included in java 8u31 and 7u75). I have debugged the situation quite a lot and i found out that the problem is directly related to the size of the jar files that are referenced in the jnlp file. The problem is that each time the applet starts, there is some 're-indexing' of the cached jar files that takes time.
To reproduce the issue i did this:
I created a minimal applet and in the jnlp file i used to deploy it, I added several irrelevant .jar files (that are not even referenced, so the classloader does not load them) of considerable size (e.g. 30MB). Of course i am using versioning in the jnlp and capture all http traffic to make sure that the delays are not because of traffic (either re-downloading or certificate revocation checks, etc). I run the applet with the trace enabled and then went through the xml trace log file and found out where the delays come: they are always from the JarSigningVerifier ....
Has anyone else seen something like that?
It is very easy to see and reproduce this behavior and i wonder if there is something i am overlooking. Having worked on applets for the past years extensively, i am totally lost at what can be happening. I can verify that reverting to the previous version of the plugin (and every other version before) works as expected.
I have submitted a bug report with oracle, but i haven't heard back still. Any info or idea will help,
TIA
Same here. I thought already I'm getting crazy. Thanks for sharing this.
We are using Java Web Start, but it's sharing the same problem of re-indexing all jar files (in our case it's an app with quite some jars, so starting takes ages).
Aside from the fact that Oracle suddenly decided to check the certificate of the deploy TLS, which caused some hickup on Linux and Macs (we used a StartSSL certificate there, which isn't included in the Java keystore - on Windows it works as it uses the platforms root certs, too).
And, to make it even worse, on Windows x86 the 8u31 silently dies if -XX:+DoEscapeAnalysis or -XX:+OptimizeStringConcat is present in the JVM arguments, though both parameters are standard in Java 8 (but not in 7, that's why they've been included, still). The 64bit engine doesn't have that problem.
The next thing they changed is they now overwrite the start icons if they've been changed (we changed them to put the 64bit engine's path in there), so it stubbornly changes the path back to the 32bit engine every time.
The behaviour of Oracle is not helpful at all, as they didn't announce any of these changes in their changelogs, let alone announcing the certs changes a few days ahead.
I would like to hear from anyone who's sharing the problems and possible workarounds.
Patric
Have you been able to solve this issue? Have you had a reaction from Oracle?
UPDATE START
I've tried everything I can think of and haven't managed to solve the
issue, so I posted my own question on this issue.
A similar bug report can be found here and is backported to at
least Java 8u51 which I tested. Yet again they managed to increase
startup time for our application.
END UPDATE
We are using Java Web Start for an Eclipse RCP-based application with jars that are all signed.
Startup time is 8s within the IDE, Java version doesn't seem to matter here. With web start the story is different. It becomes (much) worse with every Java update:
7u?? (<60): +2s (10s)
7u60: +5s (13s)
7u75: +15s (23s)
8u31: +12s (20s)
8u40: +21s (29s)
8u51: +23s (31s)
Have you tried your jnlp without versioning? In my experience Java jnlp is very buggy specially if you change the jnlp default values. Versioning support is disabled by support, so try it without versioning and see if it still slow?
For me, I noticed some bugs when I used update="background" value, so I no longer change the default update method. My theory is that Oracle only tests jnlp against default values before they release new Java versions.

Java web app: Force browser to load static content (js, css, html) if deployed file changed

We're trying to force the client's browser to reload static files when they change. Currently, we have our build scripts automatically creating a new directory with the build timestamp and replace the content in the code to point to that directory.
However, I feel this is hardly an optimal solution. It forces the client browser to load every single file if a new build exists, even if only 1 file changed, and build time increases considerably by scanning every file and replace every static file reference.
I know we can also set the version when we declare files (something like < link src="blahblah.css?version=1.1" />), but this forces us to change all our code to include a version placeholder and still have our build scripts replacing it.
Is there a smarter way to do this? We're using Spring MVC. Is there any option in mvc:resources that I'm not aware of to do this without changing code? Or something on web.xml?
We're using tomcat. Is there a way to do this at server level? Would it help to use a cache like Varnish or something? Or these caches only allow to set expiry times and not check that the file changed? Bear in mind I'm not comfortable at all in server and cache configuration tasks.
I found out about this project https://code.google.com/p/modpagespeed/, but since it's far from my comfort zone, I'm struggling to understand capabilities and if this helps with what I want.
Anyone has any ideas?
Thanks
You can use version as a query parameter, e.g. /resources/foo.js?_version=1.0.0. If you are using Maven, it is not that hard to get version information from /META-INF/maven/{groupId}/{artifactId}/pom.properties. Of course this will force reload all scripts with every new version... but new versions are probably not deployed that often.
Then it is always a good practice to properly set HTTP caching headers. <mvc:resources> should correctly handle Last-Modified header for you. And you can set cache-period to make browser check the for resource modifications more often.
Here is a working solution: CorrectBrowserCacheHandlerFilter.java
Basically, when your browser requests the static files, the server will redirect every requests to the same one but with a hash query parameter (?v=azErT for example) which depends on the content of the target static file.
Doing this, the browser will never cache the static files declared in your index.htmlfor example (because will always received a 302 Moved Temporarily), but will only cache the ones with the hash version (the server will answer 200 for them). So the browser cache will be used efficiently for those static files with hash version.
Disclaimer: I'm the author of CorrectBrowserCacheHandlerFilter.java.

Java inexplicably writes to file with good or wrong codepage depending on web API call URL

Good evening,
I am thoroughly baffled by a behaviour that happens with a Java application of mine.
The application is to be used to connect to a web API and download a table of data from there to be further used in academic research.
I was trying to set the export to correct encoding, to save time, I disabled iteration in calls to web API by disabling some methods and removing a variable from a URL string construction - placing an integer 42 in its place.
Upon this, I was surprised to see the correct encoding.
A bit down the road, and I can confirm - if I use this URL:
new URL("http://www.foo.bar/api/unit?id="+scraper.ujList[i]);
where ujList[] is an array of integers,
then the output has typical wrong encoded characters like this ÄŤasĹĄ RuĹľinov
meanwhile, if I use
new URL("http://www.foo.bar/api/unit?id="+42);
then the output is proper, like Ružinov.
I have also tried Integer.toString() as well as String.valueOf() on ujList member, but it didn't help.
FWIW it does not matter if I run a jar file, a class file, or from within Eclipse.
I have no idea how to continue.

Getting absolute path jsf

I want to get the absolute path of my app and I'm using the code below:
String pathToSave = FacesContext.getCurrentInstance()
.getExternalContext().getRealPath("/");
the result is:
/home/ronaldo/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Odontonew/
But I'm waiting for something like: /home/ronaldo/workspace/Odontonew/
What is wrong ?
ExternalContext#getRealPath() returns the path relative to where the webapp is been deployed, not where the webapp is been developed orso, as you incorrectly seemed to expect.
But, the variable name pathToSave indicates a much bigger problem: you seem to intend to save files in there. This is a bad idea for the reasons mentioned in the following answer: Uploaded image only available after refreshing the page. In a nutshell, save them to a fixed local disk file system path instead. Note that some servers offer ways to make this step easier configurable, e.g. JBoss.
Just stop using getRealPath(). You never need it in real world. In the 10 years I developed Java web applications (it's under the covers coming from ServletContext#getRealPath()), that method was never been useful for anything. Just ignore that method altogether.
See also:
What does servletcontext.getRealPath("/") mean and when should I use it

Java WS application ignoring arguments sporadically

I have recently put together a JWS application which gets it's argument from a dynamically created JNLP file (details can be found here). It's all good except the application ignores the argument (starts without loading the specified number) on my system (linux x86_64). It seems however that the JWS application exactly as intended on the win_64 machine of a colleague of mine. This is rather interesting as I couldn't replicate his success on another similar win_64.
To make things more exciting, the same JWS application works just fine (in other words, doesn't ignore the argument) when I download the JNLP file and run it by javaws on the terminal.
I have compared the java.policy and javaws.policy files and there are no differences. The JNLP file clearly gives all-permissions, and the jar files are signed all fine (which can't be the source of the problem otherwise the application wouldn't start, right?).
Question 1: So what could this problem depend on?
EDIT: I just managed to get proper response from a new (in this particular sense) win32 machine, without any obvious java update. Question 2 : Is there a log file for javaws on which I can check what happens, or alternatively, can I verbose the launch to a console so I can create my own custom logs?
Edit 2: By the way, I have forgotten to mention that I have also posted this question at the Oracle forums, which I should have perhaps mentioned initially as it was politely pointed out there. Anyways, there is more information on the JNLP file there on the thread, in case it might be relevant.
Edit 3: I came to think that the problem could be originating from the properties of the <jnlp> tag, upon generating the JNLP file. Originally the jnlp tag looked like this like this:
<jnlp spec="1.0+" codebase="http://mydomain/myapp/"
href="my.jnlp">
The problem with this is the fact that there is no my.jnlp in the the directory declared in the codebase, instead the JNLP code is created on the fly by a Perl script in the cgi-bin directory and returned as an output stream (I think). So I edited the script to generate the JNLP with the following tag:
<jnlp spec="1.0+" codebase="http://mydomain/myapp/"
href="http://mydomain/cgi-bin/my.jnlp">
The result of this experiment: not even the GUI started this time...
I have found a relevant thread on Oracle forums, where it was advised to define the href property in the following fashion:
href="script.jsp?<%=request.getQueryString()%>">
which unfortunately doesn't solve my problem.
Question 3: Could this modification be applicable to my situation as well? In that case how? If not any insights on what might be causing the problem would be seriously appreciated as I am really at a stalemate on my work right now
After two weeks of wrestling with the JNLP file syntax and my CGI script, I think I finally found the crux of the problem. I am noting this down here (at the risk of looking pretentious enough to answer my own question) in case somebody else runs into the same problem.
The href property of the <jnlp> tag, in my case was apparently unnecessary and when removed the application started working as intended on both linux and win systems. I am not 100% sure if this is the exact reason but my understanding is that as the jnlp syntax is generated from a script and directly returned to the user instead of a jnlp file somewhere in the filesystem, the href property was pointing to a wrong place and perhaps caused some sort of a clash that is handled differently in different OS.
Make sure the JNLP file is not cached. I.e., each time you try something new, have you renamed / relocated the JNLP file?
Regarding your updates,
The only ting that comes to my mind is that you need to make sure that your script responds with the correct mime type: application/x-java-jnlp-file
That is, from your cgi-script, you have to provide the HTTP header field
Content-Type: application/x-java-jnlp-file

Categories