具有属性值的表达式语言的JSF 2自定义组件不会触发属性设置器

时间:2012-08-08 14:40:56

标签: jsf jsf-2 attributes custom-component

我在JSF 2.0中构建了一个自定义组件

标签如下所示:

<x:myTag id="1" name="AAA" />

对应的java类:

@FacesComponent("a.b.c.MyTag")
public class UIMyTag extends UIInput {

   private String name;
   private String id;

   public String getId() {
      return id;
   }

   public void setId(String id) {
       this.id = id;
   }


   public String getId() {
      return id;
   }

   public void setId(String id) {
       this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   @Override
   public void encodeBegin(FacesContext context) throws IOException {
       ResponseWriter writer = context.getResponseWriter();
       logger.debug(getName()); //prints null for name="#{dummyBean.name}" 
                                //   and AAA for name="AAA"
       logger.debug(getAttributes().get("name")); // always correct value
   ...
}
   ....

}

如果我使用

<x:myTag id="1" name="AAA" />

一切都按预期工作,但当我使用EL进行myTag属性时,setName()方法永远不会被调用。所以,

<x:myTag id="#{dummyBean.id}" name="#{dummyBean.name}" />

我总是在null方法中获取name属性encodeBegin。调试后我发现setName方法永远不会被调用。我认为关于EL的事情可能会让事情变得混乱(我仍然认为原因与此有关),但真正奇怪的是id属性运行良好:setter被调用,值为as在经济开始时预期。

我必须提一下,如果我从getAttributes().get("name")方法调用encodeBegin,我会得到正确的名称值,但我很感兴趣为什么它不适用于getter和setter。

我的组件缺少什么想法?

1 个答案:

答案 0 :(得分:12)

此行为是预期的并且符合规范。作为值表达式的属性值由UIComponent#setValueExpression()设置。它们应该仅在它们真正使用时才被评估,通常在视图渲染时间期间。

id(和binding)属性有特殊处理:在设置之前在视图构建时期间对其进行评估,因此将调用“常规”setter setValueExpression()的{​​{1}}(因为id(或binding)属性动态评估的值与视图构建时的值不同,因此视图的渲染会因某种原因而崩溃)

最好是将getter / setter委托给UIComponent#getStateHelper()而不是本地属性。 setValueExpression()最终也会在StateHelper中结束(请注意,它根本不会调用setter;只要在需要数据时调用getter),getAttributes()也会解析来自StateHelper

的值
public String getName() {
   return (String) getStateHelper().eval("name");
}

public void setName(String name) {
    getStateHelper().put("name", name);
}

请注意,您可以安全地删除 getId()setId()方法,因为它们已经在您正在扩展的UIComponentBase超类中定义