tags:

views:

1471

answers:

4

I am making modifications to /grails-app/views/index.gsp.

When I save the file and refresh http://localhost%3A8080/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!

+1  A: 

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.

John Wagenleitner
+4  A: 

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.

Burt Beckwith
Thanks for the detailed answer. For how long are gsp pages cached by default? Also-- what would you recommend doing for production environments?
Emmett
A: 

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.

Aman Aggarwal
A: 

This DOESN'T work. super.doPage doesnt work because it doesnt compile. There is no doPage method in the super object!

Tester
In more recent versions of Grails you'll need to override doService() instead of doPage() but otherwise the code should be the same.
Burt Beckwith