1

I have a bit of code like this in my template:

#{list people, as:'person'}
    <img src="@@{Application.image(person.id)}">
#{/list}

After starting up the play server, the list shows the first image multiple times. So for example, if the people variable contained the ids of 1, 2, 3, 4, 5 - then there will be five images shown but they are all the same image: that of the image corresponding to the id of 1.

If I hit refresh, the images all change to be unique depending on their ids. The html rendered from the template looks like this:

<img src="http://url/application/image?personId=1"/>
<img src="http://url/application/image?personId=2"/>
<img src="http://url/application/image?personId=3"/>
<img src="http://url/application/image?personId=4"/>
<img src="http://url/application/image?personId=5"/>

How can I stop the template from showing the same image first time round?

Edit: Also tried adding the response headers seen below prior to the renderBinary(image) call in my controller that responds to the src request:

...
response.setHeader("Pragma-directive", "no-cache");
response.setHeader("Cache-directive", "no-cache");
response.setHeader("Cache-control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "0");
renderBinary(imageFile);

as per this post. It actually worked the first couple of times but then the third time after stopping and starting the Play server, I had the same caching issue where all the images showed the same image despite the differing personIds. I have also appended the timestamp to the end of the url without any luck.

Edit #2: I also tried changing the http.cacheControl property to 0 in the application.conf:

http.cacheControl=0

But it again gave me inconsistent results as to whether it showed the right or wrong images.

Community
  • 1
  • 1
digiarnie
  • 20,378
  • 29
  • 75
  • 124

2 Answers2

1

2 options I can think of:

  1. Generate a unique number and append it to the URL of the image as a useless parameter. For example, "http://url/application/image?personId=1&ts=12314125123". Since this changes the URL every time the page is generated, the browser won't hit cache and will request the image each time. Usually timestamp works best as the parameter.

  2. Find some way to set the "Cache-Control" HTTP response header parameter with a value of "no-cache" when the image is served. If you're using a custom servlet to stream the images this should be pretty easy. If not, I'm unsure how you can do this, but perhaps Play provides a way.

In the past, I've usually used option 1 because it's almost always much easier. Ghetto, but it works.

Kaleb Brasee
  • 48,461
  • 8
  • 103
  • 110
  • I thought of doing that but figured that the personIds were at least going to be unique the first time round, why would adding a timestamp make a difference? (I tried it and the problem seems to have gone away, but just a bit confused as to why the personId didn't have the same affect, at least first time round) – digiarnie Dec 21 '11 at 02:38
  • correction, I just had another instance where the image repeated itself despite having the timestamp. – digiarnie Dec 21 '11 at 02:58
  • I also tried this: response.setHeader("Cache-Control", "no-cache"); in my controller prior to the call to renderBinary(image); and that didn't seem to fix the problem either. – digiarnie Dec 21 '11 at 03:06
1

I'm not sure if this is a viable solution, but I've got a work around for now that seems to work (well, it hasn't failed on me just yet) by doing these things:

  • Set the cache-control prior to the renderBinary(...) call in the Controller

    response.setHeader("Cache-Control", "no-cache");

  • Convert the File that you are rendering to a FileInputStream and pass that to the renderBinary(...) method instead of the File directly.

Like this:

File fileImage = ... // some .png image
FileInputStream stream = new FileInputStream(fileImage);
renderBinary(stream);

I got the idea from seeing this bug report about caching and rendering binaries.

digiarnie
  • 20,378
  • 29
  • 75
  • 124