SeamFramework.orgCommunity Documentation
Seam は、 Web ページから AJAX (Asynchronous Javascript and XML) を使用してコンポーネントにリモートアクセスする便利な方法を提供します。 この機能を実現する Seam では、 開発時に労力がかからないようになっています - コンポーネントに必要なものは、 AJAX を通じてアクセス可能とするための単純なアノテーションだけです。 この章では、 AJAX 可能な Web ページを作るために必要なステップについて述べ、 そしてSeam Remoting フレームワークの機能についても詳しく説明します。
リモーティングの機能を使用するには、まずweb.xml
ファイル内でSeam Resourceサーブレットを設定する必要があります。
<servlet>
<servlet-name
>Seam Resource Servlet</servlet-name>
<servlet-class
>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name
>Seam Resource Servlet</servlet-name>
<url-pattern
>/seam/resource/*</url-pattern>
</servlet-mapping
>
次のステップは、Webページに必要なJavaScriptをインポートすることです。インポートすべきスクリプトが最低二つあります。最初の一つは、リモーティングの機能を有効にする、クライアントサイドフレームワークのすべてのコードを含みます:
<script type="text/javascript" src="seam/resource/remoting/resource/remote.js"
></script
>
二つ目のスクリプトは、 呼び出したいコンポーネントに対するスタブと型定義を含みます。 それはコンポーネントのローカルインタフェースをもとにして動的に生成され、 インタフェースのリモートメソッドを呼び出す際に使用されるすべてのクラスに対する型定義を内包しています。 スクリプトの名前はコンポーネントの名前が反映されます。 例えば、 @Name("customerAction")
というアノテーション付きのステートレスセッション Bean を持つ場合、 スクリプトタグは以下のようになります。
<script type="text/javascript"
src="seam/resource/remoting/interface.js?customerAction"
></script
>
同じページから一つ以上のコンポーネントにアクセスしたい場合は、スクリプトタグのパラメータとしてそれらをすべて含めます。
<script type="text/javascript"
src="seam/resource/remoting/interface.js?customerAction&accountAction"
></script
>
代わりに、 必要な Javascript のインポートに s:remote
を使用することもできます。 インポートするコンポーネントあるいはクラス名をそれぞれコンマで区切ります。
<s:remote include="customerAction,accountAction"/>
クライアント側からのコンポーネントとのやりとりは、 すべて Seam
Javascript オブジェクト経由で行われます。 このオブジェクトは remote.js
に定義され、 コンポーネントに対する非同期呼び出しに使用します。 オブジェクトは 二つの機能に区分されます。 コンポーネントと連携するメソッドを含む Seam.Component
そして、リモート要求を実行するメソッドを含む Seam.Remoting
です。 このオブジェクトに精通する一番容易な方法は、 簡単なサンプルから始めることです。
Seam
オブジェクトがどのように動作するかを見るために、 簡単なサンプルを通じて一歩を踏み出してみましょう。 まず最初に、helloAction
と呼ばれる新しい Seam コンポーネントを作成しましょう。
@Stateless
@Name("helloAction")
public class HelloAction implements HelloLocal {
public String sayHello(String name) {
return "Hello, " + name;
}
}
新しいコンポーネント用にローカルインタフェースも生成する必要があります。 @WebRemote
アノテーションに特に注意してください。 リモートによるメソッドへのアクセスを可能とするために必要です。
@Local
public interface HelloLocal {
@WebRemote
public String sayHello(String name);
}
That's all the server-side code we need to write.
If you are performing a persistence operation in the method marked @WebRemote
you will also need to add a @Transactional
annotation to the method. Otherwise, your method would execute outside of a transaction without this extra hint.That's because unlike a JSF request, Seam does not wrap the remoting request in a transaction automatically.
Now for our web page - create a new page and import the helloAction
component:
<s:remote include="helloAction"/>
ユーザーにとって完全にインテラクティブとなるようページにボタンを追加してみます。
<button onclick="javascript:sayHello()"
>Say Hello</button
>
ボタンをクリックしたとき、実際にボタンに何かを行わせるためのスクリプトをもう少し追加する必要があります。
<script type="text/javascript">
//<![CDATA[
function sayHello() {
var name = prompt("What is your name?");
Seam.Component.getInstance("helloAction").sayHello(name, sayHelloCallback);
}
function sayHelloCallback(result) {
alert(result);
}
// ]]>
</script
>
作業完了です! アプリケーションをデプロイして、ページを見てみましょう。 ボタンをクリックして、プロンプトが出たら名前を入力しましょう。 呼び出しの成功を確認するための hello メッセージが、メッセージボックスに表示されます。 少し時間を節約したいのであれば、 Seam の /examples/remoting/helloworld
ディレクトリにこの Hello World サンプルの全ソースコードがあります。
ところで、このスクリプトのコードは何をするのでしょうか。 もっと細かく分解してみましょう。手始めに、二つのメソッドを実装した Javascript コードから見ていきましょう。 最初のメソッドはユーザーに対して名前を入力するよう促し、リモート要求を行うのがその役割です。 以下の行から見てみましょう。
Seam.Component.getInstance("helloAction").sayHello(name, sayHelloCallback);
この行の最初の部分 Seam.Component.getInstance("helloAction")
は、 helloAction
コンポーネントのプロキシ、あるいは"スタブ"を返します。 このスタブに対してコンポーネントのメソッド呼び出しが可能です。 それは、まさにこの行の残りの部分 sayHello(name, sayHelloCallback);
になります。
コード行全体で行っていることは、コンポーネントのsayHello
メソッドの呼び出しと、 パラメータとしてname
を渡すことです。 二番目のパラメータsayHelloCallback
は、 このコンポーネントの sayHello
メソッドのパラメータではありません。 その代わり、Seam Remoting フレームワークが要求に対する応答を受けたら、 それを sayHelloCallback
Javascript メソッドに渡すべきことを指示します。 このコールバックパラメータは完全にオプションです。 戻り値 void
のメソッドを呼び出す場合、 あるいは結果を気にする必要がない場合は、 遠慮なくそのままにしてください。
sayHelloCallback
メソッドが、リモート要求に対するレスポンスを受信した場合、 メソッド呼び出しの結果を表示するアラートメッセージが現れます。
Seam.Component
Javascript オブジェクトは、 Seam コンポーネントと連携する多くのクライアントメソッドを提供します。 主な二つのメソッド、newInstance()
と getInstance()
は、 以降の章にも記述されていますが、 これらの主な違いは、newInstance()
は、いつもコンポーネントタイプの新しいインスタンスを生成し、そして、getInstance()
は、シングルトンのインスタンスを返すことです。
新しいエンティティ、あるいは、JavaBean コンポーネントインスタンスを生成するためにこのメソッドを使用します。 このメソッドにより返されるオブジェクトは、 サーバサイドの対応するものと同じ getter/setter メソッドを持つか、 あるいは、代替として、お望みならば、そのフィールドに直接アクセスが可能です。 例として、以下の Seam エンティティ コンポーネントをご覧ください。
@Name("customer")
@Entity
public class Customer implements Serializable
{
private Integer customerId;
private String firstName;
private String lastName;
@Column public Integer getCustomerId() {
return customerId;
}
public void setCustomerId(Integer customerId} {
this.customerId = customerId;
}
@Column public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@Column public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
クライアントサイド Customer を生成するために、以下のコードを記述します。
var customer = Seam.Component.newInstance("customer");
そして、ここからは customer オブジェクトのフィールドの設定が可能です。
customer.setFirstName("John");
// Or you can set the fields directly
customer.lastName = "Smith";
getInstance()
メソッドは、 Seam セッション Bean コンポーネントの、スタブへの参照を取得するために使用されます。 それは、コンポーネントに対してリモートのメソッド実行に使用可能です。 このメソッドは、特定のコンポーネントのシングルトンを返します。 その結果、続けて同じコンポーネント名で二回呼び出すと、同じコンポーネントインスタンスが返されます。
前記のサンプルから続けて、 新しいcustomer
を生成、保存しようとする場合、customerAction
コンポーネントのsaveCustomer()
メソッドにそれを渡します。
Seam.Component.getInstance("customerAction").saveCustomer(customer);
Seam Remoting の大部分のクライアントサイドの機能は、Seam.Remoting
オブジェクトに含まれます。 メソッドを直接呼ぶ必要はほとんどないとはいえ、 言及する価値のある重要なものがあります。
アプリケーションが Seam コンポーネントではない JavaBean のクラスを含むまたは使用する場合、 クライアント側ででこれらのタイプを作成してパラメータとしてコンポーネントメソッドに渡す必要があるかもしれません。 タイプのインスタンスを作成するために、 createType()
メソッドを使用してください。 パラメータとして、完全修飾の Java クラス名を渡してください。
var widget = Seam.Remoting.createType("com.acme.widgets.MyWidget");
Seam Remoting は EL 式の評価にも対応します。 サーバからのデータ取得にもうひとつ便利なメソッドを提供します。 Seam.Remoting.eval()
関数を使用して、 EL 式をサーバ上で遠隔に評価してその結果値をクライアント側のコールバックメソッドに返すことができます。 この関数は二つのパラメータを受け取ります。 一番目のパラメータは 評価対象となる EL 式となり、 二番目のパラメータはその式の値を付けて呼び出すコールバックメソッドになります。 次に例を示します。
function customersCallback(customers) {
for (var i = 0; i < customers.length; i++) {
alert("Got customer: " + customers[i].getName());
}
}
Seam.Remoting.eval("#{customers}", customersCallback);
この例では、 #{customers}
の式が Seam によって評価され、 その式の値 (この場合 Customer オブジェクトの一覧) がcustomersCallback()
メソッドに返されます。 このようにして返されるオブジェクトは Javascript で動作できるようそれ自体のタイプがインポートされていなければなりません (s:remote
)。 したがって、 customer
オブジェクトの一覧と動作させるには、 customer
タイプをインポートする必要があります。
<s:remote include="customer"/>
上記の設定のセクションでは、 インタフェースまたはコンポーネントの「スタブ」は seam/resource/remoting/interface.js
経由でページにインポートするか、 s:remote
を使用してインポートします。
<script type="text/javascript"
src="seam/resource/remoting/interface.js?customerAction"
></script
>
<s:remote include="customerAction"/>
ページにこのスクリプトをインクルードすることにより、 コンポーネントのためのインタフェース定義に加えて、コンポーネントのメソッドを実行するために必要なその他のコンポーネントとタイプが生成され、リモーティングフレームワークで使用可能になります。
生成可能なクライアントスタブには「実行可能」スタブと「タイプ」スタブの二タイプがあります。 実行可能スタブは動作を持ち、 セッション Bean コンポーネントに対するメソッドの実行に使用されます。 一方、 タイプスタブは状態を保持し、 パラメータとして渡すまたは結果として返すことができるタイプを表します。
生成されるクライアントスタブのタイプは Seam コンポーネントのタイプにより異なります。 コンポーネントがセッション Bean の場合、 実行可能スタブが生成されます。 これ以外、 エンティティや JavaBean となる場合にはタイプスタブが生成されます。 この規則には例外がひとつあります。 コンポーネントが JavaBean (つまり、セッション Bean や エンティティ Bean ではない場合) であり、 そのメソッドのいずれにも @WebRemote アノテーションが付く場合、 タイプスタブではなく実行可能スタブが生成されます。 これにより、 セッション Bean にアクセスできない非 EJB 環境で JavaBean コンポーネントのメソッドを呼び出すリモーティングが使用できるようになります。
Seam リモートコンテキストは、 リモーティングの要求 / 応答サイクルの一部として送受信される追加情報を含んでいます。 現段階では対話 ID だけしか含んでいませんが、将来拡張される可能性があります。
対話スコープでリモート呼び出しをしようとする場合、 Seam Remotingコンテキスト内にある対話ID の読み込みと設定が行える必要があります。リモート要求の後に対話 ID を読み込むためには、Seam.Remoting.getContext().getConversationId()
を呼び出します。 要求の前に対話ID を設定するためには、Seam.Remoting.getContext().setConversationId()
を呼び出します。
対話ID が明示的に Seam.Remoting.getContext().setConversationId()
で設定されない場合、 リモート呼び出しによって返される最初の有効な対話ID が自動的に割り当てられます。 ページ内で複数の対話ID を使用する場合は、それぞれの呼び出しの前に対話IDを明示的に設定する必要があるかもしれません。 一つの対話だけを使用する場合は、 特別なことをする必要はありません。
Seam リモーティングは、複数のコンポーネント呼び出しが一つの要求内で実行されることを可能にします。 ネットワークトラフィックを減少することが適切であれば、 どこでもこの特徴を使用することを推奨します。
Seam.Remoting.startBatch()
メソッド は、 新たなバッチを起動します。 バッチ起動後に実行されたコンポーネント呼び出しは、 即座に送られるのではなく、キューイングされます。 必要とされるすべてのコンポーネント呼び出しがバッチに追加されたとき、Seam.Remoting.executeBatch()
メソッドは、 サーバにキューイングされた呼び出しすべてを含む一つの要求を送信するでしょう。 そして、そこで順番に実行されます。 呼び出しが実行された後、 すべての戻り値を含む一つの応答は、 クライアントに返され、コールバック機能が (もし、設定されていれば) 実行と同じ順番で起動されます。
startBatch()
メソッドで新たなバッチを起動したが要求を送らないことにした場合、 Seam.Remoting.cancelBatch()
メソッドはキュー待ちしているすべての呼び出しを破棄してそのバッチモードを終了します。
バッチが利用されているサンプルを見るには、/examples/remoting/chatroom
を参照ください。
この章は、基本データタイプのサポートについて述べています。 サーバサイドではこれらの値は、一般的にプリミティブタイプ、あるいは、対応するラッパクラスと互換性があります。
Java でサポートされているすべての数値タイプにサポートがあります。 クライアント側では数値は常に String 表現としてシリアライズされ、 サーバ側で適切な目的とするタイプに変換されます。 プリミティブまたはラッパーいずれかのタイプへの変換は、 Byte
、 Double
、 Float
、 Integer
、 Long
、 Short
の各タイプに対してサポートされます。
一般的に JavaBeans は Seam エンティティ、 JavaBean コンポーネント、 または non-component クラスのいずれかになります。 オブジェクトの新しいインスタンスの生成には適切なメソッドを使用してください (Seam コンポーネントには Seam.Component.newInstance()
、 これ以外は Seam.Remoting.createType()
)。
パラメータが、このセクションの別の場所で記述されたその他の有効なタイプの一つではない場合、 これら二つのメソッドのどちらかによって生成されるオブジェクトだけがパラメータ値として使用されるべきであることに気づくことが重要です。 いくつかの状況では、 以下のように厳密にパラメータタイプを決定できないコンポーネントメソッドがあるかもしれません。
@Name("myAction")
public class MyAction implements MyActionLocal {
public void doSomethingWithObject(Object obj) {
// code
}
}
この場合、 myWidget
コンポーネントのインスタンスを渡したいところですが、 myAction
のインタフェースはそのいずれのメソッドからも直接参照されないため myWidget
を含みません。 これを回避するには、 MyWidget
を明示的にインポートする必要があります。
<s:remote include="myAction,myWidget"/>
これにより myWidget
オブジェクトが Seam.Component.newInstance("myWidget")
で作成されるようになり、 myAction.doSomethingWithObject()
に渡されます。
日付の値は、 ミリ秒単位まで正確な String 表示にシリアライズされます。 クライアント側では Javascript Date オブジェクトを使って日付値と動作させます。 サーバ側では java.util.Date
を使用します (または java.sql.Date
や java.sql.Timestamp
などの下位クラス)。
クライアント側では、 Enum は String と同様に扱われます。 Enum パラメータの値を設定する場合は単純に enum の String 表現を使います。 次のコンポーネントを例として参照してください。
@Name("paintAction")
public class paintAction implements paintLocal {
public enum Color {red, green, blue, yellow, orange, purple};
public void paint(Color color) {
// code
}
}
paint()
メソッドを red
の色を使って呼び出すには、 String のままでパラメータ値を渡します。
Seam.Component.getInstance("paintAction").paint("red");
逆もまた同じことが言えます。 つまり、 コンポーネントメソッドが enum パラメータを返す場合 (または返されるオブジェクトグラフのどこかに enum フィールドを含む場合)、 クライアント側では String として表示されます。
Bag は配列、 コレクション、 リスト、 セットなどすべての集合タイプを対象とし (ただし Map は除く、 これについては次のセクションを参照)、 Javascript 配列としてクライアント側で実装されます。 パラメータとしてこれらのタイプのいずれかを受け取るコンポーネントメソッドを呼び出す場合、 使用するパラメータは Javascript アレイにします。 コンポーネントメソッドがこれらのタイプのいずれかを返す場合は、 戻り値も Javascript 配列になります。 このリモーティングフレームワークは、 サーバ側で bag をコンポーネントメソッドコールに対して適切なタイプに変換することが可能です。
Javascript 内では Map に対するネイティブのサポートはないため、 シンプルな Map 実装が Seam Remoting フレームワークで提供されます。 リモートコールに対するパラメータとして使用できる Map を作成するには、 新たに Seam.Remoting.Map
オブジェクトを作成します。
var map = new Seam.Remoting.Map();
この Javascript 実装では Map と動作することを目的とした基本的なメソッド、 size()
、 isEmpty()
、 keySet()
、 values()
、 get(key)
、 put(key, value)
、 remove(key)
、 contains(key)
を提供します。 それぞれのメソッドは Java のそれと同等になります。 メソッドが keySet()
および values()
などの一集合を返すと、 そのキーまたは値オブジェクトを含む Javascript Array オブジェクトが返されます。
バグの追跡を支援する目的で、 ポップアップウィンドウ内でクライアントとサーバ間を行ったり来たりするすべてのパケットの内容を表示するデバッグモードを有効にすることができます。 デバッグモードを有効にするには、 次のいずれかを行います。 Javascript 内で setDebug()
メソッドを実行する方法は次の通りです。
Seam.Remoting.setDebug(true);
components.xml を使って設定を行う方法は次のようになります。
<remoting:remoting debug="true"/>
デバッグ機能をオフにするには、 setDebug(false)
を呼び出します。 独自のメッセージをデバッグログに書き込みたい場合は、 Seam.Remoting.log(message)
を呼び出します。
When invoking a remote component method, it is possible to specify an exception handler which will process the response in the event of an exception during component invocation. To specify an exception handler function, include a reference to it after the callback parameter in your JavaScript:
var callback = function(result) { alert(result); }; var exceptionHandler = function(ex) { alert("An exception occurred: " + ex.getMessage()); }; Seam.Component.getInstance("helloAction").sayHello(name, callback, exceptionHandler);
If you do not have a callback handler defined, you must specify null
in its place:
var exceptionHandler = function(ex) { alert("An exception occurred: " + ex.getMessage()); }; Seam.Component.getInstance("helloAction").sayHello(name, null, exceptionHandler);
The exception object that is passed to the exception handler exposes one method, getMessage()
that returns the exception message which is produced by the exception thrown by the @WebRemote
method.
画面の上部右端にデフォルトで表示されるローディングメッセージは、 変更、 レンダリングのカスタマイズ、 完全にオフにするなどが可能です。
デフォルトの "Please Wait..." というメッセージを別のメッセージに変更するには、 Seam.Remoting.loadingMessage
の値を設定します。
Seam.Remoting.loadingMessage = "Loading...";
ローディングメッセージを完全に表示させないようにするには、 displayLoadingMessage()
および hideLoadingMessage()
を何も行わない機能で上書きします。
// don't display the loading indicator
Seam.Remoting.displayLoadingMessage = function() {};
Seam.Remoting.hideLoadingMessage = function() {};
ローディングインジケータを上書きしてアニメのアイコンの他、 好きなものを表示させることができます。 displayLoadingMessage()
と hideLoadingMessage()
の各メッセージを独自の実装で上書きしてこれを行います。
Seam.Remoting.displayLoadingMessage = function() {
// Write code here to display the indicator
};
Seam.Remoting.hideLoadingMessage = function() {
// Write code here to hide the indicator
};
リモートメソッドが実行されると、 その結果はクライアントに返される XML レスポンスにシリアライズされます。 この応答は次にクライアントにより Javascript オブジェクトにアンマーシャルされます。 他のオブジェクトへの参照を含む複雑なタイプの場合 (Javabeans など)、 こうした参照されるオブジェクトもすべて応答の一部としてシリアライズされます。 これらのオブジェクトは他のオブジェクトを参照することができ、 またこの他のオブジェクトはその他のオブジェクトを参照できるといった具合になります。 チェックしないままにしておくと、 このオブジェクト「グラフ」はオブジェクト間で存在する関係によっては非常に膨大なものになる可能性があります。 派生的な問題として (応答が冗長となる問題とは別)、 クライアントに対して機密情報が公開されてしまうのを防ぎたい場合もあるかもしれません。
Seam Remoting は、 リモートメソッドの @WebRemote
アノテーションの exclude
フィールドを指定することでそのオブジェクトグラフを「制約する」シンプルな方法を提供しています。 このフィールドはドット (「.」) 表記を使って指定されるパスまたは複数のパスを含む String 配列を受け取ります。 リモートメソッドを呼び出すと、 これらのパスと一致する結果となるオブジェクトグラフ内のオブジェクトがシリアライズされる結果パケットから除外されます。
すべての例で次の Widget
クラスを使用します。
@Name("widget")
public class Widget
{
private String value;
private String secret;
private Widget child;
private Map<String,Widget> widgetMap;
private List<Widget> widgetList;
// getters and setters for all fields
}
リモートメソッドが Widget
のインスタンスを返すけれど secret
フィールドには機密情報が含まれているため公開したくない場合、 次のように制約します。
@WebRemote(exclude = {"secret"})
public Widget getWidget();
「secret」の値は返されるオブジェクトの secret
フィールドを参照します。 ここで、 クライアントに対してこの特定フィールドが公開されても構わないと仮定します。 返される Widget
値には child
フィールドがあり、 これも Widget
になります。 代わりに child
の secret
値を隠したい場合はどうしたらよいでしょうか。 ドット表記を使用して結果となるオブジェクトグラフ内のこのフィールドのパスを指定することができます。
@WebRemote(exclude = {"child.secret"})
public Widget getWidget();
オブジェクトグラフ内にオブジェクトが存在できるその他の場所は Map
、 あるいはなんらかの集合の種類内になります (List
、 Set
、 Array
など)。 集合は簡単で、 その他のフィールドと同様に扱えます。 たとえば、 Widget
の widgetList
フィールド内に他の Widget
一覧が含まれていて、 この一覧の Widget
の secret
フィールドを制約している場合、 アノテーションは次のようになります。
@WebRemote(exclude = {"widgetList.secret"})
public Widget getWidget();
Map
のキーまたは値を制約する場合の表記は少し異なります。 Map
のフィールド名の後ろに [key]
を付け加えると Map
のキーオブジェクト値を制約し、 [value]
は値オブジェクトの値を制約します。 次の例では widgetMap
フィールドの値に制約された secret
フィールドを持たせる方法を示しています。
@WebRemote(exclude = {"widgetMap[value].secret"})
public Widget getWidget();
最後に、結果となるオブジェクトグラフ内のどこに出現するかに関係なくオブジェクトタイプのフィールド制約に使用できる表記について説明します。 この表記はコンポーネント名 (オブジェクトが Seam コンポーネントである場合) または完全修飾クラス名 (オブジェクトが Seam コンポーネントではない場合のみ) のいずれかを使用し角括弧を使って表現されます。
@WebRemote(exclude = {"[widget].secret"})
public Widget getWidget();
By default there is no active transaction during a remoting request, so if you wish to perform database updates during a remoting request, you need to annotate the @WebRemote
method with @Transactional
, like so:
@WebRemote @Transactional(TransactionPropagationType.REQUIRED) public void updateOrder(Order order) { entityManager.merge(order); }
Seam Remoting は JMS メッセージングに対して実験的にサポートを提供しています。 本セクションでは現在実装されている JMS サポートについて記載していますが、 今後、 変更される可能性があるので注意してください。 現在、 この機能を実稼働環境下で使用することは推奨されていません。
JMS トピックをサブスクライブする前に、 まず Seam Remoting でサブスクライブさせることができるトピック一覧を設定する必要があります。 seam.properties
、 web.xml
または components.xml
の org.jboss.seam.remoting.messaging.subscriptionRegistry.allowedTopics
配下にあるトピックを一覧表示させます。
<remoting:remoting poll-timeout="5" poll-interval="1"/>
次の例では JMS Topic へのサブスクライブ方法を示しています。
function subscriptionCallback(message)
{
if (message instanceof Seam.Remoting.TextMessage)
alert("Received message: " + message.getText());
}
Seam.Remoting.subscribe("topicName", subscriptionCallback);
Seam.Remoting.subscribe()
メソッドは二つのパラメータを受け取ります。 一つ目はサブスクライブする JMS Topic 名になり、 二つ目はメッセージが受け取られると呼び出すコールバック機能になります。
サポートされているメッセージは二種類で、 テキストメッセージとオブジェクトメッセージです。 コールバック機能に渡されるメッセージタイプのテストを必要とする場合は、 instanceof
演算子を使ってメッセージが Seam.Remoting.TextMessage
なのか Seam.Remoting.ObjectMessage
であるのかをテストすることができます。 TextMessage
はその text
フィールドにテキスト値を含み (または代わりに getText()
を呼び出す)、 ObjectMessage
はその value
フィールドにオブジェクト値を含みます (またはその getValue()
メソッドを呼び出す)。
トピックのサブスクライブを中止するには、 Seam.Remoting.unsubscribe()
を呼び出してトピック名で渡します。
Seam.Remoting.unsubscribe("topicName");
ポーリングの発生方法を制御するために変更できるパラメータが二つあります。 一つ目は Seam.Remoting.pollInterval
で、 新しいメッセージに対して後続ポールが発生する間隔を制御します。 秒単位で表現します、 デフォルト設定は 10 になります。
二つ目のパラメータは Seam.Remoting.pollTimeout
で、 このパラメータも秒単位で表現されます。 サーバへの要求がタイムアウトして空白の応答を送信するまでの新しいメッセージを待機する長さを制御します。 デフォルトは 0秒で、 サーバがポールされると配信できるメッセージがない場合は空白の応答が直ちに返されます。
pollTimeout
値を高く設定する場合は注意が必要です。 各リクエストがメッセージを待機する必要があるということは、 メッセージが受信されるまでまたはその要求がタイムアウトするまでサーバスレッドが固定されるということになります。 こうした要求が同時に多数発生すると、 大量のスレッドが固定される結果になります。
これらのオプションは components.xml 経由で設定することを推奨しますが、 必要に応じて Javascript で上書きすることができます。 次の例ではポーリングがかなりアグレッシブに発生するよう設定する方法を示しています。 これらのパラメータはご使用のアプリケーションに適切な値を設定してください。
components.xml:
<remoting:remoting poll-timeout="5" poll-interval="1"/>
JavaScript:
// Only wait 1 second between receiving a poll response and sending the next poll request.
Seam.Remoting.pollInterval = 1;
// Wait up to 5 seconds on the server for new messages
Seam.Remoting.pollTimeout = 5;