StaxでBlazeDSを始めてみる
http://www.stax.net/
Staxは簡単に言えばGoogle App EngineのJava版みたいなものです。
今のところ無料でJavaサーバサイドの環境で開発できちゃいます。
情報があんまり無いのでこれからちょっとずつ書いていこうと思います。
Staxで開発を始める前に
まず、上のリンクの"Apply for the Beta"をクリックしてメールを送ります。
すると招待コードが送られてくるのでメールのリンクからユーザ登録をします。
あとはここからSDKをダウンロードしてホームディレクトリにでも展開しましょう。
Unix系の場合はパスを通す必要があります。例えば僕が使っているzshの場合は~/.zshrcに
export STAX_HOME=~/stax-sdk-0.2.14 PATH=$STAX_HOME:$PATH
と追加しました。Windowsの場合はコンソールへのリンクがあるのでそれを使うとパスが通っているので使う必要がありません。
他のコマンドプロンプトから実行したい場合はUnix系と同様にpathを通す必要があると思います。
BlazeDSを使ってみる
こちらのページはアプリケーションコンソールとしてログインすると表示されますが、
アプリケーションを作りたい場合は左上の"Create App"をクリックします。アプリケーション名を決めて、開発フレームワークを決定します。
僕は一度試してみたかったのでBlazeDSを選択しました。
あとはアプリケーションコンソール上に書いてあるように、先ほどのSDKのディレクトリから
stax getapp -a ユーザ名/アプリケーション名 -u ユーザ名 -p パスワード
とすると、自動的に必要なライブラリやファイル等がダウンロードされます。
今後はこれを使って開発していきます。
まずサンプルを動かしてみよう
stax compile
でJavaとFlexのファイルがコンパイルされます。
そして、
stax run
とするとアプリケーションがローカルサーバhttp://localhost:8080/で立ち上がります。
今回はこのアプリケーションを少しだけ改造してみます。
BlazeDSは全体的にどうなってんだ
まず大事なファイル等について以下に書いておきます。
(色々と間違ってるかもしれないので注意)
- ソースファイル
- srcディレクトリとflex-srcディレクトリ
- web.xml
- webapp/WEB-INFディレクトリ
- 設定ファイルのトップとなる
- サーブレットやリソースとかを定義
- 設定ファイルの中間職みたいな存在
- サービスを定義
- Long Pollとかの設定はここで行う
- BlazeDSでCometを構築したいときは設定が必要。
- 今回はデフォルトのままで大丈夫
- 設定ファイルでは下っ端だが大事
- FlexからJavaを呼ぶ際のJavaのクラスへの対応の定義を書いたりする
- だからJavaのクラスが増えたらちゃんと追記しないといけない
- 今回はデフォルトのままで大丈夫
- 実はこれが一番大事な設定ファイルかもしれない
- データベースを使うときに追記する必要がある
他にもいろいろありますが、基本的にこれらのファイルに対して処理していく流れになります。
データベースを使ってみよう!!
StaxではデータベースとしてMySQLを使っています。
ここではJavaから処理してみたいと思います。(JDBCを使う)
まず、データベースをアプリケーションコンソールで作成しましょう。
左上の"Create DB"をクリックすると作成できます。ユニークなデータベース名、パスワードなどを入れます。
すると中央の"Cribsheet Snippets"という場所で使用方法が載っているので、それを参考にファイルに追記していきます。
このときパスワードとかが丸見えなので注意しましょう。(それもどうかと思うが…)
ここではデータベース名をhogehogeとしておきました。
上の部分をstax-application.xmlに、下の部分をweb.xmlに追加しておきます。
これでデータベースを使用する準備ができたので、実際に使用する場合はCode samplesを参考にするといいと思います。
僕の作ったサンプル改造も置いておきます。
/src/example/HelloWorldService.java
package example; import java.util.HashMap; import javax.naming.*; import javax.sql.*; import java.sql.*; public class HelloWorldService { //これはサンプルそのまま public HashMap<String, String> getData(String message) { HashMap<String, String> data = new HashMap<String, String>(); data.put("clientMessage", message); data.put("serverResponse", "Hello from HelloWorldService"); return data; } //データベースを作成する例 public void createDB(){ try { Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/hogehoge"); Connection conn = ds.getConnection(); Statement stmt = conn.createStatement(); String sql = "CREATE TABLE testTable" + "(hoge INTEGER PRIMARY KEY, " + "fuga varchar(50)," + " piyo varchar(50) )"; stmt.execute(sql); sql = "INSERT INTO testTable" +"(hoge,fuga,piyo) " + "VALUES(1,'hoga','hogera')"; stmt.executeUpdate(sql); sql = "INSERT INTO testTable" +"(hoge,fuga,piyo) " + "VALUES(2,'bar!!','foo!!')"; stmt.executeUpdate(sql); sql = "INSERT INTO testTable" +"(hoge,fuga,piyo) " + "VALUES(3,'太郎','花子')"; stmt.executeUpdate(sql); conn.close(); System.out.println("created database."); }catch(Exception e){ System.out.println(e.toString()); } } //データを参照する例 public HashMap<String, String> viewDB(){ HashMap<String, String> data = new HashMap<String, String>(); try { Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/hogehoge"); Connection conn = ds.getConnection(); Statement stmt = conn.createStatement(); ResultSet rst = stmt.executeQuery("select hoge, fuga, piyo from testTable"); int num = 0; while(rst.next()) { int hoge = rst.getInt(1); String fuga= rst.getString(2); String piyo = rst.getString(3); num++; data.put("hoge"+num,Integer.toString(hoge)); data.put("fuga"+num,piyo); data.put("piyo"+num,fuga); } conn.close(); }catch(Exception e){ data.put("error",e.toString()); } return data; } }
/flex-src/main.mxml (ほぼサンプル通り)
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()"> <mx:Script> <![CDATA[ import mx.messaging.Channel; import mx.messaging.ChannelSet; import mx.messaging.channels.AMFChannel; import mx.rpc.events.ResultEvent; import mx.managers.BrowserManager; import mx.managers.IBrowserManager; import mx.utils.URLUtil; public function init():void { //initialize the RemoteObjects with the channel //TODO: is there away to avoid this step? var browserManager:IBrowserManager = BrowserManager.getInstance(); browserManager.init("", "Welcome!"); var baseURL:String = null; var protocol:String = URLUtil.getProtocol(browserManager.url); if(protocol == "file") baseURL = "http://localhost:8080"; else baseURL = protocol + "://" + URLUtil.getServerNameWithPort(browserManager.url); var cs:ChannelSet = new ChannelSet(); var customChannel:Channel = new AMFChannel("my-amf", baseURL + "/messagebroker/amf"); cs.addChannel(customChannel); helloRO.channelSet = cs; } private function getDataResultHandler(event:ResultEvent):void { resultText.text = dump(event.result); } private function viewDBResultHandler(event:ResultEvent):void { resultText.text = dump(event.result); } private function dump(obj:Object):String { var dumpStr:String = ""; for(var key:String in obj) { dumpStr += key + " = " + obj[key] + "\n"; } dumpStr += ""; return dumpStr; } ]]> </mx:Script> <mx:Button label="Send Message" click="helloRO.getData(clientMessage.text)" y="33" right="78"/> <mx:Button label="Create Data" click="helloRO.createDB()" y="60" right="88"/> <mx:Button label="View Data" click="helloRO.viewDB()" y="60" right="0"/> <mx:RemoteObject id="helloRO" destination="HelloWorldService"> <mx:method name="getData" result="getDataResultHandler(event)"/> <mx:method name="createDB"/> <mx:method name="viewDB" result="viewDBResultHandler(event)"/> </mx:RemoteObject> <mx:TextInput y="33" id="clientMessage" text="Hello World" left="78" right="192"/> <mx:Label y="75" text="Result from server" left="78"/> <mx:TextArea id="resultText" y="94" height="186" left="78" right="78" editable="false"/> </mx:Application>
ポイントは
ところです
作ったものをアップしたい
stax deploy -u ユーザ名 -p パスワード
これでアップできます!!
今回作ったのは
http://testblazeds.voidy21.staxapps.net/
です。