JSF 2.0如何创建状态节省的UIComponents?

时间:2010-12-03 08:54:49

标签: jsf jsf-2

我试过简单:

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);
    }
}

我已经注册了一个标签处理程序并成功将组件插入到页面中。但是,当我单击渲染的蓝色表单时,JSF重新创建组件(捕获构造函数中的断点)。这样做的结果是任何实例变量都会丢失。如果总是重新创建数据,应该如何将数据保存到组件中?

我尝试覆盖并检查StateHolderPartialStateHolder的状态存储机制,但运气不错:

@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正在执行saveState,但永远不会调用restoreState。实际上,当处理AJAX请求时,会创建一个新的UIDemoComponent实例,但saveState方法再次被称为,而不是restoreState

如何创建这样一个状态保存组件(通过AJAX请求保留实例字段)?

1 个答案:

答案 0 :(得分:3)

似乎JSF正在对state对象运行一些预检查,如果没有输入自定义字段,则根本不执行restoreState。只有在将自定义值实际插入状态对象后,才会调用restoreState

例如:

@Override
public Object saveState(FacesContext context) {
    Object[] rtrn = new Object[2];
    rtrn[0] = super.saveState(context);
    rtrn[1] = "dummy";
    return rtrn;
}

在此之后,调用restoreState并根据需要恢复属性字段。