Is there a way to attach a global listener to all AJAX calls in JSF? Maybe through a phase listener or something?
Here is the conundrum... Lets say you're using f:ajax tags and something like apache shiro and you let your session expire. Then you come back and click a button that has an f:ajax attached to it. The server will respond with a 302 redirect to the login page.
The user sees nothing. They can repeatedly click and invoke the ajax call, but to them the app is just "dead."
So, my though is, is there a way to attach a listener to all ajax calls in JSF? If so, what I'd like to do is monitoring the response code. If it's a redirect, use a window.navigate to send them along their way.
I'm always open to hear how others have solved this problem!
By using the f:ajax tag along with another standard component in a Facelets application. This method adds Ajax functionality to any UI component without additional coding and configuration.
It is a technique to use HTTPXMLObject of JavaScript to send data to server and receive data from server asynchronously. In Ajax, Javascript code exchanges data with server, updates parts of web page without reloading the whole page. JSF supports for Ajax call with f:ajax tag.
JavaServer Faces (JSF) JSF provides execellent support for making ajax call. It provides f:ajax tag to handle ajax calls.
<p:inputText id="counter" value="#{listenerBean.text}" placeholder="Enter Text"> <p:ajax event="keyup" update="out" listener="#{listenerBean.ajaxEvent()}" /> </p:inputText> </h:panelGrid> <h:panelGrid id="out">
Is there a way to attach a global listener to all AJAX calls in JSF? Maybe through a phase listener or something?
Yes, a PhaseListener
can do it. A SystemEventListener
also. A Filter
also.
If you're inside JSF context, then you can check as follows whether the current request is an ajax request or not.
if (FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest()) {
// It's an ajax request.
}
If you're not inside JSF context, e.g. inside a Filter
, then you can check as follows whether the current request is a JSF ajax request or not.
if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
// It's a JSF ajax request.
}
Here is the conundrum... Lets say you're using f:ajax tags and something like apache shiro and you let your session expire. Then you come back and click a button that has an f:ajax attached to it. The server will respond with a 302 redirect to the login page.
The user sees nothing. They can repeatedly click and invoke the ajax call, but to them the app is just "dead."
Forcing a redirect on an ajax request requires a special XML response. When you're inside JSF context, then ExternalContext#redirect()
already takes this implicitly into account. All you need to do is to write this:
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
If you're not inside JSF context, e.g. inside a Filter
, then you'd need to write the whole XML response yourself. E.g.
response.setContentType("text/xml");
response.getWriter()
.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
.printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", url);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With