0

JSF 2.X がそのように動作する方法と理由を理解するために、単純なコンポーネントを構築しようとしています。私は新しい注釈を使用しており、明確な例をまとめようとしています。

したがって、コンポーネントをビルドし、次のように xhtml ファイルにデプロイしました。

<kal:day value="K.Day" title="Kalendar" model="#{kalendarDay}"/>

UIComponent 内で次のことを行います。

ValueExpression ve      = getValueExpression("model");
if (ve != null) 
{
    System.out.println("model expression "+ve.getExpressionString());
    model = (KalendarDay) ve.getValue(getFacesContext().getELContext());
    System.out.println("model "+model);
}

「#{kalendarDay}」という式が正しく表示され、ページとコンポーネントの間で値が正常に送信されたことを示します。ただし、式の評価は「null」になります。

これは、この時点でバッキング Bean が使用できないことを示しているようですが、ページは正しく検証およびデプロイされます。したがって、Bean が実行時にそこにあることは 95% 確実です。

おそらくこれはフェーズの問題ですか?レンダラーのデコードでこれを評価し、属性マップに値を設定する必要がありますか? 実際の値と値式の組み合わせについては、まだ少し混乱しています。

したがって、私の質問は、モデルの valueExpression をどこで取得して評価する必要があり、評価の結果を UIComponent に保存する必要があるのか​​、それとも毎回評価する必要があるのか​​ということです。

以下のSSCCEファイルは、問題を実証するために必要な唯一のファイルだと思います

Bean インターフェース -----

/**
 * 
 */
package com.istana.kalendar.fixture;

import java.util.Date;

/**
 * @author User
 *
 */
public interface KalendarDay
{
    public      Date        getDate();
}

ビーン実装 ---

/**
 * 
 */
package com.istana.kalendar.session.wui;

import java.util.Calendar;
import java.util.Date;

import javax.ejb.Stateful;
import javax.inject.Named;

import com.istana.kalendar.fixture.KalendarDay;

/**
 * @author User
 *
 */
@Named      ("kalendarDay")
@Stateful
public class KalKalendarDay
    implements KalendarDay
{

    private     Calendar        m_date  =   Calendar.getInstance();

    /* (non-Javadoc)
     * @see com.istana.kalendar.fixture.KalendarDay#getDate()
     */
    @Override
    public      Date            getDate()
    {
        return m_date.getTime();
    }

}

UI コンポーネント ---

/**
 * 
 */
package com.istana.kalendar.fixture.jsf;

import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIOutput;

import com.istana.kalendar.fixture.KalendarDay;

/**
 * @author User
 *
 */
@FacesComponent     (value=UIDay.COMPONENT_TYPE)
public class UIDay  extends UIOutput
{
    static      final
    public      String          COMPONENT_TYPE      =   "com.istana.kalendar.fixture.jsf.Day";

    static      final
    public      String          COMPONENT_FAMILY    =   "com.istana.kalendar.fixture.jsf.Day";

    private     KalendarDay     m_model;

    private     String          m_title;

    @Override
    public      String          getRendererType() 
    {
        return UIDayRenderer.RENDERER_TYPE;
    }

    @Override
    public      String          getFamily() 
    {
        return COMPONENT_FAMILY;
    }

    public      KalendarDay     getModel()
    {
        KalendarDay     model = (KalendarDay) getStateHelper().eval("model");

        System.out.println("model "+model);

        return model;
    }

    public      void            setModel(KalendarDay model)
    {
        getStateHelper().put("model",model);
    }

    public      String          getTitle()
    {
        return (String) getStateHelper().eval("title");
    }

    public      void            setTitle(String title)
    {
        getStateHelper().put("title",title);
    }
}

UIComponentRenderer ---

/**
 * 
 */
package com.istana.kalendar.fixture.jsf;

import java.io.IOException;

import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import javax.faces.render.Renderer;

import com.istana.kalendar.fixture.KalendarDay;

/**
 * @author User
 *
 */
@FacesRenderer  (componentFamily    = UIDay.COMPONENT_FAMILY
                ,rendererType       = UIDayRenderer.RENDERER_TYPE
                )
public class UIDayRenderer extends Renderer
{
    static      final
    public      String      RENDERER_TYPE   =   "com.istana.kalendar.fixture.jsf.DayRenderer";

    @Override
    public      void        encodeBegin (FacesContext context,UIComponent component) 
        throws IOException 
    {
        UIDay uic = (UIDay) component;

        ResponseWriter writer = context.getResponseWriter();
        writer.startElement("p", uic);
        /*
         * This is the call that triggers the println
         */
        writer.write("Day - "+uic.getModel().getDate());
    }

    @Override
    public      void        encodeEnd   (FacesContext context,UIComponent component) 
            throws IOException 
    {
        ResponseWriter writer = context.getResponseWriter();
        writer.endElement("p");
        writer.flush();
    }
}

kalendar.taglib.xml ---

<facelet-taglib 
    id="kalendar"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
    version="2.0"
>

    <namespace>http://istana.com/kalendar</namespace>
    <tag>
        <tag-name>day</tag-name>
        <component>
            <component-type>com.istana.kalendar.fixture.jsf.Day</component-type>
        </component>
    </tag>

</facelet-taglib>
4

1 に答える 1

0

理由はわかりませんが、ビューのビルド時に を評価しようとしているときに、ビューのレンダリング時に が指定されているnullことを示す症状です。#{kalendarDay}


おそらくこれはフェーズの問題ですか?レンダラーのデコードでこれを評価し、属性マップに値を設定する必要がありますか? 実際の値と値式の組み合わせについては、まだ少し混乱しています。

コンポーネントまたは関連するレンダラー (存在する場合)のメソッドを使用しencodeXxx()て、コンポーネントの属性/プロパティに基づいて HTML を生成する必要があります。

コンポーネントのdecode()メソッドまたは関連するレンダラー (存在する場合) を使用して、HTML フォームの送信と共に送信された HTTP 要求パラメーターに基づいてコンポーネントの属性/プロパティを設定する必要があります。


したがって、私の質問は、モデルの valueExpression をどこで取得して評価する必要があり、評価の結果を UIComponent に保存する必要があるのか​​、それとも毎回評価する必要があるのか​​ということです。

JSF 2.x 以降では、コンポーネント属性の getter と setter を明示的に指定することをお勧めしますUIComponent#getStateHelper()

public String getValue() {
    return (String) getStateHelper().eval("value");
}

public void setValue(String value) {
    getStateHelper().put("value", value);
}

public String getTitle() {
    return (String) getStateHelper().eval("title");
}

public void setTitle(String title) {
    getStateHelper().put("title", title);
}

public Object getModel() {
    return getStateHelper().eval("model");
}

public void setModel(Object model) {
    getStateHelper().put("model", model);
}

基本的にこれで十分です (getter と setter は、Javabeans 仕様に従って属性名と正確に一致する必要があることに注意してください)。次に、メソッドで、属性の値を取得 (および評価) するためencodeXxx()に呼び出すだけです。getModel()model

于 2012-08-06T15:55:25.843 に答える