2010-02-06
Fedone サーバに ClientBackend を使ってメッセージを送ってみるテスト
ローカルに建てた Google Waveプロトコルの実験実装 Fedone Server に対して、ClientBackend クラスを使ってメッセージを送ってみるテスト。
http://rainbowdevil.jp/wave/install-fedone.html
public class HelloWave {
public static void main(String[] args) throws Exception {
ClientBackend backend = new ClientBackend("test1@domainname", "localhost", 9876);
try {
//Create Wave
BlockingSuccessFailCallback<ProtocolSubmitResponse, String> callback = BlockingSuccessFailCallback.create();
backend.createConversationWave(callback);
callback.await(1, TimeUnit.MINUTES);
//Get Wave
ClientWaveView indexWave = backend.getIndexWave();
List<IndexEntry> index = ClientUtils.getIndexEntries(indexWave);
ClientWaveView wave = backend.getWave(index.get(0).getWaveId());
//Send Wavelet Delta
WaveletData waveletData = ClientUtils.getConversationRoot(wave);
BufferedDocOp docOp = waveletData.getDocuments().get(DocumentConstants.MANIFEST_DOCUMENT_ID);
String documentId = backend.getIdGenerator().newDocumentId();
WaveletDelta waveletDelta = ClientUtils.createAppendBlipDelta(docOp, backend.getUserId(), documentId, "Hello Wave!");
backend.sendAndAwaitWaveletDelta(waveletData.getWaveletName(), waveletDelta, 1, TimeUnit.MINUTES);
} finally {
backend.shutdown();
System.exit(0);
}
}
}
2010-01-07
JSONで通信する汎用的なjQueryのWebSocketプラグインを作ってみた
単純に文字列しか送れない Web Sockets API(プロトコル的にはバイナリも送れるけど)なので、ちょっと色々送ろうと思うと、やっぱり JSON で送りたくなる。
どうせ絶対毎回使うと思うので、汎用的なプラグインにしてみた。
http://code.google.com/p/jquery-websocket/
やれることは、
これのみ。あとは使う人の自由。
通常と違うところは、
- sendメソッドの引数が2つになっており、第1引数にイベントタイプ、第2引数に送信するJSONデータを渡すこと
- イベントタイプに応じたイベントハンドラを登録出来ること
- 要 jquery-json プラグイン
このプラグインでJetty で WebSocket を使ってみる - ショータローDiaryで使ったコードを書き換えるとこんな感じ↓
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat</title>
</head>
<body>
<h1>WebSocket Chat</h1>
<section id="content"></section>
<input id="message" type="text"/>
<script src="http://www.google.com/jsapi"></script>
<script>google.load("jquery", "1.3")</script>
<script src="http://jquery-json.googlecode.com/files/jquery.json-2.2.min.js"></script>
<script src="http://jquery-websocket.googlecode.com/files/jquery.websocket-0.0.1.js"></script>
<script>
var ws = $.websocket("ws://127.0.0.1:8080/", {
events: {
message: function(e) { $('#content').append(e.data + '<br>') }
}
});
$('#message').change(function(){
ws.send('message', this.value);
this.value = '';
});
</script>
</body>
</html>
この単純すぎるコードではあまり恩恵はない(window.unload での close はプラグインでやってるのでその分は楽だけど)ので、イベント多用するサンプルを作ってみたけど、何か面白くないのでやり直し。。
でも、これが出来るだけで、かなり使いやすくなったはず! ということで、誰か面白いの作ったら教えて下さいw
2009-12-20
MMTBでLTした
前の会社にいた時は社内向けにLTっぽい事してたけど、公の場では人生初LT。
とは言っても、知り合いが大半の場でしたがw
そのときのスライド
http://docs.google.com/present/view?id=dddvzhrc_3frv8djhr
デモは先週書いたJetty で WebSocket を使ってみる - ショータローDiaryそのままという手抜きですがw
でもまぁ、何となく今年のTryだった「LTする」ってのは、ギリギリ達成されました。パチパチ
来年はもっと発表して行こうと思う(ネタがあれば)
2009-12-14
Jetty で WebSocket を使ってみる
Java, Jetty, html5, WebSocket | |
Jetty 7.0.1.v20091125 で、HTML5 の WebSocket がサポートされているので、Chrome から繋げてみる。
WebSocketServlet によるサンプルが紹介されているので、
WebSocketHandler で。
こんな感じ。
public class MemberSocket implements WebSocket {
static Set<MemberSocket> members = new CopyOnWriteArraySet<MemberSocket>();
Outbound outbound;
@Override
public void onConnect(Outbound outbound) {
System.out.println("onConnect:" + this);
this.outbound = outbound;
members.add(this);
}
@Override
public void onDisconnect() {
System.out.println("onDisconnect:" + this);
members.remove(this);
}
@Override
public void onMessage(byte frame, String data) {
System.out.println("onMessage:" + this);
for (MemberSocket member : members) {
try {
member.outbound.sendMessage(frame, data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onMessage(byte frame, byte[] data, int offset, int length) {
System.out.println("onMessageOffset:" + this);
}
public static void main(String[] args) throws Exception {
Server server = new Server(8080);
server.setHandler(new WebSocketHandler() {
@Override
protected WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {
MemberSocket memberSocket = new MemberSocket();
System.out.println("doWebSocketConnect:" + memberSocket);
return memberSocket;
}
});
server.start();
}
}
見たままですね。
offset ありの onMessage はどういう場合に呼ばれるんだろ??
クライアントは、本家のWebSocket Chatでもいいのだけど、何か無駄にごちゃごちゃしてるので、おおたにさんのところにあったEmerge Technology: WebSocketでChatを作ってみたを jQuery 化したもの。
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>WebSocket Chat</title>
</head>
<body>
<h1>WebSocket Chat</h1>
<section id="content"></section>
<input id="message" type="text"/>
<script src="http://www.google.com/jsapi"></script>
<script>google.load("jquery", "1.3")</script>
<script>
var ws = new WebSocket("ws://127.0.0.1:8080/");
ws.onmessage = function(m) {
$('#content').append(m.data + '<br>');
};
$('#message').change(function(){
ws.send(this.value);
this.value = '';
});
$(window).unload(function(){
ws.close();
});
</script>
</body>
</html>
コネクションが解放されない問題Emerge Technology: ChromeとWebSocketも対応済み。Chrome のバグなんだろか。
で、実行すると、、
うん、チャットできてますね。
一応、Maven であれば jetty-websocket に依存させるだけでよい。らくちん。
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-websocket</artifactId> <version>7.0.1.v20091125</version> </dependency>
もう Comet 要らないな。
2009-12-10
T2 を Jetty Embedded で直接動かす
軽量な Web フレームワークとして T2 が気になるところなのですが、最近のマイブームはクライアントサイド Java アプリなので、それに組み込んでみたらどうかと考えてみたり。
よりシンプルに動かしたいので、軽量なアプリケーションサーバの代表格である Jetty で動かそうかと。それも直接に。
T2 は ServletFilter ベースなので、普通に動かすには war ファイルを作って(それか webapp ディレクトリを指定して)デプロイをしなければならないわけですが、組み込みのアプリにデプロイなんて行為は必要ない。デプロイするには jetty-deploy に依存する必要もあり、イケてない。
最新の Jetty 7 は、機能がかなり小分けに jar 化されていて、最小構成の jetty-server からの依存だと、JSP はおろか Servlet すら動かない構成にすることができる。直接動かすって何かというと、この最小構成の Jetty(仮に Jetty Embedded と呼ぶ)で、デプロイも無しに動かすということ。
Jetty/Reference/Dependencies - Eclipsepedia
Servlet も動かない Jetty Embedded で処理を実行する唯一の方法は、リクエストを処理する Handler インタフェースを実装したクラスを作って、Server に登録すること。
Jetty/Tutorial/Embedding Jetty - Eclipsepedia
そこで、T2 の根幹である T2Filter をラッピングした Handler を作れば良いと思って、作ったのが↓
public class T2Handler extends AbstractHandler {
protected Filter t2Filter;
protected Context context;
protected Dictionary<String, String> initParam;
public T2Handler() {
t2Filter = new T2Filter();
initParam = new Hashtable<String, String>();
}
@Override
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// FilterChain を偽造
FilterChain chain = new FilterChain() {
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
}
};
t2Filter.doFilter(request, response, chain);
baseRequest.setHandled(true);
}
@Override
protected void doStart() throws Exception {
context = ContextHandler.getCurrentContext();
// FilterConfig を偽造
FilterConfig config = new FilterConfig() {
public ServletContext getServletContext() {
return context;
}
public Enumeration<String> getInitParameterNames() {
return initParam.keys();
}
public String getInitParameter(String name) {
return initParam.get(name);
}
public String getFilterName() {
return "t2";
}
};
t2Filter.init(config);
super.doStart();
}
@Override
protected void doStop() throws Exception {
t2Filter.destroy();
}
public void setRootPackage(String value) {
initParam.put("t2.rootpackage", value);
}
}
Handler は、ほとんど Filter と同じ仕組みになっているので、
- Handler.handle() から Filter.doFilter()
- Handler.doStart() から Filter.init()
- Handler.doStop() から Filter.destroy()
を呼んであげて、initParam で指定する t2.rootpackage を設定する setter だけとりあえず用意すれば良い。至って簡単。ただし、Filter 固有の FilterConfig と FilterChain が無いので、偽造して渡してあげる必要がある。ここだけシンプルさに欠ける。。
で、この T2Handler をサーバーに登録して起動する main クラスを作っておしまい。
public class Main {
public static void main(String[] args) throws Exception {
T2Handler t2Handler = new T2Handler();
t2Handler.setRootPackage("sample.page");
SessionHandler sessionHandler = new SessionHandler();
sessionHandler.setHandler(t2Handler);
ContextHandler contextHandler = new ContextHandler();
contextHandler.setHandler(sessionHandler);
Server server = new Server(8080);
server.setHandler(contextHandler);
server.start();
}
}
あとは適当な Page クラスを用意して実行すれば、、
おおお!ちゃんと動いてますね!
439,063 t2-0.6.2-ga.jar
348,057 commons-0.6.5-ga.jar
250,557 jetty-server-7.0.1.v20091125.jar
179,079 jetty-util-7.0.1.v20091125.jar
106,778 jetty-http-7.0.1.v20091125.jar
105,112 servlet-api-2.5.jar
67,325 jetty-io-7.0.1.v20091125.jar
19,332 jetty-continuation-7.0.1.v20091125.jar
23,445 slf4j-api-1.5.8.jar
5,284 slf4j-nop-1.5.8.jar
こう比較すると T2 って思ったよりデカイ。(十分小さいけど。)
Jetty みたいにもうちょっと小分けにすれば小さくなるんじゃなかろうか。org.t2framework.t2.format.amf* 配下とか、AMF 使わなければ要らないんじゃ?と思って、削ってみたら(依存する箇所がいくつかあったので、若干修正込み)、
348,057 commons-0.6.5-ga.jar 291,324 t2-without-amf-0.6.3-SNAPSHOT.jar 250,557 jetty-server-7.0.1.v20091125.jar
commons よりも小さくなった。



昨日はありがとうございました。
MMTBの今年の最後は飛び込みでの「LT」でバシッと〆ていただけましたね。
参加された方々にとっても刺激的で勉強になったのではないかと思います。
私自身また聞きたいので、来年も是非何回でもよろしくお願いします!