LoginSignup
6
7

More than 5 years have passed since last update.

Apache Wikcet 7.x ユーザガイド7章邦訳+訳注

Posted at

原文

原文著者: Authors: Andrea Del Bene, Martin Grigorov, Carsten Hufe, Christian Kroemer, Daniel Bartl, Paul Borș, Tobias Soloschenko, Igor Vaynberg , Joachim Rohde

訳注は :sos: で示します。
訳語集

ページ部品
org.apache.wicket.Component 原文では単に component

7. ページ部品のライフサイクル

アプレットやサーブレットと同様にWicketのページ部品はその存在期間中に幾つかの段階が存在します。この章ではその段階それぞれについで分析し、ページ部品の段階が切り替わった時に実行される(ほとんど全ての)フックメソッドの作り方を学びます。

7.1. ページ部品のライフサイクル段階

ページ部品の生涯には以下の3つの基本的段階があります:

初期化(initialization)
Wicketによりページ部品が生成され、描写前の準備が行われます。
描写中(Rendering)
この段階でWicketはページ部品のマークアップを生成します。(例えばMarkupContainerのような)子となるページ部品が含まれていた場合は、自身の描写に先立ってにそれら(:sos:子となるページ部品)の描写が完了するのを待たなくてはなりません。
除去中(Removing)
この段階はページ部品が明示的にページ部品の木構造から除去された時、例えば親となるページ部品がそのページ部品に対して`remove(component)`を呼び出したとかいった時に発生します。この段階は随意のもので(:sos:開発者がremoveしなきゃ呼ばれないよという意味です)、ページそのものについては発生することはありません。

以下がページ部品のライフサイクル段階の状態遷移図になります。

原文ページ転載

ページ部品は一度除去された後、再びコンテナ(:sos:親あるいは他のページ部品)に追加することができますが、初期化段階が再び発生することはありません。

:warning: ページ部品のライフサイクルに関するより詳細な説明はComponentクラスのJavaDocにあります。JavaDocの説明はまだ説明していない高度な内容を含んでいるため、この章では混乱を避けるために、後の章で説明する詳細な部分については省略しています。今は上に説明した簡略化されたライフサイクルについてだけ考えてください。

7.2. 各ライフサイクル段階に対応するフックメソッド

Componentクラスにはそれぞれのライフサイクル段階における振る舞いをカスタマイズするための、オーバライド可能なたくさんのフックメソッドがあります。以下の表ではそれらのメソッドを実行されるライフサイクル段階別にグループ化したものになります(同じグループのものは実行順に並べられています):

段階 実行されるメソッド
初期化 onInitialize
描写中 onConfigure, onBeforeRender, onRender, onComponentTag, onComponentTagBody, onAfterRenderChildren, onAfterRender
除去中 onRemove

ではそれぞれの段階と実行されるフックメソッドについて詳しく見ていきましょう。

7.3. 初期化(Initialization stage)

この段階はページ部品のライフサイクルの一番最初に実行されます。初期化段階のページ部品はページ全体の木構造に既に組み込まれているため、安全にgetParent()getPage()のようなメソッドによって親となるページ部品やページそのものにアクセスすることが可能です。この段階で呼び出されるメソッドはonInitialize()のみです。このメソッドは任意の初期化処理を実行することができる特殊化されたコンストラクタとでも呼ぶべきものです。

またonInitializeは一般的なコンストラクタと同様に、オーバーライドした場合には親クラスのsuper.onInitializeをそのメソッド内で呼び出さなくてはなりません。(普通は場合は一番最初に呼び出ます)

7.4. 描写中(Rendering stage)

この段階はページ部品がWicketによって描写されるたび、典型的にはページがリクエストされた時やAJAXで更新された時に発生します。

onConfigure メソッド

onConfigure() メソッドはページ部品の可視性(:sos:可視・不可視)や有効性(:sos:活性・非活性)を制御する最適の場所として導入されました。このメソッドは描写が始まる前に呼び出されます。6.1.章で言及したようにisVisibleisEnabledはページ部品の描写中に何度となく呼び出されるため、これらのメソッドを直接オーバーライドすることは強く推奨されず、それよりもonConfigureを用いて状態を変更するべきです。(次の節で説明する)onBeforeRener メソッドはこれとはまったく逆に、ページ部品を不可視にした場合にはそもそも呼び出されないため、この手の処理を意図したものではありません。

onBeforeRender メソッド

