I have a JSF page which posts data to an external page. The data is loaded from a JSF managed bean which generates a unique ID in the post data.
I have an issue wher
I found a solution that works for JSF without having to create a servlet-filter. Just put the line below to your .xhtml page.
<f:event type="preRenderView" listener="#{facesContext.externalContext.response.setHeader('Cache-Control', 'no-cache, no-store')}" />
That page is likely being loaded from browser cache. This is essentially harmless, but indeed confusing to the enduser, because s/he incorrectly thinks that it's really coming from the server. You can easily confirm this by looking at the HTTP traffic monitor in browser's web developer toolset (press F12 in Chrome/FireFox23+/IE9+ and check "Network" section).
You basically need to tell the browser to not cache (dynamic) JSF pages. This way the browser will actually request the server for the page (and hereby triggering proper creation/initialization of managed beans and so forth) instead of showing the previously requested one from its cache.
Generally, this is to be done with a simple servlet filter like follows:
@WebFilter("/app/*")
public class NoCacheFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(req, res);
}
// ...
}
Where /app/*
is the example URL pattern on which you'd like to turn off the browser cache. You can if necessary map it on /*
, *.xhtml
or even on servletNames={"Faces Servlet"}
.
If you happen to use JSF utility library OmniFaces, then you can use its builtin CacheControlFilter by just adding the following entry to web.xml
(which demonstrates a direct mapping on FacesServlet
, meaning that every dynamic JSF page won't be cached):
<filter>
<filter-name>noCache</filter-name>
<filter-class>org.omnifaces.filter.CacheControlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>noCache</filter-name>
<servlet-name>facesServlet</servlet-name>
</filter-mapping>
See also the showcase.