2011-07-31 1 views
2

私はWicketアプリケーションでPropertyModelとCompoundpropertyモデルを使用しています。私はそれらをページ変数のメンバーではなくローカル変数として使用します。モデルがローカルのときにモデルをデタッチするためにonDetach()関数をオーバーライドする必要がありますか?または、メンバー変数のみがセッションにシリアル化されていますか?ローカル変数で使用されている場合、私はウィケットモデルを取り外さなければなりませんか?

例:この例では、とWicketでは、このようなモデルのほとんどの用途で

TextField<String> title = new TextField<String>("title", new PropertyModel<String>(position, "title")); 
title.setRequired(true); 
form.add(positionTitle); 

答えて

2

、初期割り当ては、ローカル変数にですが、オブジェクトが何かに入れられるいいえローカルではありません。

あなたのformは、ほぼ確実にフィールドであるか、セッションにシリアル化されているフィールドに含まれています。これにはtitleフィールドがあり、フィールドにはモデルが含まれています。

したがって、シリアル化されます。はい、おそらくonDetach()を実装する必要があります。

編集:コメントで述べたように

、本当に重要なのは、それがフィールドであるかどうかではなく、ページのコンポーネント階層の一部であるかどうかです。ページや他のコンポーネントの子コンポーネントは、スーパークラスorg.apache.wicket.MarkupContainerのフィールドchildrenに保持されているため、同じレベルになります。

+0

@Martinさらに、フォームがフィールドではない場合でも、ページに追加されます(その間に他のコンポーネントが1つ以上ある可能性があります)。そして、このページは確実にシリアル化されます。 – Nicktar

+0

@Nicktar - 良い点。私はこれを組み込む答えを更新しました。 –

3

投稿したフォームの値を書き込むためにTextFieldにモデルオブジェクトが必要なので、なぜあなたのTextFieldのモデルを切り離したいのかはわかりません。 PropertyModelからpositionをデタッチすると、ユーザーがフォームを送信した後にTextFieldに "title"値を書き込む場所がありません。 positionが何であるか、どこからロードされたのか、そしてリクエストサイクルの間にデタッチする必要があるのか​​についての詳細を提供したいかもしれません。一般的なプラクティスは、フォームコンポーネントがその値を書き込むための安全にシリアライズ可能なモデルオブジェクトを持つことです。

各リクエストの最後にPropertyModelのモデルオブジェクトをデタッチする必要がある場合は、PropertyModelをLoadableDetachableModelにチェーンします。 LDMは、提供されたload()メソッドに基づいて、各要求サイクルごとに新しいモデルオブジェクトをロードし、そのモデルオブジェクトの参照を自動的に無効にして、モデルオブジェクトの直列化を防止します。 LoadableDetachableModel<Position>をPropertyModelのモデルオブジェクトとして使用すると、PropertyModelによってLoadableDetachableModelが自動的に切り離され、positionオブジェクトのシリアル化が回避されます。

例のようなモデルでdetach()を明示的に呼び出す必要はありません。 Wicketは、ページ階層内のすべてのコンポーネントのデフォルトモデルを自動的に切り離します。 「デフォルトモデル」とは、super(...)チェーンを通過し、最終的にComponent(...)コンストラクタの1つのmodel引数になるモデルを意味します。

リクエスト処理の終了時に、ページは子供のdetach()(およびその子どもはdetach()を子どもに呼び出すなど)を呼び出します。このメソッド(Componentで定義されている)はdetachModels()を呼び出し、Componentのデフォルトモデルを切り離します。

複数のモデルを共通に使用する標準のWicketコンポーネントは、detachModelsの間に追加モデルを切り離します。たとえば、DropDownChoiceを選択した値を取得または設定するモデルと選択肢のリストのモデルの両方を渡すと、DropDownChoiceは各要求の最後にこれらのモデルを自動的に切り離します。これは、AbstractChoice#detachModel()が設定されている場合、choicesモデルを検索して切り離すためです。あなたはCompoundPropertyModelがdetachModelsによって自動的に切り離されることになる

Form<User> userForm = new Form<User>("userForm", new CompoundPropertyModel<User>(new DetachableUserModel(...)); 

があった場合例えばので

チェーンモデルも、彼らのチェーンモデルを切り離し、それは順番にDetachableUserModelを切り離します。

モデルを手動で切り離すことを心配する必要がある場合は、コード内にデフォルトの部品番号modelでない追加モデルを使用したり、別のモデルにチェーンしたりしない場合があります。これは、複数のモデルオブジェクトを持つ新しいタイプのComponentを作成する場合には問題になる可能性があります。あなたのケースでは

+0

確かに、彼らはwicketによってデタッチされますが、それらがdatachableであり、意味のある方法で "デタッチ"を実装する場合に限ります。 PropertyModelは、ターゲットオブジェクト上のdetachを呼び出します(デタッチ可能な場合)。だから、はい、それは自動的に切り離されますが、あなたが必要なコードを提供し、それが質問の内容です。 – Nicktar

+0

@Nicktar入手しました。コメントありがとう。元の質問は、 "モデル"と "モデルオブジェクト"を混同しているようです。 "PropertyModelとCompoundpropertyModelをローカル変数として使用し、ページクラスのメンバーとしてではなく、使用しています。ローカルにいるときにモデルをデタッチする必要はありますか?"私は私の答えを更新しました。 –

0

、私はどうなる:

IModel model = new CompoundPropertyModel(new LoadableDetachableModel(position){ 
     @Override protected Object load() { return null; } 
    }); 
    Form form = new Form("form", model); 
    form.add(
      new TextField("title") 
       .setRequired(true)); 
    add(form); 

detach()は、リクエストの最後にチェーンで呼び出されます。 LoadableDetachableModelを使用して、位置オブジェクトが参照されていないことを確認します。

トリック:ドメインオブジェクトまたは値オブジェクトをシリアライズ不可能に保ちます。開発環境では、シリアル化エラーが発生した場合、これらのオブジェクトに対する参照を保持していることを意味します。

関連する問題