【问题标题】:JSF 2 Custom components having Expression Language for attribute value don't trigger the attribute setter具有属性值表达式语言的 JSF 2 自定义组件不会触发属性设置器
【发布时间】:2012-08-05 17:00:11
【问题描述】:

我已经在 J​​SF 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}" />

我的encodeBegin 方法中的name 属性总是得到null。调试后我注意到setName 方法永远不会被调用。我认为可能与 EL 有关的某些事情会搞砸(我仍然相信原因与此有关),但真正奇怪的是 id 属性工作得很好:setter 被调用,并且值符合预期开始。

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

任何想法我的组件缺少什么?

【问题讨论】:

    标签: jsf jsf-2 attributes custom-component


    【解决方案1】:

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

    id(和binding)属性有特殊处理:在视图构建期间评估它在设置之前,因此将调用“常规”设置器而不是@987654326 @(因为由于某种原因,当 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 超类中定义。

    【讨论】:

    • 感谢您的回答!我想问我是否必须实现一些特殊的方法来区分组件内不同类型的属性值。 (我知道 UIComponentBase 自己处理它)如果是,是否有最佳实践?!
    • 不,您通常也不应该关心它。要获取(评估的)属性值,只需调用 getter。
    猜你喜欢
    • 1970-01-01
    • 2011-08-02
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 2013-08-18
    • 2011-08-23
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多