2

JSF複合コンポーネントutil_primefaces:inplace_nameがあり、エンティティの「name」フィールドが編集されたときに永続性の更新を実行する「マネージャー」バッキングBeanが必要です(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).

[ASIDE:異常な「elid」属性の理由はここで説明されていますが、この質問ではそれ以上の役割はありません:Primefaces p:inplace:エンティティをマージするためのEL式をよりエレガントに伝播する方法]

明示的な#{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: com.example.web.BlockManager@71396a88.onInplaceNameSaveEvent(javax.faces.event.AjaxBehaviorEvent)
javax.el.MethodNotFoundException: Method not found: com.example.web.BlockManager@71396a88.onInplaceNameSaveEvent(javax.faces.event.AjaxBehaviorEvent)
at com.sun.el.util.ReflectionUtil.getMethod(ReflectionUtil.java:155) 

Q:複合コンポーネント属性でdefault = "#{blockManager}"を使用すると、バッキングBeanが正しく取得されないのはなぜですか?

4

1 に答える 1

5

タグのドキュメントにcc:attributeよると、の値はにdefault評価される必要がありjava.lang.Stringます。

そのため、#{blockManager}式が期待どおりに機能せず、String属性のデフォルトを設定することしかできません。

何が起こるかを確認するには、次の関数をtaglibに登録してテストできます(ここに示すように)。

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 />

...デフォルトの属性であるStringにclass java.lang.StringValueExpressionの結果を使用するため、出力されます。"1"

そして、paramを指定すると:

<my:comp param="1" />

...出力します。これclass java.lang.Integerは、に指定された型に強制変換した結果の値cc:attributeです。

于 2012-07-22T02:55:15.957 に答える