The JSF navigation handler has some implicit rules that cause the same view to be displayed again after processing a post back. For example if a JSP a.jsp executes an action #{controllerBean.actionMethod} and no explicit navigationrule is matching either the action or an outcome, then the navigation handler will display a.jsp again. This is convenient as no navigation rules have to be coded. On top of that JSF has a built-in behaviour to keep form input values for a previous post if the view id remains unchanged (which is the case here!). To be more specific: if submitted data is available it is displayed otherwise the values of properties bound to a backing bean are displayed (submitted data is only reset when an explicit navigation rule is executed!) This feature is required for supporting the JSF form validation mechanisms. If any form validator reports a validation error, the ooriginating form will rdisplay the form with the values as they were entered before.

However this can get tricky for some special occasions. Next I will describe such a scenario in which this is causing troubles:

I was trying to implement a simple table for selecting a table row and editing the selected row in a form in a different way than I did it before. Table and form are rendered through the same JSP (see below) such that no navigation rules are required. This does not behave as expected-> when a row is selected, its data is shown in the form. After returning back to the table and selecting a different row, the form shows the same row data as before BUT NOT the data for the new selection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<tr:form>
        <tr:table value="#{listController.model}" var="object"
                rendered="#{formController.entity==null}">
                <tr:column>
                        <tr:commandLink action="#{listController.select}">
                                <tr:outputText value="#{object.type}" />
                        </tr:commandLink>
                </tr:column>
        </tr:table>
        <tr:panelFormLayout rendered="#{formController.entity!=null}">
                <tr:outputLabel for="typeInput" value="Type" />
                <tr:inputText id="typeInput" value="#{formController.entity.type}" />
                <tr:commandButton text="OK" action="#{formController.store}" id="okButton" />
                <tr:commandButton text="CANCEL" action="#{formController.cancel}" immediate="true" />
        </tr:panelFormLayout>
</tr:form>

listController.select is implemented like shown below

1
2
3
4
public String select() {
  setSelectedEntity((T) getDataModel().getRowData());// this injects the selected object into the form controller
  return OUTCOME_SELECT;
}

So considering the above described JSF behaviour a navigation rule must be added in order to get this working

1
2
3
4
5
6
<navigation-rule>
  <from-view-id>/experimental/listformcontroller.jsp</from-view-id>
  <navigation-case>
      <to-view-id>/experimental/listformcontroller.jsp</to-view-id>
  </navigation-case>
</navigation-rule>

Comments