I have figured out how to log when a request is an ajax request and which page it is from, in a filter.
What I would really like to do is log what the ajax request is actually for. Such as the name of the method being called by the ajax (eg "findAddress" in this call:<p:ajax process="contactDetails" update="@form" listener="#{aboutYouController.findAddress}" .... )
How can I do this? My app has many ajax requests and I want to log which are being triggered.
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;
    String pageHit = req.getRequestURI().substring(req.getContextPath().length()+1).replace(".xhtml", "");
    if(!pageHit.contains("javax.faces.resource")){ // if is a url we want to log
        if ("partial/ajax".equals(req.getHeader("Faces-Request"))) {
            LOG.trace("ajax on URI: " + req.getRequestURI());
        }
				
                        
This information is only available in the JSF component tree. The JSF component tree is only available after view build time. A view is only built when the request has been served by
FacesServlet. Thus, a servlet filter is way too early as it runs before any servlet.You'd better run the code after the restore view phase of a postback. The JSF component tree is guaranteed to be available during that moment. You can use
FacesContext#isPostback()to check if the current request is a postback. You can usePartialViewContext#isAjaxRequest()to check if the current request is an ajax request. You can use the predefinedjavax.faces.sourcerequest parameter to obtain the client ID of the source component of the ajax request. You can use the predefinedjavax.faces.behavior.eventrequest parameter to obtain the ajax event name (e.g.change,click,action, etc).Obtaining the associated behavior listeners is in turn a story apart. This is easy on
ActionSource2components (e.g.<h|p:commandButton action="#{...}">) as theMethodExpressionis just available byActionSource2#getActionExpression(). However, this isn't easy onBehaviorBasetaghandlers (e.g.<f|p:ajax listener="#{...}">) as this API doesn't have any method likegetBehaviorListeners(). There are only methods to add and remove them, but not to obtain a list of them. So some nasty reflection trickery is necessary to access theprivatefield with those listeners whose name is JSF implementation specific. In Mojarra it'slistenersand in MyFaces it's_behaviorListeners. Both are fortunately assignable fromListand it's the only field of that type, so we could just check for that. Once having hand of theBehaviorListenerinstance, then you still need to do another reflection trickery to obtain theMethodExpressionfield of that instance. Yuck.All in all, here's how the trickery look like in flavor of a
PhaseListenerlistening onafterPhaseofRESTORE_VIEW:In order to get it to run, register as below in
faces-config.xml:Above is tested and compatible with Mojarra and PrimeFaces and theoretically also compatible with MyFaces.
Update: in case you're using JSF utility library OmniFaces, or are open to, since version 2.4 you can use the new
Components#getCurrentActionSource()utility method to find out the current action source component andComponents#getActionExpressionsAndListeners()to get a list of all action methods and listeners registered on a given component. This is also useable on regular (non-ajax) requests. With that, the abovePhaseListenerexample can be reduced as below: