views:

55

answers:

1

Hi,
I have a js file which is cached between 5-10 minutes, depending on whether I'm using tomcat from the eclipse (via GWT plugin) or starting tomcat as standalone.
This is strange as I'm using GWT as my framework and this file should not be cached at all (it's a nocache.js file to those of you who know GWT). I've read on a GWT Google group thread that it's a container configuration issue, and somewhere else that it's something I need to define in the containing HTML file.
Basically, I'm confused right now as I have no clue on how to get this file to not cache. Please note that this js is generated by GWT and I cannot modify it.

Thanks for any help, Ittai alt text alt text

+1  A: 

Using a javax.servlet.Filter

One way to do this in a portable way (across different app servers), is using Filters. In your web.xml add the following:

  <filter>
    <filter-name>headersFilter</filter-name>
    <filter-class>MyHeadersFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>headersFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

Then implement your MyHeadersFilter like:

public class MyHeadersFilter implements Filter {

  @Override
  public void doFilter(final ServletRequest request,
         final ServletResponse response, final FilterChain chain)
         throws IOException, ServletException {

      final HttpServletRequest httpRequest = (HttpServletRequest) request;
      final String requestUri = httpRequest.getRequestURI();

      final HttpServletResponse httpResponse = (HttpServletResponse) response;


      if (requestUri.contains(".nocache.")) {
        httpResponse.addHeader("Cache-Control", "no-cache");
        ...

      } else if (...) {
        ...
      }

      chain.doFilter(request, response);
  }
}

Optional: Configurable Filters

You can also make your filter configurable from your web.xml, by using <init-param>s:

  <filter>
    <filter-name>headersFilter</filter-name>
    <filter-class>MyHeadersFilter</filter-class>
    <init-param>
        <param-name>myParam</param-name>
        <param-value>myValue</param-value>
    </init-param>
  </filter>

Add the following to MyHeadersFilter:

    private FilterConfig filterConfig;

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void destroy() {
        this.filterConfig = null;
    }

That makes it possible to access your init-param(s) using:

filterConfig.getInitParameter("myParam")
Chris Lercher
thanks! In such a filter, if I don't use any external resources or class properties, should I do anything in the destroy() method?
Ittai
and also, will this work? httpResponse.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");or should I write multiple httpResponse.addHeader("Cache-Control", "value1");httpResponse.addHeader("Cache-Control", "value2"); etc...
Ittai
@Ittai: The destroy method should clean up any instance fields that could continue using memory, when the container takes the filter out of service, but for whatever reason doesn't remove the reference to the filter. From the Javadoc: "This method gives the filter an opportunity to clean up any resources that are being held (for example, memory, file handles, threads) and make sure that any persistent state is synchronized with the filter's current state in memory."
Chris Lercher
@Ittai: You can use addHeader("Cache-Control", "no-cache, no-store, must-revalidate")
Chris Lercher