Tuesday, March 20, 2012

JSF 2 Navigation Pitfalls and Solutions

In this article I will present some cases where JSF 2 navigation will not work; in order the reader can avoid them.


JSF navigation works by first calling the action method (if defined), and from the outcome of the action, the JSF implementation decides which view to display. If there is no action method, a view id can be used directly (e.g.: "landingPage", the file name without extension).


1. Missing <h:form> tag


symptom: By pressing the button (or clicking the link), nothing happens. If there is a <h:messages> tag in the view, the following "cryptic" message is displayed: 


The form component needs to have a UIForm in its ancestry. Suggestion: enclose the necessary components within <h:form>


solution: Put the <h:commandButton> or <h:commandLink> inside a <h:form>
If the <h:commandButton> or <h:commandLink> component is outside of the <h:form>, or there is no <h:form> in the view, no form submit will be generated, so no navigation will occur (and the action method is also won't be called)


2. Missing EL brackets (#{})


Eclipse with JBoss Tools displays the action value with
underline and warning icon, if the EL brackets are missing




symptom: the page is redisplayed, but the action method is not called. If there is a <h:messages> tag in the view, the following error message appears: 


Unable to find matching navigation case with from-view-id '/navigation/page1.xhtml' for action 'navigation.navigateAction1()' with outcome 'navigation.navigateAction1()'


In this case, the button was defined as: 


<h:commandButton
            action="navigation.navigateAction1()"
            value="Missing EL brackets"
/>

solution: Put the action method reference between EL brackets.


note: In this case, the JSF implementation thinks, that what we defined as an action method, is a view id, but it doesn't find a file called "navigation.navigateAction1().xhtml".




3. "void" action method (navigation rule is defined in faces-config.xml)


symptom: The action method is called; page is redisplayed, but no navigation occur, no error message is displayed.


solution: change the action method to return anything (e.g.: a String)


This method:
// doesn't navigate because of void return value
public void doNotNavigateAction1() {
  logger.info("doNotNavigateAction1");
}
should be rewritten to return anything to enable navigation:

public String navigateAction1() {
  logger.info("navigateAction1");
  return "success";
}






4. action method returns null value

symptom: The action method is called; page is redisplayed, but no navigation occur, no error message is displayed.


solution: change the action method to return anything (e.g.: a String value), but not null.

note: This is by design, if the action method returns null, this means, that the previous page should be redisplayed.


No comments:

Post a Comment