3

私は、(通常はクライアント固有の) コードによって拡張できるコアコンポーネントで構成される JSF 2 アプリケーションに取り組んでいます。一般的に言えば、アプリケーションの拡張部分はコア部分よりも優先されます。

Java コードの場合、これは従来のメカニズムを使用して行われます。プレゼンテーション レイヤーでは、コアリソースが使用される前にまず拡張jarjavax.faces.view.facelets.ResourceResolver内のリソースを見つけようとする実装を使用します。

再利用可能なマークアップのために、多くの複合コンポーネントを使用しています。住所、給与などを表示するためのコンポーネントを考えてみてください。

Facelets は、アプリケーションの拡張可能な性質に関して大きな頭痛の種を引き起こしています。私たちが直面している問題の解決策があるかどうか疑問に思い始めています。

私たちが達成したいのは、複合コンポーネントの標準インターフェースを持つことですが、複数の implementationを解決することによって、何らかの方法で実装をオーバーライドします。そのうちの拡張された実装は、コアの実装に先行する必要があります。

もちろん、コアはアプリケーションの標準レイアウト/テンプレートを定義し、拡張機能はクライアント固有の書式設定オプションを定義するか、アプリケーションが実行するマネージド モデルの一部を非表示/表示するという考え方です。

例えば:

<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:cc="http://java.sun.com/jsf/composite"
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:pui="http://java.sun.com/jsf/composite/pui">

    <cc:interface>
        <cc:attribute name="saveButtonLabel" />
        <cc:attribute name="saveButtonIcon" />
        <cc:attribute name="saveButtonIconPosition" />
    </cc:interface>

    <cc:implementation>
        <pui:pension_plan_custom_state pensionPlanBean="#{pensionPlanBean}" />
        <pui:pension_plan_general pensionPlanBean="#{pensionPlanBean}" />
        <pui:pension_plan_pension_plan pensionPlanBean="#{pensionPlanBean}" />
        <pui:pension_plan_salary pensionPlanBean="#{pensionPlanBean}" />
        <pui:pension_plan_investments pensionPlanBean="#{pensionPlanBean}" />
        <pui:pension_plan_benefit_types benefitTypes="#{pensionPlanBean.benefitTypesViewData}" />

        <div class="buttons">
            <!-- Irrelevant -->
        </div>
    </cc:implementation>
</ui:composition>

pension_plan_benefit_types複合コンポーネントを例にとってみましょう。そのインターフェースは、名前による属性がbenefitTypesクライアントによって与えられることを規定しています。クライアントが画面のこの部分だけを標準の実装とは異なるコンテンツで上書きしたい場合は、これをどこかに上書きする場所が必要です。

また、コアは (オプションの)拡張機能が提供する名前空間を認識していないことに注意してください。コンポジットのインターフェースが安定していて、変更を必要としない限り、コアはあまり気にしません。

最後の手段として、以下を試してみました (疑似コード):

<ui:composition
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:cc="http://java.sun.com/jsf/composite"
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:pui="http://java.sun.com/jsf/composite/pui">

    <cc:interface>
        <cc:attribute name="benefitTypes" required="true" type="com.foo.bar.PensionPlanBenefitTypesViewData" />
    </cc:interface>

    <cc:implementation>
        <ui:include src="/resources/pui/markup/pension_plan_benefit_types_markup.xhtml" />
    </cc:implementation>
</ui:composition>

アイデアがどこにあるのか、それがjavax.faces.view.facelets.ResourceResolver私たちの救助に来るということです。

それは「うまくいく」のですが、複合コンポーネントのために書かなければならない実装によっては、JSF ライフサイクルの悪名高いビルド対レンダリング時間部門であらゆる種類の問題に遭遇します。基本的に、私たちが期待するようには機能しません。

今の大きな問題は次のとおりです。

安定した契約/名前空間と、動的に解決される複数の実装の両方を持つ方法はありますか?

ご意見をお寄せいただきありがとうございます。

敬具、

レンズ

4

2 に答える 2

1

からの xhtml リソースのロードが要求されResourceHandlerWrapperたときにクラスパスが (最初に) スキャンされるように、を拡張しました。WEB-INF/resources

ファイルで明示的なクラスパスを定義することによりMANIFEST.MF、拡張 jar ファイルを標準実装よりも優先させることができます。そうすることで、プログラムで追加のコンテンツを生成することもできます。これは、UI で開発者 (開発モードで実行している場合) に表示され、「オーバーライド」実装が拡張プロジェクトで記述できることを開発者に知らせることができます。

于 2014-07-16T12:07:38.423 に答える
1

この種の状況は、JSF 2.2 でリソース ライブラリ コントラクト機能によって対処されています。この機能を使用すると、ローカリゼーションとアクティブなコントラクトに従って、同じ複合コンポーネントを複数実装することができます。ローカリゼーション/コントラクトはビューごとにアクティブであることに注意してください。

しかし、おそらくあなたに適したオプションは使用です:

<ui:include src="#{...}">

また

<ui:decorate template="#{...}">

また、マネージド Bean または複合コンポーネント クラス自体からテンプレート名を指定します (cc:interface componentType=...)。この場合、MyFaces Core の最新バージョンを使用することをお勧めします。これは、そのアルゴリズムがこれらのケース (小さなビュー ステート サイズと高速なパフォーマンス) に合わせて特別に最適化されているためです。ここで ResourceResolver ロジックを扱う必要はないと思います。

于 2013-10-30T15:36:38.790 に答える