You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Matt Hughes <mh...@chariotsolutions.com> on 2006/05/03 22:20:06 UTC

ActionListeners and Actions

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="#{backingBean.actionMethod}" 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?


Re: ActionListeners and Actions

Posted by Andrew Robinson <an...@gmail.com>.
Could this be done with a custom application listener of the faces
context? I am too familiar with the spec at that level, but it seems
to be the one in controlling the invoking of the action method? If so,
there could be a custom listener written that has an abort boolean
property or something of the sort, that if set to true will not invoke
the action?

-Andrew

On 5/4/06, Mike Kienenberger <mk...@gmail.com> wrote:
> On 5/4/06, Andrew Robinson <an...@gmail.com> 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.
> >
> > 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:
>
> Andrew, I was thinking the same thing.   However, I don't think either
> method aborts the current phase.  It merely prevents any future phases
> from executing.
>
> responseComplete() actually means you've already "drawn" a response
> page.   renderResponse does mean what you're saying, which is to skip
> to the render response phase.
>
> Matt,  I think your best bet is to look at the LifeCycleImpl code and
> see what goes on when renderResponse is true.   I know it kills any
> pending events, and you probably can use similar code to kill your
> existing action event.    The other thing you can do is have your
> action listener set a flag somewhere, and then have your action take a
> look at the value of that flag when it starts up.
>

Re: ActionListeners and Actions

Posted by Mike Kienenberger <mk...@gmail.com>.
On 5/4/06, Andrew Robinson <an...@gmail.com> 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.
>
> 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:

Andrew, I was thinking the same thing.   However, I don't think either
method aborts the current phase.  It merely prevents any future phases
from executing.

responseComplete() actually means you've already "drawn" a response
page.   renderResponse does mean what you're saying, which is to skip
to the render response phase.

Matt,  I think your best bet is to look at the LifeCycleImpl code and
see what goes on when renderResponse is true.   I know it kills any
pending events, and you probably can use similar code to kill your
existing action event.    The other thing you can do is have your
action listener set a flag somewhere, and then have your action take a
look at the value of that flag when it starts up.

Re: ActionListeners and Actions

Posted by Craig McClanahan <cr...@apache.org>.
On 5/4/06, Andrew Robinson <an...@gmail.com> 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 <mh...@chariotsolutions.com> 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="#{backingBean.actionMethod}" 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?
> >
> >
>

Re: ActionListeners and Actions

Posted by Andrew Robinson <an...@gmail.com>.
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.

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

On 5/3/06, Matt Hughes <mh...@chariotsolutions.com> 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="#{backingBean.actionMethod}" 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?
>
>