17

I'm currently experiencing a problem with JSF's order of execution.

Looking at my sample code:

<p:commandButton action="update.xhtml" ajax="false"
                        icon="ui-icon-pencil"
                        actionListener="#{marketingCodeBean.initForUpdate}">
    <f:setPropertyActionListener
        target="#{marketingCodeBean.marketingCode}" value="#{code}"></f:setPropertyActionListener>
</p:commandButton>

I would like to set a bean property using setPropertyActionListener, and do some processing on actionListener=initForUpdate. But JSF default sequence of execution is the opposite, actionListener first before setPropertyActionListener. Is there a clean work around for this problem?

I'm thinking of having an actionListener and pass the bean parameter to it, but I'm not sure if that is the best approach.

czetsuya
  • 4,773
  • 13
  • 53
  • 99

1 Answers1

33

That's indeed expected behaviour. The action listeners (actionListener, <f:actionListener> and <f:setPropertyActionListener>) are all invoked in the order they're registered on the component, with the actionListener attribute first. It's not possible to change the ordering this way other than adding the method behind actionListener as a <f:actionListener> (which should refer a concrete implementation class of ActionListener interface).

<p:commandButton ...>
    <f:setPropertyActionListener target="#{marketingCodeBean.marketingCode}" value="#{code}" />
    <f:actionListener type="com.example.InitForUpdate" />
</p:commandButton>

Better is to just use action instead of actionListener. It's invoked after all action listeners. Action listeners are intented to "prepare" an action and using them for business actions is actually poor practice.

<p:commandButton ... action="#{marketingCodeBean.initForUpdate}">
    <f:setPropertyActionListener target="#{marketingCodeBean.marketingCode}" value="#{code}" />
</p:commandButton>

with

public String initForUpdate() {
    // ...

    return "update.xhtml";
}

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I thought of f:actionListener approach too but felt like that is not what I really needed. So I'll go to the actionListener->action approach as you have suggested. Once again thank you :-). – czetsuya Jan 05 '13 at 03:59
  • I have implemented a similar work using `action` in `p:dataTable` but `f:setPropertyActionListener` is always taking the object data of the first row of the table even when I click button on other rows. How to get the data of clicked row ?? – SudeepShakya Feb 25 '15 at 09:23
  • @Sudeep: You're searching in the wrong question. Move on to http://stackoverflow.com/q/4994458/ – BalusC Feb 25 '15 at 17:44
  • Using ajax listener to remove an element after a user Query and the user Query pops up again when inserting a new dataset to ui:repeat, cause the setPropertyAL is not called when removing the parent container (not sure why) how can one work around all these JSF limitations? – mondjunge Dec 01 '16 at 11:49