I tried simply:
public class UIDemoComponent extends UIComponentBase {
private String someVariable; // this gets always cleared, getters/setters omitted
public UIDemoComponent() {
super(); // place breakpoint here
}
@Override
public void encodeBegin(FacesContext context) throws IOException {
HtmlForm form = new HtmlForm();
form.setStyle("padding: 10px; background-color: blue;");
getChildren().add(form);
AjaxBehavior behavior = new AjaxBehavior();
behavior.setRender(Arrays.asList("@form"));
form.addClientBehavior("click", behavior);
}
}
I have registered a tag handler and succesfully inserted the component into page. However, when I click the blue form that is rendered, JSF re-creates the component (breakpoint in the constructor is caught). The effect of this is that any instance variables are lost. How is one supposed to save data into components if they always get re-created?
I tried overriding and inspecting the state staving mechanisms of StateHolder and PartialStateHolder wihout luck:
@Override
public Object saveState(FacesContext context) {
return super.saveState(context); // breakpoint
}
@Override
public void restoreState(FacesContext context, Object state) {
super.restoreState(context, state); // breakpoint
}
JSF is executing the saveState when page and components are created, but restoreState is never called. Actually, when the AJAX request is being processed, a new instamnce of UIDemoComponent is created but saveState method is called again, instead of restoreState.
How to create such a state-saving component (that retains the instance fields over AJAX requests)?
Seems like JSF is running some pre-checks on
stateobject and not executingrestoreStateat all if custom fields are not entered. Only after actually inserting custom values into state object, therestoreStategets called.For example:
After this, the
restoreStategets called and property fields can be restored as wanted.