GWT Tips 2 - nocache.js getting cached in browser
I have recently discovered that, after version deployments, our GWT application does not work in some users' browsers unless they do a hard refresh on the browser.
A bit of investigation revealed that this is because their browsers are caching the all-important YOUR_MODULE_NAME.nocache.js file. This file is GWT's bootstrapping file and its content (not its name) is likely to change as you introduce changes and then gwt-compile your Java code. If a user has an older version of this js file cached in the browser, the application will not be able to properly communicate with your server code. One should make sure that this file does not get cached by the browser nor any proxy servers along the way.
You may wonder what is the significance the of the "nocache" bit in the name. What does it actually do? Well, it does not do anything! But having this identifiable string in the filename does allow you to configure your server to send HTTP header information to the client browser to stop it from caching the file.
If you are using Apache to serve your static files. You can simply edit your .htaccess file to send the correct HTTP header information to the client for this nocache.js file.
However, if you are using a Java application server such as Tomcat to server your static files, you have to create a servlet Filter to dispatch the necessary HTTP header information. Below is a filter I have written to do exactly this:
Essentially, this filter checks whether the requested file name contains the string ".nocache.", and if it does, it sets the header to tell the browser and any proxy servers along the way to not cache the file. For an excellent explanation of the different header options, check out http://code.google.com/p/doctype/wiki/ArticleHttpCaching.
Of course, you would have to add this filter to your web.xml (host-mode as well as standalone mode):
A bit of investigation revealed that this is because their browsers are caching the all-important YOUR_MODULE_NAME.nocache.js file. This file is GWT's bootstrapping file and its content (not its name) is likely to change as you introduce changes and then gwt-compile your Java code. If a user has an older version of this js file cached in the browser, the application will not be able to properly communicate with your server code. One should make sure that this file does not get cached by the browser nor any proxy servers along the way.
You may wonder what is the significance the of the "nocache" bit in the name. What does it actually do? Well, it does not do anything! But having this identifiable string in the filename does allow you to configure your server to send HTTP header information to the client browser to stop it from caching the file.
If you are using Apache to serve your static files. You can simply edit your .htaccess file to send the correct HTTP header information to the client for this nocache.js file.
However, if you are using a Java application server such as Tomcat to server your static files, you have to create a servlet Filter to dispatch the necessary HTTP header information. Below is a filter I have written to do exactly this:
import java.io.IOException;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* {@link Filter} to add cache control headers for GWT generated files to ensure
* that the correct files get cached.
*
* @author See Wah Cheng
* @created 24 Feb 2009
*/
public class GWTCacheControlFilter implements Filter {
public void destroy() {
}
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
if (requestURI.contains(".nocache.")) {
Date now = new Date();
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setDateHeader("Date", now.getTime());
// one day old
httpResponse.setDateHeader("Expires", now.getTime() - 86400000L);
httpResponse.setHeader("Pragma", "no-cache");
httpResponse.setHeader("Cache-control", "no-cache, no-store, must-revalidate");
}
filterChain.doFilter(request, response);
}
}
Essentially, this filter checks whether the requested file name contains the string ".nocache.", and if it does, it sets the header to tell the browser and any proxy servers along the way to not cache the file. For an excellent explanation of the different header options, check out http://code.google.com/p/doctype/wiki/ArticleHttpCaching.
Of course, you would have to add this filter to your web.xml (host-mode as well as standalone mode):
<filter>
<filter-name>gwtCacheControlFilter</filter-name>
<filter-class>com.seewah.blog.GWTCacheControlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gwtCacheControlFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Comments
If only I'd seen your post some time ago :(
I wasted a good few days on this until I was helped on stackOverflow.
Do you happen to know why previous versions of GWT's nocache.js were not cached and this one is?
Because I can almost swear that it used to work.
Thanks in advance
http://bit.ly/GwtApacheConfig
Thus, is this filter necessary ?
This solution worked for us as well. I verified with Firebug that the correct headers are now sent. No more 304's! :)
Thanks a bunch.
Alex
thanks..
I am getting same problem, but using IIS, do you have any suggestion from IIS point of view.
Hai i am using jboss server and also am using the same filter code you posted that but not working its problem for my code ..how to solve that
Angularjs developer
Anika Digital Media