この段階でも最も重要なフックメソッドはおそらく`onBeforeRender()です。このメソッドはページ部品が描写処理に入る前に呼び出され、その子となるページ部品の構造を変更する最後の機会になります。

もしも子となるページ部品を追加したり除去したりしたいのであれば、ここが最適の場所です。次の例(LifeCycleStagesプロジェクト)では描写されるたびに異なる2つのラベルを交互に表示するページを作っています:

public class HomePage extends WebPage
{
    private Label firstLabel;
    private Label secondLabel;
    public HomePage(){
        firstLabel = new Label("label", "First label");
        secondLabel = new Label("label", "Second label");

        add(firstLabel);
        add(new Link("reload"){
            @Override
            public void onClick() {
            }
        });
    }

    @Override
    protected void onBeforeRender() {
        if(contains(firstLabel, true))
            replace(secondLabel);
        else
            replace(firstLabel);

        super.onBeforeRender();
    }
}

onBeforeRender()内のコードはささいなもので、ページ部品の木構造にfirstLabelsecondLabelのどちらが存在するかを調べ、存在するものをもう一方のものと交換しています。
このメソッドは子となるページ部品のonBeforeRender()の呼び出しも行っているため、オーバーライドするときにはsuper.onBeforeRender()を呼びださなくてはなりません。ただしonInitialize()とは異なり、カスタマイズコードでの変更を子となるページ部品の描写に反映するため、親クラスのメソッドの呼び出しは一番最後でなくてはなりません。

上の例ではF5キーを押すか、リロードボタンを押すかして描写中段階を発生させなくてはならない点には注意してください。

:no_entry: もしも親クラスのonInitialize()onBeforeRender()の呼び出しを忘れた場合、Wicketは以下のメッセージでIllegalStateExceptionを発行します。

java.lang.IllegalStateException: org.apache.wicket.Component has not been properly initialized. Something in the hierarchy of has not called super.onInitialize()/onBeforeRender() in the override of onInitialize()/ onBeforeRender() method

onComponentTag メソッド

onBeforeRender(ComponentTag)メソッドはページ部品のタグ引数のorg.apache.wicket.markup.ComponentTagを通して自由に処理してもらうために呼び出されます。例えばput(String key, String value)メソッドやremove(String key)メソッドでタグ属性の追加/除去ができ、あるいはタグの名前そのものを`setName(String)で変更することもできます。(次のコードはonComponentTagExampleプロジェクトのものです):

Markup code:

<head>
  <meta charset="utf-8" />
  <title></title>
</head>
<body>      
  <h1 wicket:id="helloMessage"></h1>        
</body>

Java code:

public class HomePage extends WebPage {
   public HomePage() {
      add(new Label("helloMessage", "Hello World"){
         @Override
         protected void onComponentTag(ComponentTag tag) {            
            super.onComponentTag(tag);
            //Turn the h1 tag to a span
            tag.setName("span");
            //Add formatting style
            tag.put("style", "font-weight:bold");
         }
      });
    }
}

Generated markup:

<head>
  <meta charset="utf-8" />
  <title></title>
</head>
<body>      
  <span wicket:id="helloMessage" style="font-weight:bold">Hello World</span>        
</body>

onInitializeと同様にonComponentTagをオーバーライドするとなったなら、親クラスでもタグのカスタマイズをしているかもしれないので、親クラスの同じメソッドを呼び出すのを忘れてはなりません。onConponentTagのオーバーライドは特定のページ部品のタグをカスタマイズしなくてはならない場合には完璧ですが、同じコードを別のページ部品でも使いまわしたい場合にはこのフックメソッドの代わりにビヘイビアを使ったほうが良いでしょう。

タグ属性を操作する場合のAttributeModifierビヘイビアの使い方については既に6.2.章で見ています。19.1章ではそのベースクラスであるBehaviorクラスがフックメソッドのonComponentTag(ComponentTag)の代替となるonComponentTag(ComponentTag, Component)というメソッドを持っているのを見ることになります。

onComponentTagBody メソッド

onComponentTagBody(MarkupStream, ComponentTag)メソッドはタグの中身を処理するために呼ばれます。入力としてonComponentTagと同様にページ部品のタグを表すComponentTagを受け取ります。それに加えてクライアントに返却されるページのマークアップストリームを表すMarkupStreamもあります。

onComponentTagBodyではComponentクラスのreplaceComponentTagBodyとの組み合わせで特定状況にカスタマイズされたタグ内容を描写することができます。例えば(プロジェクトOnComponentTagExampleからのものです)ラベル部品が無効化されている場合にその内容の代わりに簡潔な説明文を表示することができます:

public class HomePage extends WebPage {
   public HomePage() {
      add(new Label("helloMessage", "Hello World"){
         @Override
         protected void onComponentTagBody(MarkupStream markupStream, ComponentTag tag) {

           if(!isEnabled())
               replaceComponentTagBody(markupStream, tag, "(the component is disabled)"); 
          else    
               super.onComponentTagBody(markupStream, tag);
         }
      });   
    }
}

親クラスのonComponentTagは標準のタグ内容描写処理を維持したい場合にだけ呼び出せば良い点に注意してください。(上の例ではページ部品(:sos:ラベル)が有効な場合のみになります)

7.5. 除去中(Removing stage)

この段階はページ部品がコンテナ(:sos:親あるいは他のページ部品)の木構造から取り除かれた時に発生します。この段階のフックメソッドはonRemove()のみです。もしもページ部品が描写中に必要だった何かしらのリソースをまだ保持していたりする場合、このメソッドをオーバーライドしてそれを開放することができます。

一度ページ部品が除去された後は、それを同じコンテナに追加するのも別のものに追加するのも自由です。バージョン6.18.0以降ではさらに、一度除去されたページ部品が再度別のコンテナに追加されるたびに呼び出されるonReAdd()というフックメソッドが追加されています。onInitializeページ部品がコンテナに初めて追加された時のみなのに対して、onReAddd一度除去された後、追加される度である点には注意してください。

7.6. まとめ

この章ではWicketページ部品のライフサイクル各段階とそれぞれに提供されているフックメソッドについて見てきました。これらのメソッドをオーバーライドすることでページ部品の構造を動的に変更したり、カスタムページ部品の振る舞いを強化したりすることができます。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7