成らぬは人の為さぬなりけり

エンジニアライフをエンジョイする為のブログ

PhantomJs+Vert.x(JRuby)でSockJsの疎通確認をしてみる

さて今回は、最近なにかとよく見るPhantomJsを使ってみようと思います。

背景

今、ちょっといろいろあって、
Vert.x+SockJsをやろうとしるんですが、以下のような問題が、、、

  • SockJsのクライアントがブラウザ用かnode.js用しかない
  • node.js用は、XHRStreamingにしか対応していない
  • Websocketで複数クライアントつなぐテストをしたい

そこで、PhantomJsを使ってブラウザからWebsocketでつなげてみよう、
と思って今回やってみました。

環境

  • MacOSX 10.8.3
  • PhantomJs 1.9.0
  • Vert.x 1.3.1-final
  • JRuby 1.7.3

手順

今回は以下の様な流れでいきたいと思います。

  1. HomebrewでPhantomJsインストール
  2. HomebrewでVert.xインストール
  3. rvmでjrubyインストール
  4. RubyでSockJsサーバを書いて実行
  5. PhantomJsからSockJsでサーバに接続

HomebrewでPhantomJsインストール

brew install phantomjs

HomebrewでVert.xインストール

brew install vert.x

rvmでjrubyインストール

ちょっとrvmのリストが古かったんで、更新しました。

rvm get head
rvm reload

※今時RVMかよ、というツッコミは気にしない。
JRubyをインストール

rvm install jruby

RubyでSockJsサーバを書いて実行

SockJsのサーバはサンプルをそのまま使いました。
vert.x/vertx-examples/src/main/ruby/sockjs at master · vert-x/vert.x · GitHub
これと同じ物を、ローカルで、「sockjs_server.rb」という名前で作成しました。
(しかし、この後ちょっとはまる、、、
とりあえず、実行してみます。

$ vertx run sockjs_server.rb
Failed to create verticle 
java.lang.NoClassDefFoundError: org/jruby/embed/InvokeFailedException
	at org.vertx.java.deploy.impl.jruby.JRubyVerticleFactory.createVerticle(JRubyVerticleFactory.java:51)
	at org.vertx.java.deploy.impl.VerticleManager$10.run(VerticleManager.java:777)
	at org.vertx.java.core.impl.Context$2.run(Context.java:119)
	at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processEventQueue(AbstractNioWorker.java:454)
	at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:331)
	at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:35)
	at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:102)
	at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.ClassNotFoundException: org.jruby.embed.InvokeFailedException
	at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
	... 11 more

おっと、、、エラーになった。
これの原因が分からず、小一時間ハマる、、、(調べ方が悪かったんですが)
結局、なんこっちゃない、環境変数がなかっただけでした。
以下の対応で解決。

$ export JRUBY_HOME=~/.rvm/rubies/jruby-1.7.3/ 
$ vertx run sockjs_server.rb

で無事起動しました。

PhatomJsからSockJsサーバに接続

やっとサーバの準備が整ったので、クライアントサイドを作っていきたいと思います。

「page.open」で開いているのは、空っぽのHTMLです。
「page.includeJs」でcdnのsockjs-clientを読み込んで、
「page.evaluate」を使って、ブラウザ上で、Javascriptを実行しています。
※コメントにあるように、evaluateに渡した関数の中では外側のスコープを参照できませんでした。

これでやっと準備が整って。。。と思ったんですが、
今のままだと、接続できたのかどーかわからないので、
サーバ側を少しいじりたいと思います。

  • 接続された時
  • メッセージが送られてきた時

に標準出力にメッセージを表示するようにしました。

それでは、全体通して、実行してみたいと思います。
1. SockJsサーバ起動

$ vertx run sockjs_server.rb

2.PhantomJsでクライアント実行

$ phantomjs ghost_sockjs_client.js

(SockJsサーバのコンソール)

$ vertx run sockjs_server.rb
connected.
hoge
connection closed.

うん、成功ですね。

あとは、phantomjsのプロセスをどのくらい起動できるか、、、
続きは明日以降に個人的にやってみたいと思います。