Reputation: 5964
I have a JSF application. Upon hitting an entry point.
/MyApp/start.xhtml
The page contains a view action which will decide from the query string params which page to go to.
<f:viewAction action="#{startController.newQuote()}" />
.
@ManagedBean
@SessionScoped
public class StartController {
public String newQuote(){
....
FacesContext fc = FacesContext.getCurrentInstance();
ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler)fc.getApplication().getNavigationHandler();
nav.performNavigation("aboutYou.xhtml?faces-redirect=true");
}
The aboutYou.xhtml
is reportedly hit 3 times according to my filter.
@WebFilter("*.xhtml")
public class TrackingFilter implements Filter {
private static Logger LOG = Logger.getLogger(TrackingFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
LOG.trace("request URI: " + req.getRequestURI());
}
why is this? I suspect it is to do with the PRG pattern used by ?faces-redirect=true
but I might expect to see this 2 times, not 3.
how do I optimise my filter so that I only catch a single action of moving to that page?
Upvotes: 2
Views: 292
Reputation: 1108632
As per the comment:
The browser shows x2 HTTP200 POSTs
That's thus 1 GET request as fully expected. Those POST requests can happen if you're firing some ajax request on load of the requested page. E.g., assuming PrimeFaces, with <p:outputPanel deferred="true">
, <p:remoteCommand autoRun="true">
, etc. Usually all related to lazy loading.
You can in the filter recognize POST requests by inspecting HttpServletRequest#getMethod()
.
if ("POST".equals(request.getMethod())) {
// It's a POST request.
}
Or, specifically JSF ajax requests by inspecting Faces-Request
header.
if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
// It's a JSF ajax request.
}
Unrelated to the concrete problem, you're not performing a PRG here at all. The <f:viewAction>
is by default only invoked on a GET request, not on a POST request (it only does that when you add onPostback="true"
). And, the <f:viewAction action>
behaves exactly the same as <h:commandButton action>
, including returning a navigation case outcome as usual (with the only difference that it's a GET, not a POST). So all that navigation handler and redirect mess is unnecessary.
public String newQuote() {
// ...
return "aboutYou.xhtml";
}
The navigation handler approach is only necessary if returning a String
outcome is not supported (like in <f:event type="preRenderView">
). The redirect is only necessary if the initial request is a POST request (like in <h:commandButton action>
or <f:viewAction onPostback="true">
).
Upvotes: 3