On 5/4/06, Andrew Robinson <[EMAIL PROTECTED]> wrote:
I am going on a limb to answer this without first checking MyFaces
code and the spec, so feel free to correct any errors I am about to
post.

Gotta admire a guy willing to walk a tightrope with no net :-).

Calling render response on the faces context will not interrupt the
current phase, but instead just cause rendering to occur. According to
what I remember of the JSF spec, you need to call the
responseComplete() method of the context if you want to abort the
phase cycle of JSF. With that said, I know that will abort the phase
cycle, but I don't know if it will abort the current phase (execute
application or whatever it is called). You can give it a shot though:

public void actionListenerMethod(ActionEvent e) {
    //Shouldn't this bypass the action method???
    FacesContext.getCurrentInstance ().renderResponse();
    FacesContext.getCurrentInstance().responseComplete();
}

public String actionMethod() {
    return null;
}

(note, this is all from memory, so I may have the method name wrong
and its location)
-Andrew

Neither of these methods will *necessarily* accomplish what Matt is asking for, but it depends on when they are called.

Calling renderResponse() says "after the current phase is finished, go to Render Response phase next".  Calling responseComplete() says "I have already created the response, so as soon as this phase completes stop the lifecycle."  But, in both cases, you'll note that the current phase is finished first.  So, if you are already in Invoke Application phase, then the current phase is still going to get finished (but see below for a possible approach).  If you call either method in a phase *before* Invoke Application, then caling the application action should indeed be skipped.

So, how do we do what Matt wants?  To review, he wants to have an ActionListener that can dynamically decide to skip invoking the regular action method.  But action listeners are fired during Invoke Application phase, and as we've seen above, the rest of the phase (incuding the call to the action method, which is done by a default ActionListener instance provided by the JSF implementation) will still happen.  Here's two approaches to consider:

* Have your ActionListener throw AbortProcessingException, which
  is supposed to stop processing events for the current phase.

* Write your ActionListener set a flag in some well-known
  request scope attribute, and then write your own wrapper
  around the default ActionListener -- inside this class, check
  the state of the flag, and either delegate to the standard
  default action listener or not.

Craig



 

On 5/3/06, Matt Hughes <[EMAIL PROTECTED]> wrote:
> Is there any way to prevent an action method from being invoked from the
> action listener method?
>
> For example...take the following commandButton:
>
> <h:commandButton actionListener="#{backingBean.actionListenerMethod}"
> action="" value="Click Me" />
>
> And the matching methods in your backing bean:
>
> public void actionListenerMethod(ActionEvent e) {
>     //Shouldn't this bypass the action method???
>     FacesContext.getCurrentInstance ().renderResponse();
> }
>
> public String actionMethod() {
>     return null;
> }
>
>
> It was my understanding the *renderResponse()* would skip the context
> into the render response phase, and any action methods would be
> skipped.  In my tests, this is not true.  So...is there any way to
> prevent an action method from being invoked from within an action
> listener method?
>
>

Reply via email to