JSF 复合组件支持 bean EL 表达式作为必需属性的默认值失败,方法未知

标签 jsf jsf-2 default composite-component

我有一个 JSF 复合组件 util_primefaces:inplace_name ,它需要一个“manager”支持 bean,它在编辑实体的“name”字段时执行持久性更新(使用 p:inplace):

<cc:interface>
  <cc:attribute name="manager" type="com.example.web.AbstractManager" required="false" default="#{blockManager}"/>
  <cc:attribute name="element" type="com.example.entity.Element" required="true"/>
  <cc:attribute name="elid" required="true"/>
  <cc:attribute name="update" required="false" default="@parent"/>
 ..
</cc:interface>

<cc:implementation>
 ..
 <p:inplace id="#{cc.attrs.elid}" editor="true" emptyLabel="UNDEF" >
  <p:ajax 
   event="save" 
   listener="#{cc.attrs.manager.onInplaceNameSaveEvent}"
   process="@this #{cc.attrs.elid}-name"
   update="#{cc.attrs.update}"
  />
 <h:inputText id="#{cc.attrs.elid}-name" value="#{cc.attrs.element.name}"/>
 ..

例如@ViewScoped @ManagedBean BlockManager最终扩展了一个AbstractManager,它有一个监听器方法:

public void onInplaceNameSaveEvent(AjaxBehaviorEvent ae).

[旁白:这里描述了不寻常的“elid”属性的原因,它在这个问题中没有发挥进一步的作用:Primefaces p:inplace: How to more elegantly propagate the EL expression for entity to merge ]

当我调用传入显式 #{blockManager} (或 AbstractManager 的其他子类)的复合组件时,它工作正常:

<util_primefaces:inplace_name 
 element="#{tenancy}" 
 elid="tenancy"
 manager="#{blockManager}"
/>

但是,如果我不传入 #{blockManager},则在执行就地编辑和保存时会收到一条错误,指出 onInplaceNameSaveEvent(AjaxBehaviorEvent) 方法未知:

<util_primefaces:inplace_name 
 element="#{tenancy}" 
 elid="tenancy"
/>

错误是:

WARNING: Method not found: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cfaca0a2e1aab7aea2bfa3aae1b8aaade18da3a0aca482aea1aea8aabd8ff8fefcf6f9aef7f7e1a0a186a1bfa3aeacaa81aea2aa9caeb9aa8ab9aaa1bb" rel="noreferrer noopener nofollow">[email protected]</a>(javax.faces.event.AjaxBehaviorEvent)
javax.el.MethodNotFoundException: Method not found: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0a696567246f726b677a666f247d6f68244866656961476b646b6d6f784a3d3b39333c6b323224656443647a666b696f446b676f596b7c6f4f7c6f647e" rel="noreferrer noopener nofollow">[email protected]</a>(javax.faces.event.AjaxBehaviorEvent)
at com.sun.el.util.ReflectionUtil.getMethod(ReflectionUtil.java:155) 

问:为什么在复合组件属性中使用 default="#{blockManager}"时没有正确获取支持 bean?

最佳答案

根据the documentation for the tag cc:attributedefault 的值必须计算为 java.lang.String

这就是为什么 #{blockManager} 表达式无法按您的预期工作,您只能为 String 属性设置默认值。

要查看会发生什么,您可以测试在标记库 ( like showed here ) 中注册以下函数:

public static String typeOf(Object o) {
    return o == null ? null : o.getClass().toString();
}

并在复合组件中使用它,如下所示:

<ui:composition>
    <cc:interface>
        <cc:attribute name="param" type="java.lang.Integer" required="true"
            default="1" />
    </cc:interface>
    <cc:implementation>
        <h:outputText value="#{fnc:typeOf(cc.attrs.param)}" />
    </cc:implementation>
</ui:composition>

现在,如果您在不指定 param 的情况下使用该组件,如下所示:

<my:comp />

...它将输出class java.lang.String,因为它使用ValueExpression的结果作为default属性,即String “1”

当您指定参数时:

<my:comp param="1" />

...它输出class java.lang.Integer,因为现在它是强制转换为cc:attribute指定的类型所产生的值。

关于JSF 复合组件支持 bean EL 表达式作为必需属性的默认值失败,方法未知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11596470/

相关文章:

java - 在 JBoss Seam 中修剪输入

windows - java.io.IOException : Not in GZIP format Exception

c# - 用默认文本替换空值

c++ - 下标 [] 运算符的默认值?

html - form 和 div html 元素的默认 css 参数

java - 在 JSF 1.2 中使用动态生成的包

java - 如何在 Java EE 上使用 Hibernate、C3P0 处理数据库连接失败?

java - 关于servlet的正确使用方法的问题

java - 无法刷新注入(inject)到 JSF 2 Managed Bean 中的 JPA 2 实体

css - 我怎样才能使禁用的字段变灰?