我有一个 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:attribute
,default
的值必须计算为 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/