I am developing a web application that runs on Struts2 and Tomcat 7.0.42.
I wrote an action that dinamically generates a jsp file, generated.jsp, with some image references in it and creates the associated "_files" folder containing the images.
The action is called in another page, request.html, via JQuery ajax request and then loads the generated.jsp with a JQuery load. The request.html file looks like this:
<HTML>
<HEAD>
<script language="javascript">
$(function() {
$.ajax({
type: "POST",
url: "http://..../myAction.action",
data: someDataObj,
success: function(msg){
$("#myDiv").load("http://.../generated.jsp");
});
}
</script>
</HEAD>
<BODY>
<div id="myDiv"> </div>
</BODY>
</HTML>
At every request the action first deletes the old files and then generates everything. The generated images depends on the data passed in the ajax request.
The generated.jsp page contains some directives to make tomcat send response header to prevent the page from being cached:
<%
response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
%>
If I do open request.html and I do requests not too often, waiting some seconds after the generated page is displayed, it all works as expected: the page and its images are displayed.
But if I do a couple of requests very fast, like waiting less than a second for each one, I see that the images displayed are the ones generated from the older request.
Looking at the request and response headers, when it works good the response code for the page and images is always "200 OK".
When the problem occours, tomcat answers the GET request for generated.jsp page with status code "200 OK", but the requests for the images it returns "304 Not Modified" even if the image files are different from the last request.
There are the request/response headers:
Request URL:http://.../generated.jsp Request Method:GET Status Code:200 OK Request Headersview source Accept:text/html, */*; q=0.01 Accept-Encoding:gzip,deflate,sdch Accept-Language:en-US,en;q=0.8,it;q=0.6 Connection:keep-alive Cookie:JSESSIONID=44E591CE76423F14CCFBE2DF86F50DDE Host:127.0.0.1:8080 User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 X-Requested-With:XMLHttpRequest Response Headersview source Cache-Control:no-cache Content-Type:text/html;charset=ISO-8859-1 Date:Tue, 03 Dec 2013 07:54:05 GMT Expires:Thu, 01 Jan 1970 00:00:00 GMT Pragma:no-cache Server:Apache-Coyote/1.1 Transfer-Encoding:chunked
Request URL:http://.../generated.jsp_files/img.png Request Method:GET Status Code:304 Not Modified Request Headersview source Accept:image/webp,*/*;q=0.8 Accept-Encoding:gzip,deflate,sdch Accept-Language:en-US,en;q=0.8,it;q=0.6 Cache-Control:max-age=0 Connection:keep-alive Cookie:JSESSIONID=300B5CB436CD60BA8E129B21B085A965 Host:127.0.0.1:8080 If-Modified-Since:Mon, 02 Dec 2013 15:31:57 GMT If-None-Match:W/"1481-1385998317000" User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36 Response Headersview source Date:Mon, 02 Dec 2013 15:32:00 GMT ETag:W/"1481-1385998317000" Server:Apache-Coyote/1.1
I don't think that the problem is caused by the browser cache, because the requests are done and the browser uses the cache only after it receives the 304 status code.
I have tried different things, until I found a workaround.
First, I've modified the action to delete the old files at every request, page and images, and then generate everything, but with no success.
Then I've tried to generate the images every time with a different name, concatenating a timestamp to the file name.
What happens is that generated.jsp is first deleted, then generated with the reference to the new image names at every request.
In this case when the browser requests generated.jsp tomcat returns the page with 200 OK status code. When the problem occours, looking at the source of the page, I can see that what is returned is the page with the old image name references.
It seemed like tomcat don't recognize the file changes and that the old images doesn't exist anymore, because at the requests of the image with the old name it still answers with a 304 status code.
Seeing this behaviour, I checked tomcat's work directory to find the "java" and "class" files corresponding to generated.jsp and I found that those files has a timestamp older that the page contained in the webapp folder.
At this point I've tried another workaround: make the action delete tomcat's work subfolder containing generated.jsp related files.
Even this attempt failed, same behaviour with the browser receiving the old generated.jsp page and the 304 status code for images.
The only workaround that did the trick was to delete the old page in webapp folder and create the page with a different name, like I did with the images.
I read in the documentation that Tomcat does check at every request if a resource is modified, unless some properties in web.xml are changed.
Seeing this behaviour I believe that tomcat uses some cache to do the check and doesn't do the that on the filesystem every time, but I haven't found anything in the documentation.
Does someone knows if I am wrong and maybe help me understand how those mechanism works in Tomcat?
Tomcat caches stuff on the server, so modifying the resources available at runtime is going to get you into trouble. You will spend the rest of your career trying to work-out all the kinks and go insane in the process. I'm sorry, you're going to need to re-think your approach.
Instead of generating code, etc. on each request, why not serve the request 100% dynamically each time, directly from the servlet?