Getters inside f:verbatim called before form submi

2019-01-27 03:30发布

问题:

I have the following page:

<h:form id="gameSelectionForm">
    <h:selectOneMenu id="gameSelection">
        <f:selectItems value="#{gameBean.gameIds}" />
    </h:selectOneMenu>
    <h:commandButton id="gameSelector" value="Play" action="#{gameBean.changeGame}"  />
</h:form>

<h:panelGroup id="gameDiv">
    <f:verbatim>
        <iframe src="/levelup/resources/games/#{gameBean.gameId}/#{gameBean.htmlPage}"  width="700px" height="800px" frameborder="0"/>
    </f:verbatim>
</h:panelGroup>

When I click on the "gameSelector" button, here is the sequence of events: 1. gameBean.getGameId and gameBean.getHtmlPage are called 2. gameBean.changeGame is called 3. The page is refreshed.

My issues lies in the order of 1. and 2. The changeGame modifies a gameBean variable that is used by the getGameId and getHtmlPage. I thus want to it execute first, so that when other panels are refreshed, they contain the proper data.

Please note that this issue seems to occur only for the call within the gameDiv element (other variables are properly refreshed).

Would you have any idea as to what I could do to revert the order of 1. and 2., so that the changeGame() method is the first one called?

I am using JavaServer Faces 2.0 on Tomcat 7.0.

Thanks in advance

回答1:

As per your own answer on this topic:

I removed the f:verbatim tag, and now it works properly. I still don't understand why it has caused this behaviour though.

The <f:verbatim> was introduced in JSF 1.0 a long time back with the sole purpose to be able to include plain HTML in the JSF component tree. On JSF 1.0 (and 1.1), when the component tree get built, all the plain HTML was ignored. The page get rendered with all the plain HTML first and then the rendered HTML of JSF components thereafter. So for example

<p>Hello</p>
<h:inputText />
<p>World</p>
<h:outputText value="outputtext" />
<p>This is weird</p>

get rendered as

<p>Hello</p>
<p>World</p>
<p>This is weird</p>
<input type="text" />
outputtext    

The <f:verbatim> allowed developers to take plain HTML into the JSF component tree, so that they get rendered "in sync" as you'd expect from the coding.

<f:verbatim><p>Hello</p></f:verbatim>
<h:inputText />
<f:verbatim><p>World</p></f:verbatim>
<h:outputText value="outputtext" />
<f:verbatim><p>This is weird</p></f:verbatim>

They however get inlined during view build time, not during view render time. This is the cause of your problem, the getters get invoked during restore view phase instead of render response phase.

Since JSF 1.2, with the improved view handler, it was possible to inline plain HTML "in sync" without hassling with ugly <f:verbatim> tags. So it's not needed anymore. There are also no useful use cases for the tag anymore, expect of possibly some premature performance optimizations, but still then, you should not use it in combination with dynamic data as obtained by Expression Language.

Related questions:

  • (Dis)advantages of JSF 2.0


回答2:

Put an immediate attribute set to true on the commandButton.

<h:commandButton id="gameSelector" value="Play" action="#{gameBean.changeGame}" immediate="true" />

It will execute the method in the ApplyRequestValues phase then.



回答3:

I removed the f:verbatim tag, and now it works properly. I still don't understand why it has caused this behaviour though.