JSF PhaseListeners: Underestimated from day one

JSF’s lifecycle is well defined and the developer takes the stand usually at invoke application phase where the button actions are handled. However using the underestimated powers of phase listeners one can play with the strict lifecycle. A Phaselistener reminds me an around advice, because it has both an after and before phase method that is executed in order. You can do whatever you want to do before and after each phase, it depends on your imagination but my favorite place to use a phaselistener is after restore view. After restore view, here is the possible use cases that I can think of, feel free to add one if you have;

Handle ajax requests.
 In one of my entries I implemented a simple application using both a servlet and a phaselistener in order to compare them. Here is the example showing how to use a phaselistener to enable ajax.

Serve resources like javascript or style sheet files from a single jar file.
 From a component developer’s point of view, phaselisteners have a great value, first thing is that the resources like .js and .css can live in the distribution jar file, and a phaselistener can register itself to the context. That means an all in one jar file can be used. This reminds me the cool ExtensionsFilter of myFaces. A phaselistener could be used instead of a filter or a servlet without requiring user configuration since it is pluggable.

Use like a servlet.
 Here is an example from me, I am planning to use a phaselistener instead of a servlet in my chart component because people who use it must define the servlet class in their web.xml’s. Instead a phaselistener can register itself to the context and  after the restore view phase, by changing the response type, a response like an image or an xml file can be rendered.

All needed to be done is to take the attention of the faces servlet, this is needed to start the lifecycle and it is as simple as using a prefix(/faces/*) and a special view id name for you to realize whether the request is a regular faces request or one of what you are looking for. Here is a simple example;
   
public class UnderestimatedPhaseListener implements PhaseListener {

    private static final String AJAX_SCRIPT = “ajax-script”;
   
    private static final String AJAX_VIEW_ID = “ajax-view”;
   
    private static final String CREATE_CHART_IMAGE = “create-chart-image”;
   
    public void afterPhase(PhaseEvent event) {
        String rootId = event.getFacesContext().getViewRoot().getViewId();
        if (rootId.indexOf(AJAX_VIEW_ID) !=-1)
            // Handle Ajax Request
        else if(rootId.indexOf(AJAX_SCRIPT) !=-1)
            // Serve the script file from jar
        else if(rootId.indexOf(CREATE_CHART_IMAGE) !=-1)
            // Just create a chart image
    }

    public void beforePhase(PhaseEvent arg0) {
          // Do nothing
    }

    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }
}

In each of the three cases responseComplete() of facesContext must be called in order to cut the lifecycle and prevent it from going further. So the answer to the question: Is there life after a phaselistener is no in this case. For the first two, Bpcatalog provides an excellent example of using a phaselistener to enable ajax in jsf, here is a more detailed jsf-ajax explanation from bpcatalog if you want to go further. The third is my idea, never tested it for now but changing the response type and copying some code from the chart servlet will do the work. I still guess there is more that can be done with phaselisteners, as I mentioned before, it depends only on the developers imagination. For example, this just hit me now, by checking the request parameters, one can understand which component caused a postback and use this information before apply request values and etc.etc.etc.

3 Responses to JSF PhaseListeners: Underestimated from day one

  1. Hi Cagatay,

    first nice blog, I like to read it!
    Your *third* option is an interesting one, since option 1 and two are *common* use cases (for now ;))

    An very more interesting plus would be (not looked at your chart component) to have an attribute for your component (lets say chartData) with you can combine with a MethodBinding to your backing bean.

    Some thing like:
    chartData=”#{bean.provideSomeData}”

    Now your PhaseListener can execute that method and use its return value to *generate* the graphic. For this use case, you must submit the state (stored in hidden fields) also during your ajax request. MyFaces’ Ajax Input Suggest Component does this already.

    The negative is (speaking in JSF 1.1) the name of hidden field is not part of the sepc. So your impl is specific to the JSF impl of your choice. JSF 1.2 make it more easier, since the spec contains some more information regarding this

    PhaseListeners are great for developers, YES!

    I wrote a PhaseListener to invoke the Dialog facility of Shale instead of *pressing* a commandButton or commandLink component.

    Keep on blogging
    Matthias

%d bloggers like this: