如何在复合组件的支持组件中保存自定义属性的状态?

时间:2011-12-14 14:36:11

标签: jsf jsf-2 composite-component

我创建了一个带有支持组件类的简单复合组件。我想保存这个类的某些属性的状态。因此,我在属性的setter / getter中使用StateHelper。从我的角度来看,如果组件是从UINamingContainer派生的,那么就需要做的就是让JSF保存和恢复状态。

不幸的是,这不能按预期工作。有一个调试语句,应该在访问时将组件的状态打印到控制台。我希望在重新输入页面时(通过导航)恢复状态,但状态总是被解析为null。

示例代码:

@FacesComponent("myComponent")
public class MyComponent extends UINamingContainer {

enum PropertyKeys {selected}

public void selectionListener(final AjaxBehaviorEvent event) {
             ...
    // do some stuff here

}

public void setSelected(final Collection<Integer> selected) {

    getStateHelper().put(PropertyKeys.selected, selected);

}

public Collection<Integer> getSelected() {
    Collection<Integer> state = (Collection<Integer>) getStateHelper().eval(PropertyKeys.selected);

    System.out.println("State: "+state);

    return state;
}

在请求期间保存复合组件的状态还需要做些什么?在这种情况下,我想提供一个复合组件,它封装了具有行选择功能的多个表。我希望在组件内的请求期间保存选定的行,而不是绑定到托管bean。

在这种特殊情况下,复合组件中会有很多可选择的表,我希望复合组件本身能够跟踪选择,因此复合组件用户不需要处理多个选择属性。


更新:我创建了一个简单的示例:

支持课程:

@FacesComponent("StateSavinComponent")
public class StateSavingComponent extends UINamingContainer{

    private String someText;

    private Object[] state;

    @Override
    public Object saveState(final FacesContext context) {
        if (state == null) {
            state = new Object[2];
        }

        state[0] = super.saveState(context);
        state[1] = someText;
        return state;
    }

    @Override
    public void restoreState(final FacesContext context, final Object state) {
        this.state = (Object[]) state;
        super.restoreState(context, this.state[0]);
        someText =  (String) this.state[1];
    }

    public void setSomeText(final String someText) {
        this.someText = someText;
    }

    public String getSomeText() {
        return someText;
    }

}

复合组件:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:ui="http://java.sun.com/jsf/facelets" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:cc="http://java.sun.com/jsf/composite">

    <cc:interface componentType="StateSavinComponent">

    </cc:interface>   

    <cc:implementation>

        <h:inputText value="#{cc.someText}" />

    </cc:implementation>

</html>

第一页:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:ui="http://java.sun.com/jsf/facelets" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:example="http://java.sun.com/jsf/composite/example">

<h:head>

</h:head>
<h:body>

    <h:form id="form">

        <example:stateSaving/>      

        <h:commandButton action="page2.xhtml" value="next" />

    </h:form>

</h:body>

</html>

第二页:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:ui="http://java.sun.com/jsf/facelets" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:f="http://java.sun.com/jsf/core">

<h:head>

</h:head>
<h:body>

    <h:form id="form">

            <h:commandButton action="example.xhtml" value="back" />

    </h:form>

</h:body>

</html>
  1. 文本字段中的输入值
  2. 导航至page2.xhtml
  3. 导航回example.xhtml
  4. 输入字段为空,但应包含先前输入的值
  5. 在支持类中设置断点
  6. saveState和restoreState似乎以错误的顺序调用

0 个答案:

没有答案