AS3SXとは、FDTを開発しているPowerFlasherが始めた新しいサービスで、サーバーサイドをActionScriptで書いたswfで動作させようというものだ。
APIの他に(今後どうなるかはわからないが)swfをアップロードするサーバーとデータベースが無料で使える。
AS3SXに対して最初の反応、概要はこんなかんじだったようだ
togetter "サーバーサイドASのAS3SXがちょっと凄そうな件についてのまとめ"
また、AS3SXの動作などについての考察がこちらのお二方でされているので併せて読でおこう。
Rest-term "AS3SXはPaaSとして成功するか"
ちょっとさわってみた感じ、なかなか面白く、ActionScriptで簡単にサーバーサイドの動きを表現できることがわかったので、簡単な使い方を書いてみる。
まずは右のほうにあるswcをダウンロードしよう。
次に右上のRegisterでEmailとPasswordを入れて登録をする。
登録が終わり、ログインするとこのような画面になる。
これがAS3SX Admin Centerで、自分のプロジェクトを管理するホーム画面だ。
新しいプロジェクトを作成する。ただし、既存プロジェクトは削除することができないのであまり無駄に作りすぎると管理が大変になるので注意。
サーバーサイドのswfをアップロードする。また、このページを開いたまま、アップロードに指定したswfが更新されると、勝手にアップロードしなおされるようだ。アップロードが終わったらすぐにAdmin Centerに戻るほうがいいかもしれない。
プロジェクトの設定を変更できる。変更できる内容は
また、このメニューでEndpointが表示される。クライアントからサーバーに接続するのに必要なので、ここに表示されることを覚えておこう。
Save Web Appを押すと設定が保存される。たまにエラーになる。
プロジェクトがデバッグモードの時にエラーやtrace結果が表示される。タイムスタンプやエラー表記はドイツ基準なので注意。
だいたい9時間たせば日本の時刻になる。分数(ふんすう)は日本とほぼ同じなので、簡易的にそこを見よう。
Databaseを操作する。コレクションとその中の各ドキュメントを見ることが出来る。
ドキュメントに関しては、新規挿入、削除、内容の直接編集を行うことができる。コレクションは削除できないようだ。
最初の状態ではコレクションが追加されていないのでなにも表示されない。
それでは実際にAS3SXをどうやって動かしていくのか見てみよう。
いろいろ足りないドキュメントはこちら。
基本的な流れとしては、サーバーサイドとクライアントサイド、2つのswfを作り、サーバーサイドのほうをAdmin Centerでアップロードし、クライアントサイドを実行して使う。
クライアントサイドからサーバーサイドに送られるデータをリクエスト、サーバーサイドからクライアントサイドに送られるデータをレスポンスという。
まず、使うクラスは基本的に2つ。ドキュメントにまっさきに表示されているClientAS3SXとServerAS3SXだ。だいたいの機能がこの2クラスに集約されているので最初のうちはこれだけでたいていのことができる(ServerTracも使うけど)。
名前からわかるとおり、クライアントサイドではClientAS3SX、サーバーサイドではServerAS3SXを使う。
ClientAS3SXクラスには3つのメソッドしかなく、動作も明確なので覚えるのは簡単だ。
だいたい以下のような働きをする。
まず、クライアントswfがサーバーswfに接続しなくてはならない。
そこでsetEndPointメソッドを使う。引数はStringで、Edit App Settingsに表示されていたURLをそのまま文字列にして渡す。
通常http://as3sx.com/Apps/長ったらしい16進数/のようになっているので、そのまま
ClientAS3SX.setEndPoint("http://as3sx.com/Apps/長ったらしい16進数/");
とする。この命令でサーバーswfと通信を開始する(定かではないが、動作についての詳しい考察は馬鹿全さんの記事を参照)。
クライアントサイドでは最初にこの命令が絶対必要だが、一度実行すればもう使うことはない。
次に、サーバーサイドから送られてくるレスポンスに備えてsetResponseHandlerでハンドラメソッドを登録する。
このメソッドには第一引数にレスポンスとして送られてくるであろうデータのクラスを、第二引数にそのクラスのレスポンスが送られてきた時に実行するハンドラメソッドを渡す。
また、渡すハンドラメソッドは第一引数に、そのレスポンスのクラスのオブジェクトを受け取り、voidを返すものにする。
ClientAS3SX.setResponseHandler(Response,onResponse);
private function onResponse(response:Response):void{
}
こうすると、カスタムのResponseクラスがレスポンスとしてサーバーサイドから送られてきた際にonResponseメソッドを実行してくれる。そして第一引数responseで送られてきたResponseクラスオブジェクトを参照することができる。addEventListenerのようなものだ。
最後にsendRequestメソッドでサーバーサイドにリクエストを送る。第一引数には好きなクラスのオブジェクトを渡すことができる。ここで渡したオブジェクトはサーバーサイドのリクエストハンドラメソッドでそのまま使うことができる、とても便利な設計だ。
ClientAS3SX.sendRequest(new Request());
これでRequestクラスオブジェクトをそのままサーバーサイドに送信することができる。
以上。クライアントサイドでやったことはサーバーとの接続、レスポンスに反応するメソッドの登録、リクエストの送信。これだけだ。
もひとつ、ClientAS3SX.userIdでクライアントのGUIDを取得することができる。このGUIDはサーバーがクライアントを一意に識別するためのもので一度クライアントを起動したら終了するまでかわることはない。使うときがそのうちくるかもしれないので取得方法だけ覚えておこう。
ServerAS3SXクラスでは、とりあえず基本的に使うのは2つのメソッドしかない。
すぐに閃くと思うが、この2つのメソッドはクライアントで使った似た名前のものとまったくいっしょだ。
ServerAS3SX.setRequestHandler(Request,onRequest);
private function onRequest(request:Request):void{
}
これで、カスタムのRequestクラスがリクエストとしてクライアントサイドから送られてきた際にonRequestメソッドを実行し、その中で第一引数requestによって送られてきたRequestクラスオブジェクトを参照することができる。
ServerAS3SX.sendResponse(new Response());
これでResponseクラスオブジェクトをそのままクライアントサイドに送信することができる。
sendResponseの方は、第二引数にGUIDのStringを渡すことで、送り先をそのGUIDのクライアントに設定することができる。デフォルトではnullが渡され、リクエストハンドラが反応したリクエストを送ってきたクライアントになる(つまり返信のような形になる)。
サーバーサイドでやったことはリクエストに反応するメソッドの登録、レスポンスの送信。
クライアントサイドと合わせて、このようなリクエストとレスポンスのキャッチボールでサーバーサイドASを実現することができる。
最後に、リファレンスには現在ないが、サーバーサイドでServerTrace.trace(文字列)でAdmin CenterのViewLogに文字列を出力することができる(サーバーサイドのRun Modeがデバッグの時)。また、クライアントサイドがデバッグモードだとそちらでも表示される。サーバーサイドのデバッグは基本的にこのメソッドを使うことにな。
しかし動作が不安定で、1フレームで多数呼ぶと出力されないことが多い。そのことによってサーバーサイドの動作が途中で止まることもあるので、ServerTrace.traceはなるべく少ない回数。1フレームで1回か多くとも2回にとどめておくべきだ。また、意図した動作をしないときにサーバーサイドのServerTrace.traceを消してアップロードしなおすと正常な動作になることもあるので、バグ解決の可能性として頭の片隅においておこう。
それではAPIの使い方が分かったところで実際にプロジェクトを作ってみよう。
今回作るのはこんなかんじ
(初回起動に少し時間がかかるかもしれないが)ボタンを押すとサーバーから文字列が返り、それを表示するものだ。
馬鹿全さんがAS3SX用のFlashDevelopeプロジェクトテンプレートを作ってくれている。
setEndPointまで書いてくれてあり、かなり便利で作業が簡単になるのでFlashDvelopeの人はこれを使おう
今回はサーバーとクライアントが通信をするだけの簡単なものを作る。宣言通りminimalcompsについては説明しない。
package { import com.as3sx.connection.SocketConnection; import com.bit101.components.PushButton; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.text.TextField; import flash.text.TextFieldAutoSize; /** * ... * @author */ public class ClientMain extends Sprite { /// change endpoint private static const END_POINT:String = "http://as3sx.fdt.powerflasher.com/Apps/ほにゃらら/"; private var tf:TextField; public function ClientMain():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point ClientAS3SX.setEndPoint(END_POINT); addEventListener(Event.ENTER_FRAME, connectionCheck); } private function connectionCheck(e:Event):void { if (SocketConnection.instance.connected){ removeEventListener(Event.ENTER_FRAME, connectionCheck); // connected new PushButton(this, 0, 0, "Request", onPush); tf = new TextField(); tf.autoSize = TextFieldAutoSize.LEFT; tf.y = 40; addChild(tf); ClientAS3SX.setResponseHandler(String, onString); } } private function onPush(e:MouseEvent):void { ClientAS3SX.sendRequest(true); } private function onString(str:String):void { tf.text = str + "\n" + tf.text; } } }
まずinitメソッドでsetEndPointをしている。この値END_POINTは人(とプロジェクト)によって違うものなので自分で確認して入れよう。
その後connectionCheckで接続が確認されたら(馬鹿全さんの記事参照)ボタンとテキストフィールドを作る。ボタンのハンドラにはsendRequestを書いてある。今回特に送りたい情報はなく、ただ単にサーバーにレスポンスの要求を伝えるだけなので、適当にBoolean型のtrueを送ってみよう。
これでボタンを押すたびにtrueがリクエストとしてサーバーに送られる。
同時に、サーバーのレスポンスに備えてsetResponseHandlerをしておく。文字列がレスポンスとして返ってくる予定なので、Stringクラスを登録しよう。
ハンドラメソッドではStringクラスのstrを第一引数に受けるようにし、メソッド内ではこのstrを参照して送られてきた文字列を改行し、テキストフィールドの上に追加して表示させる。
package { import com.as3sx.log.ServerTrace; import flash.display.Sprite; /** * ... * @author */ public class ServerMain extends Sprite { public function ServerMain():void { ServerAS3SX.setRequestHandler(Boolean, onBoolean); } private function onBoolean(bool:Boolean):void { ServerTrace.trace(bool); ServerAS3SX.sendResponse("Hello world!"); } } }
サーバーサイドではコンストラクタでsetRequestHandlerをしてある。クライアントサイドからのリクエストはBooleanで送っていたので、こちらもBooleanで受ける。
これでサーバーサイドswf起動時にBooleanクラスのハンドラが登録される。
Booleanのリクエストに対するハンドラメソッドでは、まず実験のために第一引数boolをServerTraceしてみよう。クライアントサイドでtrueを送っているので、これでView Logにtrueが表示されるはずだ。
そしてsendRequestでは、クライアントサイドでStringをレスポスとして受け取るよう設定したので、こちらも文字列"Hello world!"を送る。第二引数は指定しないことでそのままリクエストの送り主に返すことができる。
以上によりクライアントサイドからBooleanクラスのリクエストがあるたびにStringのレスポンスを送り返す。
クライアントサイドとサーバーサイド、これら二つをコンパイルし、サーバーサイドswfをAdmin Centerでアップロードしよう。
これでクライアントのswfを実行し、ボタンを押すと、クライアントにないはずの文字列"Hello world!"が返ってくる。またAdmin CenterのView Logをみると、ボタンを押すたびに確かにtrueが出力されているのもわかる。
今回、簡単のためsendRequestとsendResponseの第一引数にビルトインのクラスを使っているが、多くのクラスを登録することになるとややこしくなるので、基本的にはリクエスト用、レスポンス用またはどっちにも使う用のカスタムクラスを自分で作ってそこにデータを入れ、送信するほうが良いだろう。
今回のプロジェクトのソースファイルはこちら。setEndPointの引数は変えてあるので注意。
このように、簡単にサーバーサイドをAction Scriptで実現できるのがわかっただろうか。
特にオブジェクトをそのまま送れ、受け取り側でアクセスできるというのが非常に簡単で魅力的だ。
おおまかな使い方は今回のようなリクエストとレスポンスのキャッチボールだが、他にもいくつか便利な機能がついている。
次回以降はそれらに焦点を当てる予定だ。
Author:9ballsyn
ActionScriptについて
最近はMolehill