Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JSF 2.0 / Facelets, is there a way to attach a global listener to all AJAX calls?

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!

like image 486
Jonathan S. Fisher Avatar asked Feb 16 '12 03:02

Jonathan S. Fisher


People also ask

Which tag is useful for enabling ajax in a Facelet web page?

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.

What is jsf ajax?

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.

What is the tag for ajax support in JSF?

JavaServer Faces (JSF) JSF provides execellent support for making ajax call. It provides f:ajax tag to handle ajax calls.

What is an ajax listener?

<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">


1 Answers

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);
like image 187
BalusC Avatar answered Oct 24 '22 14:10

BalusC