Question

While debugging our web app, we found out that the "Last-Modified" timestamp of the .js / .css / etc static files that is returned by our JBOSS cluster fluctuates between two different values - which is also the number of nodes in our JBOSS cluster (we have two machines, each one running an instance of JBOSS in a cluster-node configuration). We then verified that each JBOSS node indeed serves a different timestamp (for a specific requested resource, e.g. /some/resource.js), which is NOT the modification timestamp of the file as it exists inside the APPNAME.war.

Further searching revealed that when a new version of our .ear is deployed to the cluster, the two JBOSS instances uncompress it in automatically named folders (e.g. .../deployment4670b6dc3fccdb52/APPNAME-war-885ea865da6056a5/ ). In these folders, we checked and verified that it is the modification timestamps of the newly uncompressed files that are used for the "Last-Modified" HTTP header responses, and that these timestamps are indeed NOT the actual modification timestamps contained inside the .war. In fact, It looks like JBOSS is using the deployment time when uncompressing these files - which means it uses the "current time during decompression of .war", and each JBOSS instance ends up with its own, local "version" of the timestamps.

Which in turn means, that the JBOSS cluster serves clients with DIFFERENT "Last-Modified" timestamps for static resources, depending on what server the JBOSS cluster IP forwards them on! Since our cluster is configured for a round robin basis, this means that the browsers of our clients get to see "Last-Modified" headers that look like this:

  1. GET /some/resource.js
  2. Returned HTTP "Last-Modified" header from e.g. JBOSS instance A, value T1
  3. ....
  4. GET /some/resource.js
  5. Returned HTTP "Last-Modified" header from e.g. JBOSS instance B, value T2
  6. ....
  7. GET /some/resource.js
  8. Returned HTTP "Last-Modified" header from e.g. JBOSS instance A, value T1

...with T1 and T2 two completely different timestamps (the times the .war was uncompressed in each of the two cluster nodes).

This, finally, seems to completely mess up the cache bookkeeping of browsers. More specifically, browsers end up re-downloading things all the time - which is indeed extremely wasteful.

Why isn't JBOSS using the timestamps contained in the .ear and instead uses the "deploy-decompression-time"? I verified that using "jar xvf" to extract the .war from the .ear, and again "jar xvf" on that .war, the timestamps are correct (the ones in the machine doing the build). The timestamp information is there, inside the .ear/.war - it just seems to be ignored by JBOSS.

The workaround we use so far is to stop one of the two nodes in the cluster, thus forcing "consistent" timestamps (wrong ones, mind you - since they are the "deploy time" of the node that is still up - but at least they remain consistent across repeated HTTP requests for the same resource.

Any help most welcome.

Was it helpful?

Solution

Turns out this is a bug in JBOSS EAP 6.0, which is fixed in later versions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top