コントロールでは、イベント メソッドを指定することができます。イベント メソッドは、コントロールのクライアントにイベントが発生したことを非同期に通知する手段を提供します。イベント メソッドは、クライアントのリソースをネットワーク リクエストや長時間の処理に束縛されたくない場合に特に役立ちます。コントロールが値を返すのを待機してクライアントにリソースを無駄にさせるのではなく、クライアントはコントロールから離れて、コントロールからのイベントをリスンしながら他のプロセスを処理することができます。
コントロール イベントが発生すると、それがクライアントのコードに通知されます。つまり、コントロール イベント メソッドがトリガされると、クライアントにイベントが送信されて、クライアントに実装されているイベント ハンドラが実行されます。イベント ハンドラは一般的なメソッドと変わりませんが、呼び出しのタイミングをクライアントのコードが決定しません。代わりに、コントロール イベント メソッドがイベント ハンドラ実行のタイミングを決定します。
イベントとコールバックは、イベントをクライアントのコードに非同期に通知する手段を提供するという目的においては、基本的に同じです。この 2 つの違いは、ほとんどの場合、用語上の違いと適用範囲の違いによるものです。Web サービスでは「コールバック」メッセージを送信するというのに対し、コントロールでは「イベント」メッセージを送信するといいます。
以下の図に、簡単なコントロール イベントのシナリオを示します。このシナリオは、主に、Web サービス (クライアント) と、クライアントである Web サービスが使用するコントロールの 2 つのコンポーネントから構成されています (以下に示しているのは、コントロール インタフェース クラスのみで、実装クラスは示していません)。
右方向の矢印は通常のメソッド呼び出しを表し、左方向の矢印はイベントとイベント ハンドラを表しています。
以下のシーケンスは、クライアントの Web サービスがコントロールを呼び出し、コントロールからイベントを受信する方法を示しています。
1. クライアントの Web サービスのメソッド start が実行され、コントロール メソッド requestMessage が呼び出されます。
ClientWebService.java
@Control private MyControl myControl; public void start() { myControl.requestMessage(); }
2. コントロール メソッド requestMessage が実行されます。
requestMessage メソッドのシグネチャはコントロール インタフェース クラスで定義されますが、メソッドの本体はコントロール実装クラスで定義されます。メソッドの本体がイベント メソッドを呼び出します (イベント メソッドの構文については、以下の段階 3 を参照)。
MyControl.java (Control Interface)
public void requestMessage();
MyControlImpl.java (Control Implementation)
public void requestMessage() { // イベント メソッドを呼び出し、クライアントにイベントを送信する eventSet.onMessage("This is a message from the custom control.");
3. イベント メソッド onMessage が呼び出され、クライアントにイベントが送信されます。
コントロール インタフェース クラスはイベント セット インタフェースを公開しています。イベント セット インタフェースは @EventSet アノテーションによって修飾される必要があります。@EventSet アノテーションはインタフェースのすべてのメソッドをイベント メソッド (クライアントの対応するイベント ハンドラをトリガできるメソッド) として公開しています。
MyControl.java (Control Interface)
@EventSet public interface MyEventSet { void onMessage(String aMessage); }
コントロール インタフェース クラスとコントロール実装クラスのいずれにも、onMessage イベント メソッドの実装は存在しません。イベント メソッドのシグネチャ (void onMessage(String aMessage)) のみ、コントロール インタフェース クラスに存在します。これは、イベント メソッドの目的が、クライアントのイベント ハンドラを呼び出して、そのハンドラにデータを渡すためだけだからです。
このシナリオでは、イベント メソッドに 1 つのパラメータ String aMessage が指定されており、クライアントのメソッド ハンドラに転送されます。
@Client アノテーションによって、ControlBean はイベント インタフェースの実装を初期化します。この実装はイベントをクライアントに送信するのに使用されます。
MyControlImpl.java (Control Implementation)
@Client MyEventSet eventSet; public void requestMessage() { eventSet.onMessage("This is a message from the custom control."); }
4. イベント ハンドラが実行します。
ClientWebService.java
@EventHandler(field = "myControl", eventSet = MyControl.MyEventSet.class, eventName = "onMessage") protected void myControl_MyEventSet_onMessage(String aMessage) { System.out.println("Got message from myControl: " + aMessage); }
@EventHandler アノテーションは、コントロール イベント メソッド onMessage がクライアントのイベント ハンドラ メソッドを呼び出すためのパスを提供します。@EventHandler には、ハンドラがどのイベント メソッドに反応するかを示すのに必要な情報 (ターゲット コントロール、イベント セット、イベント セットの特定のイベント) がすべて含まれています。
イベント ハンドラ名は任意に命名できます (@EventHandler アノテーションが、ハンドラが適切なイベント メソッドに反応するようになるためのすべての作業を担当するため)。通常、以下の規則に従ってイベント ハンドラを命名します。
<control-reference-field-name>_<event-set-name>_<event-name>
Workshop では、イベント ハンドラがクライアント クラスに追加されると (右クリックして [挿入|コントロールのイベント ハンドラ])、デフォルトでこの命名規則が適用されます。
イベント ハンドラが正常に呼び出されるためには、イベント メソッドのパラメータ セットがイベント ハンドラのパラメータ セットと一致している必要があります。上記の例では、イベント メソッドとイベント ハンドラのパラメータ セット (1 つの String パラメータ) が一致しています。
@EventSet public interface MyEventSet { void onMessage(String aMessage); }
@EventHandler(field = "myControl", eventSet = MyControl.MyEventSet.class, eventName = "onMessage") protected void myControl_MyEventSet_onMessage(String aMessage) { ... }
コントロールのイベント セットの定義は、2 つの要素で構成されています。
(1) イベント セット インタフェースの @EventSet 宣言 :
MyControl.java
@ControlInterface public interface MyControl { public void requestMessage(); @EventSet public interface MyEventSet { void onMessage(String aMessage); } }
@EventSet 宣言では複数のイベント メソッドを定義できます。
MyControl.java
@ControlInterface public interface MyControl { public void requestMessage(); @EventSet public interface MyEventSet { void onMessage(String aMessage); void onReady(boolean boolReady); } }
(2) コントロール実装の @Client 宣言 :
MyControlImpl.java
@Client MyEventSet eventSet;
イベントが送信されるには、コントロール実装内でイベント メソッドが呼び出される必要があります。
public void requestMessage() { eventSet.onMessage("This is a message from the custom control."); }
イベント メソッド定義には本体がありません。戻り値の型とパラメータなどのメソッド シグネチャのみです。
一般的に、イベント メソッドには「on」で始まる名前が付いています。これは、クライアントのイベント ハンドラがイベントの発生に「基づいて」呼び出されるためです。
コントロールのイベント メソッドのハンドラは、クライアント アプリケーションで実装する必要があります。
以下に、クライアント アプリケーション内に記述される可能性のあるイベント ハンドラの例を示します。
@EventHandler(field = "myControl", eventSet = MyControl.MyEventSet.class, eventName = "onMessage") protected void eventHandler(String aMessage) { // ここでメッセージを使用して何らかの処理を行う }
イベント ハンドラが関連付けられたイベントを正常にリスンにするには、以下の 2 つの条件が必要になります。
(1) @EventHandler アノテーションが適切なコントロール、イベント セット、イベントを指すこと。
つまり、フィールド属性が、クライアント内で宣言されているコントロール フィールドを参照する必要があります。コントロール フィールドが以下のように宣言されているとします。
@Control private MyControl myControl;
その場合、@EventHandler はこのフィールドを参照する必要があります。
@EventHandler(field = "myControl",
また、@EventHandler はコントロールに定義されている EventSet と特定のイベント メソッドを参照する必要があります。以下の EventSet とイベント メソッドがコントロールで定義されているとします。
@EventSet public interface MyEventSet { void onMessage(String aMessage); }
その場合、@EventHandler が以下の EventSet とイベント メソッドを参照する必要があります。
@EventHandler(field = "myControl", eventSet = MyControl.MyEventSet.class, eventName = "onMessage")
(2) イベント メソッドとそのハンドラのパラメータ セットが一致すること。つまり、パラメータの数、順序、型が一致していなければなりません。たとえば、以下のイベント メソッドとハンドラのパラメータ セットは一致しています。
@EventSet public interface MyEventSet { void onMessage(String aMessage, boolean status); }
@EventHandler(...) protected void eventHandler(String aMessage, boolean status) {
外部イベントは Web サービス クライアントでのみサポートされています。他のクライアントはネットワーク プロトコルを通じてイベント通知を処理することはできません。
イベント セットとイベント ハンドラを追加するには、以下のコマンドを使用します。
イベント セットをコントロールに追加するには、コントロール インタフェースのソース ビュー内の任意の場所で右クリックして [挿入|イベント セット] を選択します。デフォルトでは、onEvent1() という 1 つのイベント メソッドを持つ NewEventSet というイベント セット インタフェースが、コントロール インタフェースに追加されます。
SomeControl.java
@EventSet public interface NewEventSet { void onEvent1(); }
さらに、対応する @Client 宣言がコントロール実装ファイルに追加されます。
SomeControlImpl.java
@Client NewEventSet eventSetClient;
デフォルトのイベント セットとイベント メソッドの名前を手動で変更する必要があります。必要に応じて、イベント メソッドを追加します。
イベント ハンドラをコントロール クライアントに追加するには、ソース ビュー内の任意の場所で右クリックして [挿入|コントロールのイベント ハンドラ] を選択します。クライアントで宣言されているコントロールとそれらのコントロールによって公開されているイベントがダイアログに表示されます。コントロール、イベント セット、特定のイベント メソッドを選択して、そのイベント メソッドに対応するイベント ハンドラを構築します。
イベント ハンドラがクライアントのソースに追加されます。
@EventHandler(field = "myControl", eventSet = MyControl.MyEventSet.class, eventName = "onMessage") protected void myControl_MyEventSet_onMessage(String aMessage) { }