views:

870

answers:

2

I have an Applet which is loading images over a http connection using URLConnection. I am setting setUseCaches(true) for all connections, but still not seeing any caching behavior. My image's HTTP headers have reasonable cache settings. If you look at bug 4528599 there is this rather mysterious statement:

The current version (1.3.1) of Java Plug-In only checks the browser cache for files whose names end in .jar or .class. I have been told that for Java Plug-In 1.4 the browser cache will be checked for the following file types: .class, .jar, .zip, .jpg, .gif, .wav, .au.

Of course, this was marked as FIXED for 1.6, but even under 1.6 I don't see any caching. My images are PNG files, and in some cases don't actually end in with a .png extension. I don't see any caching.

The bug fix report talks about the 1.6 Unified Download Engine, but google doesn't seem to know much about it.

Is this supposed to work or it just another broken Sun "feature". Is there any way or workaround where I can get my applet to load PNG images from the browser cache? I would prefer not to implement my own....

UPDATE: The caching seems to be tied to the ResponseCache implementation. See this technote for more info on how that works. The last line says:

There is no default implementation of URLConnection caching in the Java 2 Standard Edition. However, Java Plugin and Java WebStart do provide one out of the box.

So it seems to me that the the question really becomes: How does the Java Plugin ResponseCache implementation really work? What are the differences between v1.4/v1.5/v.16

Anyone got any ideas?

A: 

This method very likely only sets the HTTP Cache-Control header directives in the outgoing request to values that permit caching. Had you called setUseCaches(false), there'd be a

Cache-Control: no-cache

directive for example. To check this, you could put an HTTP debugging proxy server between your applet and the server and take a look at the headers.

Now just because the request says it's willing to use caches, your server might not be set up to enable them. Perhaps it's not setting an Expires header with an appropriately long time in the response, or perhaps it's setting a Cache-Control header in the response that prohibits caching.

Some other things to check:

  • https responses are never cached;
  • You may not have an HTTP cache between client and server;
  • The only HTTP cache is the browser's cache but it may be disabled or set to use very little disk.

If this were just a vanilla browser to web application test, you'd also want to make sure you weren't hitting the refresh button, since that's equivalent to setting no-cache.

Jim Ferrans
+1  A: 

The abstract class URLConnection provides set/getUseCaches methods, which can be used by any subclasses. As far as I've ever been able to determine, however, the HttpURLConnection class doesn't use those fields in any way. Setting the value to true or false won't have any different behavior.

If you want to add http cacheing behavior, you can either do it yourself (write your own, or extend HttpURLConnector; or use Sockets), or try using the If-Modified-Since and If-None-Match headers and look for a status code 304 (Not Modified). The second option is probably the easiest and will get you the best results.

joe p
Writing your own is non-trivial when the cache is persistent. You need to make it accessible to multiple JVMs operating simultaneously and you need to limit it in size. It really should just work....arrgh...
Joel Carranza
I'd definitely recommend not rolling your own cache. If the client and server are sending the right HTTP headers but there is no intermediate HTTP cache set up between the client and server, install a proxy cache such as Varnish, Pound, or Squid.
Jim Ferrans