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

后端 未结 2 458
情深已故
情深已故 2020-11-30 09:21

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:a

2条回答
  •  南笙
    南笙 (楼主)
    2020-11-30 09:40

    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("")
        .printf("", url);
    

提交回复
热议问题