I am making modifications to /grails-app/views/index.gsp.
When I save the file and refresh http://localhost:8080/index.gsp in Firefox, I am getting an old version of the file.
Is there a way to prevent Grails from caching and rendering old versions of the file?
(I tried restarting the server and clearing Firefox's cache.)
Thanks!
There doesn't seem to be a simple way to do this, but it's not much work. My solution subclasses the servlet that renders GSPs (and also the controller that's used for non-GSP requests).
Here's the servlet subclass:
package com.burtbeckwith;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codehaus.groovy.grails.web.pages.GroovyPagesServlet;
public class CachingPageServlet extends GroovyPagesServlet {
private static final String HEADER_PRAGMA = "Pragma";
private static final String HEADER_EXPIRES = "Expires";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
@Override
public void doPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader(HEADER_PRAGMA, "no-cache");
response.setDateHeader(HEADER_EXPIRES, 1L);
response.setHeader(HEADER_CACHE_CONTROL, "no-cache");
response.addHeader(HEADER_CACHE_CONTROL, "no-store");
super.doPage(request, response);
}
}
and you'll need to replace the original in web.xml (run "grails install-templates" and edit src/templates/war/web.xml):
<servlet>
<servlet-name>gsp</servlet-name>
<servlet-class>com.burtbeckwith.CachingPageServlet</servlet-class>
</servlet>
and you'll probably also want to do the same for Controller-based responses, so to do that use this controller subclass:
package com.burtbeckwith;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsController;
import org.springframework.web.servlet.ModelAndView;
public class CachingSimpleGrailsController extends SimpleGrailsController {
private static final String HEADER_PRAGMA = "Pragma";
private static final String HEADER_EXPIRES = "Expires";
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setHeader(HEADER_PRAGMA, "no-cache");
response.setDateHeader(HEADER_EXPIRES, 1L);
response.setHeader(HEADER_CACHE_CONTROL, "no-cache");
response.addHeader(HEADER_CACHE_CONTROL, "no-store");
return super.handleRequest(request, response);
}
}
and you'll need to register it in grails-app/conf/spring/resources.groovy to override the regular Spring bean:
mainSimpleController(com.burtbeckwith.CachingSimpleGrailsController) {
grailsApplication = ref('grailsApplication', true)
}
The shared header-setting code should probably be extracted into a utility class instead of being copy/pasted like I did here.
can't we use a filter like this?
class CacheFilters{
def filters = {
all(controller: '*', action: '*') {
before = {
((HttpServletResponse) response).setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
}
after = {
}
afterView = {
}
}
}
}
There's a plugin for controlling cache behavior in grails called Cache Headers:
http://grails.org/plugin/cache-headers
Make sure you are running in dev mode (i.e., grails run-app and not grails test|prod run-app, test and production will enable caching of the pages. If you are in dev mode, try holding the shift key when click the Firefox refresh.
If you simply want to disable cache for your browser while development, you can use Web Developer add on for Firefox:
https://addons.mozilla.org/en-US/firefox/addon/60
Install this add on & choose "Disable cache". Remember, that will disable caching for all the websites.
For just development purposes try pressing ctrl+F5, it will refresh the page and the cache too.. for caching things on production and improving performance of page lookup ui-performance plugin and resources plugins of grails.