6

の実行順序と回数に問題がありf:event type="preRenderView"ます。

ここでの検索中に、BalusC からの通常の回答として、これと私の問題に関連するこの投稿を見つけましたが、それでも私には 2 つの質問が残っています。

  1. f:event type="preRenderView"テンプレート ファイル (すべてのビューに適用されるユーザー状態のチェックなどの一般的なタスクを管理するため) に 1 つを配置し、各ビュー (ビュー固有の初期化を処理するため) に別のファイルを配置するとf:event type="preRenderView"、なぜビューからリスナー メソッドが呼び出されるのか疑問に思います。テンプレートからのものの前に。

  2. 提案どおりに全体を配置する<f:metadata><f:event [..] /></f:metadata>ui:define、ログインページからそのページにリダイレクトした後に2回呼び出されますが、1回だけ呼び出された後、1レベル上に配置するui:compositionと。


更新: 例

次の例は、上記の動作を示しています。

これは、すべてのビューのハンドラーで共通メソッドを呼び出すイベントtemplate_test.xhtmlのリスナーを含むテンプレート ファイルです。preRenderView

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="de" lang="de" xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    <link rel="stylesheet" type="text/css" href="../resources/css/style.css" />
</h:head>
<h:body>
    <f:event type="preRenderView" listener="#{testHandler.initCommon()}" />
    <div id="content">
        <ui:insert name="content" />
    </div>
</h:body>
</html>

これはビュー ファイルで、ハンドラーでビュー固有のメソッドを呼び出すイベントtest.xhtmlのリスナーpreRenderViewと、ハンドラー メソッドを介してリダイレクトするコマンド ボタンも含まれています。

<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    template="template_test.xhtml">
    <ui:define name="content">
        <f:metadata>
            <f:event type="preRenderView"
                listener="#{testHandler.initIndividual()}"></f:event>
        </f:metadata>
        <h:form>
            <h:commandButton value="Redirect" action="#{testHandler.redirect()}" />
        </h:form>
    </ui:define>
</ui:composition>

TestHandler.javaこれは、3 つのメソッドを含むハンドラ クラスです。

package test;

import java.io.Serializable;

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class TestHandler implements Serializable {

    private static final long serialVersionUID = -2785693292020668741L;

    public void initCommon() {
        System.out.println("Common init called.");
    }

    public void initIndividual() {
        System.out.println("Init for individual page called.");
    }

    public String redirect() {
        return "test/test.xhtml?faces-redirect=true";
    }
}

テストページをリクエストすると、Tomcat ログに次のように表示されます。

Init for individual page called.
Common init called.
Init for individual page called.

これはノーを示しています。1、ビューからのイベントハンドラーがテンプレートからのイベントハンドラーの前に呼び出され、いいえ。2、ビューからのイベント ハンドラーが 2 回呼び出されること。

また、ページがリダイレクトによって要求された場合に何が起こるかを示す 3 番目のポイント (同じページへのリダイレクトを含むボタンを含めた理由) も示しています。個々のページはさらに何度も呼び出されます。

Init for individual page called.
Common init called.
Init for individual page called.
Init for individual page called.

どちらもいいえ。2 と 3 は、メタデータ セクション全体を の上に置くかui:define、URL に含まれていないビューのメタデータ セクションにダミー パラメータを追加することで回避できます。

<f:metadata>
    <f:viewParam name="dummyToDenySecondRedirect" />
    <f:event type="preRenderView"
        listener="#{testHandler.initIndividual()}"></f:event>
</f:metadata>

誰かがこれらのケースの理由を教えてもらえますか?

4

2 に答える 2

5

再現できます。/WEB-INF/beans.xmlこれは、暗黙のうちに CDIの存在によって引き起こされます。ファイルを保持したまま標準の JSF アノテーションに戻した場合にも発生しbeans.xmlます。これは、問題 1771問題 2162の両方として既に報告されています。しかし、問題を再現する具体的な WAR ファイルがなく、投票数が少なかったため、Mojarra の開発者はそれを詳しく調べようとはしませんでした。

issue 2719として再度報告しました。この問題は、より小さな例で再現できます。

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>
    <f:metadata>
        <f:event type="preRenderView" listener="#{bean.preRenderView}" />
    </f:metadata>
    <h:head>
        <title>preRenderView fail</title>
    </h:head>
    <h:body>
        <p>On initial request, you'll see the listener being invoked twice instead of only once.</p>
        <p>On every postback by the below button, you'll see the listener being invoked once more.</p>
        <h:form>
            <h:commandButton value="submit" />
        </h:form>
        <p>Note however that this increments every time you issue the postback.</p>
        <p>If you remove <code>/WEB-INF/beans.xml</code> and redeploy, then the issue will disappear.</p>
    </h:body>
</html>

package com.example;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Bean {

    public void preRenderView() {
        System.out.println("preRenderView called");
    }

}
于 2013-02-01T13:22:18.887 に答える