So, the phase execution is now corrected in TabSet, it just has to be committed, but this is the analysis of the continuance of the bad symptoms even after the code fix.
I modified the basic application to use this view definition:
<f:phaseListener
type="org.icefaces.demo.basic.InputPhaseListener"/>
<h:form id="myform">
<h:inputText id="myinput" value="#
{basic.input}
"/>
<h:commandButton id="mybutton" immediate="true" actionListener="#
{basic.actionListener}
"/>
<h:panelGroup id="mygroup">
<h:messages id="mymessages"/>
</h:panelGroup>
</h:form>
and this bean code:
public void actionListener(ActionEvent event)
{
System.out.println("Basic.actionListener " + FacesContext.getCurrentInstance().getCurrentPhaseId());
}
public void setInput(String input)
{
System.out.println("Basic.setInput " + FacesContext.getCurrentInstance().getCurrentPhaseId() + " old: " + this.input + " new: " + input);
this.input = input;
}
public String getInput()
{
System.out.println("Basic.getInput " + input);
return input;
}
private String input;
and this InputPhaseListener:
public class InputPhaseListener implements PhaseListener {
public void afterPhase(PhaseEvent phaseEvent)
{
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("recursivelyPrintInputs() " + context.getCurrentPhaseId() + " AFTER");
recursivelyPrintInputs(context.getViewRoot());
}
public void beforePhase(PhaseEvent phaseEvent)
{
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("recursivelyPrintInputs() " + context.getCurrentPhaseId() + " BEFORE");
recursivelyPrintInputs(context.getViewRoot());
}
public PhaseId getPhaseId()
{
return PhaseId.ANY_PHASE;
}
private static void recursivelyPrintInputs(UIComponent comp) {
if (comp == null)
{
System.out.println("recursivelyPrintInputs() comp is null");
return;
}
if (comp instanceof javax.faces.component.UIInput)
{
printInputs((javax.faces.component.UIInput)comp);
}
for (Iterator<UIComponent> it = comp.getFacetsAndChildren(); it.hasNext()
{
UIComponent kid = it.next();
recursivelyPrintInputs(kid);
}
}
private static void printInputs(javax.faces.component.UIInput comp)
{
System.out.println("printInputs() clientId: " + comp.getClientId());
System.out.println("printInputs() submittedValue: " + comp.getSubmittedValue());
System.out.println("printInputs() localValueSet: " + comp.isLocalValueSet());
System.out.println("printInputs() localValue: " + comp.getLocalValue());
System.out.println("printInputs() value: " + comp.getValue());
}
}
With all that, I tested the icefaces page and non-icefaces page, and the non-icefaces page with icefaces removed for a pure stock JSF scenario. In all of them, the phase listener showed that the inputText loses it's submittedValue in-between lifecycles. Auditing UIInput source shows that submittedValue is treated differently than all other fields, where is it specifically excluded from the StateHelper state saving mechanism.
So the conclusion is that it's not tabSet's fault, when an input component loses it's submittedValue, when it does a renderResponse() after decode, which happens when immediate="true" and cancelOnInvalid="true".
Looked at test page annTabset.xhtml and note that the checkboxButton is losing it's state, but exact same markup on PnlTabset.xhtml (which uses compat tabset) does not.