2017-07-10 9 views
2

わかりやすく(簡潔にするために)私は自分のコードの重要な部分だけを列挙しています。なぜJSFはネストされたクラスをバッキングBeanで正しくインスタンス化できないのですか?

は、私は2つのネストされたクラスを含むバッキングBean MemberViewを持っている:インスタンス化されている

private Person person; 
private Member member; 

ページのロード時:適切なゲッターとセッターとの

@PostConstruct 
public void init() { 
    person = new Person(); 
    member = new Member(); 
} 

<p:inputText value="#{memberView.person.lastName}" /> 
<p:inputText value="#{memberView.member.id}" /> 

とバッキングBeanの検索ルーチンを呼び出すコマンドボタン:

<p:commandButton value="Retrieve" type="submit" 
         actionListener="#{memberView.fetchMembers()}" 
         update="@all"/> 

ページがロードのない私はPrimeFacesして表示ネストしたクラスのプロパティを利用したWebページ、member.xhtmlを、持っています入射。しかし、CommandButtonを選択するとEL ContextAwarePropertyNotFoundExceptionが発生します。javax.el.PropertyNotFoundException:Target Unreachable、 'member'がnullを返しました。何が起こっているかを追跡するために、

、私はGET-とsetMember方法にいくつかのログを追加しました:ここ

public Member getMember() { 
    LOG.info("getMember() invoked"); 
    if(member == null) { 
     LOG.log(Level.WARNING, "getMember() returning NULL"); 
    } 
    LOG.info("getMember() returning Member: " + member.toString() 
      + " with ID: " + member.getId()); 
    return member; 
} 

public void setMember(Member member) { 
    LOG.info("setMember() invoked with argument: " + member); 
    this.member = member; 
} 

は、私がCommandButton上でクリックしたときに出力されます。

明らかに
INFO: getMember() invoked 
INFO: getMember() returning Member: [email protected] with ID: null 
INFO: getMember() invoked 
INFO: getMember() returning Member: [email protected] with ID: null 
INFO: getMember() invoked 
INFO: getMember() returning Member: [email protected] with ID: null 
INFO: setMember() invoked with argument: null 
INFO: getMember() invoked 
WARNING: getMember() returning NULL 

、メンバーは除外されています。もう一つの詳細。

:私は

<!-- <p:inputText value="#{memberView.member.id}" /> --> 

会員IDの入力フィールドをコメントアウトして、検索ボタンを選択した場合、ネストされたMemberView Personクラスによって提供されるよう、ページは、メンバーと名前フィールドの名前とのdataTableを移入します

<p:dataTable id="dtPerson" var="member" 
      style="margin-top:10px;text-align:center;width:400px;minWidth:400px" 
        value="#{memberView.selectableMemberList}" 
        selectionMode="single" editable="false" 
        selection="#{memberView.member}" > 

<p:inputText value="#{memberView.person.lastName}" /> 

インスタンス化されたクラスを正常に戻した3回の呼び出しの後に、null引数を指定してsetMemberメソッドへのEL呼び出しを説明するのが完全に忘れています。私はすべての提案に開放されています。

+2

'を非常に同じプロパティに設定しています。これは意図ですか?何も選択されていない場合、または選択された選択がデータテーブル内のレコードと一致しない場合、結果はそれ自体で表明されます。 – BalusC

+0

これは、選択が行われず選択イベントが発生していなくても、dataTableによってmemberView.memberがnullに設定されることを意味しますか?私の選択リスナーは、そのようなすべてのイベントを記録します。私はdataTableの選択がclazzView.clazzに設定され、同じフォームのinputTextフィールドがclazzView.clazz.variableに設定され、これらはうまく動作する他の多くのWebページがあります。あなたの質問に答えるために、はい、これは意図的です。私はnullに設定されているクラス変数を理解できますが、クラス自体は理解できません。 –

+0

はい、それはあなたが '空の/新規/初期化された'メンバオブジェクトを扱う方法をデータテーブルが知ることができないためです。ヌルであることがより明示的です。ゲッターは、jsfの提出サイクルのさまざまな段階で呼び出されます。http://balusc.omnifaces.org/2011/09/communication-in-jsf-20.htmlを参照してください。あなたは経験したことを回避することができますが、それは...まあ...回避策です。 BalusCのような同じプロパティを使用しない方が良い – Kukeltje

答えて

1

タイムリーかつ有益な回答をお寄せいただきありがとうございます。 BalusCの提案に続いて、トレースは、DataTable.processUpdates中にMethodクラスが無効になっていることを示しています。行データが存在しないため、表内にメンバーが見つからないため、PrimeFaces SelectableDataModelはnullを戻します。これはJSFメソッドBeanELResolver.setValueによって設定されます。

私の以前のデータベースはすべて、多対1のリレーションシップを利用しています.ArrayListはポストコンストラクトに配置されているため、その後は決して空ではありません。ここで考えられる解決策の1つは、2006年のBalusCの記事(「バッキングBeanのコンストラクタまたは初期化ブロックのいずれかにdataListを読み込むことができます」)で提案されているように、ページが読み込まれたときにデータテーブルを読み込むことです。http://balusc.omnifaces.org/2006/06/using-datatables.html

より一般的なソリューションは、両方の初期化時に、空、ブランクのないデータリストとのデータテーブルを提供することで、クエリが空の結果セットが返されるときは:

/** 
* Member edited/displayed in web page text fields 
*/ 
private Member member; 

/** 
* List of Member Objects 
*/ 
private List<Member> mList; 

/** 
* Member List implementing PF SelectableDataModel 
*/ 
private SelectableMemberList selectableMemberList; 

/** 
* Creates a blank [not empty] SelectableMemberList. 
* Call on PostConstruct & on return of empty result set. 
*/ 
private void blankSelectableMemberList() { 
    if(mList == null) {   // instantiate on init() 
     mList = new ArrayList<>(); 
    } 
    if(mList.isEmpty()) {  // add blank Object 
     mList.add(new Member()); 
    } 
selectableMemberList = new SelectableMemberList(mList); 
} 

を、私は、これは誰が誰にでも役立つことを願います「空の」データテーブルを表示したい。

+0

これは「複雑な」回避策です。 'commdButton'の' process'属性がどのようにしてデータテーブルの選択を '処理'しないのかを調べる方が良いでしょう。 https://stackoverflow.com/questions/25339056/understanding-primefaces-process-update-and-jsf-fajax-execute-render-attributes – Kukeltje

+0

複雑さは視点の問題です。あなたのリンクに含まれている情報を解読するのは難しいのですが、私はそれを理解して実装するのが簡単だから、私はJavaベースのソリューションに慣れています。さらに、ビュー(MVC)と混在するのではなく、ヌルチェックをコード内に保持する方が望ましいです。さらに、これは単に自分の限界を反映しているだけで、データテーブルの処理を、実行可能であればクエリがnull結果セットを返すかどうかに制限する方法はわかりません。最後に、nullsはプログラマにとって困惑し、私はそれらをコードから守ることを好みます。 –

+0

私が投稿したリンクの情報を解読するのが難しい場合は、多くの関連する問題に対処し、回避策でそれらを修正し、最終的にはJSFを「責め」して複雑になるのではないかと心配しています。リンク内の情報を理解する。大事です!そして、私はビューbtwでヌルチェックをすることは決してなかった... – Kukeltje

関連する問題