I have put my problem case below, which simplifies a real world problem I am having. By changing the Bean to @SessionScoped I can solve this, but that is really undesirable. As is @ViewScoped. I think it should work in @RequestScoped. My questions are:
- Why does JSF need access to
#{simpleBean.outerStrings}
to invoke the#{simpleBean.processInnerClick()}
listener (outerStrings will have died in the previous request) - What is the best pattern for solving this?
Happy to edit to make clearer - just let me know.
Bean class
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
@Named
@RequestScoped
public class SimpleBean implements Serializable {
private List<String> topLevelStrings =
Arrays.asList("TopLevel1", "TopLevel2");
private List<String> outerStrings;
private List<String> innerStrings;
public void processOuterClick() {
System.err.println("processOuterClick()");
outerStrings = Arrays.asList("Outer1", "Outer2", "Outer3");
}
public void processInnerClick() {
System.err.println("processInnerClick()");
innerStrings = Arrays.asList("InnerA", "InnerB", "InnerC");
}
public List<String> getOuterStrings() {
return outerStrings;
}
public List<String> getInnerStrings() {
return innerStrings;
}
public List<String> getTopLevelStrings() {
return topLevelStrings;
}
}
XHTML
<h:form>
<ui:repeat var="toplevel" value="#{simpleBean.topLevelStrings}"
id="toplevel_id">
<h:commandLink id="toplevel_command">
#{toplevel} <br/>
<f:ajax render="outerlevel_panel"
listener="#{simpleBean.processOuterClick()}"/>
</h:commandLink>
<h:panelGroup id="outerlevel_panel">
<ui:repeat var="outerLevel" value="#{simpleBean.outerStrings}"
id="outerlevel_id">
<h:commandLink id="outerlevel_command">
#{outerLevel} <br/>
<f:ajax listener="#{simpleBean.processInnerClick()}" render="innerlevel_panel"/>
</h:commandLink>
<h:panelGroup id="innerlevel_panel">
<ui:repeat var="innerLevel" value="#{simpleBean.innerStrings}"
id="innerlevel_id">
<h:commandLink id="innerlevel_command">
#{innerLevel} <br/>
</h:commandLink>
</ui:repeat>
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</ui:repeat>
</h:form>
Basically:
- The
#{simpleBean.processOuterClick()}
listener fires ok and the #{outerLevel} command links render - But when I click on the
#{outerLevel}
command Link the#{simpleBean.processInnerClick()}
listener is never fired