|
週末に病院送りになった都合で、
Groovy/Grailsネタを書く機会を逸していたのですが、 先週の時点でGrailsを動かすところまではできてます ただ、良くも悪くも時間が空いたことで、 Groovyそのものについて、さらに調べを進めていたわけですが、 そこでよく出てきたのがJRubyとGroovyの比較 ・JVM上で動く ・スクリプト言語である ・Rubyと互換性がある、あるいは参考にしている このような点で非常に似ていることもあり、 そういった論争が起こることもわかるのですが・・・ 結局のところ、JRubyとGroovyは設計思想の違う言語であり、 これを比較して優劣を決めることは、 言語の優劣を決めることと同格な気がします (比較するならRubyとJRubyの実行速度とか・・・) JRubyはRubyをJVM上で動かすための仕組みであり、 GroovyはJavaを簡潔に書くための記法ですから、 いろいろ似ていても根本的には違うもののはずです おそらく、問題を面倒にしているのが、 「JRubyはJavaのコードを呼べる」ってところでしょう (GroovyもJavaのコードを呼べる・・・という表現は間違いで、 むしろGroovyはJavaそのものなのですが、 このあたりが混同されている気がします) 確かにJRubyはJavaのコードを呼び出して書けます しかし、それで書かれたコードはRuby特有の簡潔な書式ではなく、 かといってJavaほど厳格でもないという、 非常に「ごちゃっと」した印象を受けます 無理矢理RubyとJavaのコードを混在させるくらいなら、 PureRubyかPureJavaで統一した方が、 生産性もメンテナンス性もいいと思うのですが 一方で、「GroovyがあればJavaはいらない」的な論調も見かけましたが、 これも違うよね・・・と思います 確かに、Groovyの「威力」はすさまじいのですが・・・と、 本論からずれるので、この話はまた次回にでも |
|
「Ruby on Rails」は手早く動くものが作れる
これは事実なのですが、いざ本番に持っていこうとすると、 非常に面倒だったりします 開発中に気楽に動かせるのは「WEBrick」のおかげなのですが、 本番環境でこれを動かすわけにはいかないわけで かといって、そのままApacheのCGIとして動かした日には、 リクエストの度にRailsの初期化処理が走ってしまい、 恐ろしいほど遅くなってしまう(´・ω・`) 仕方なく、Railsを動かすことに特化されたサーバを使うわけですが、 これをApacheと連動させるさせるのは、 難しいとは言いませんが面倒です 正直、私は作ったRailsのアプリを、XML出力だけに使って、 XMLはバッチで定期的にキャッシュしておき、 フロントエンドはFlexあたりにしようか、とか考えていました しかし、当然ながらそのバッチを作る方が面倒なわけで、 こりゃ困ったね、と(´・ω・`) で、考えたのが「JRubyならTomcatで動くんじゃない?」ってことでして 「JRuby」はJavaで書かれたRubyの実装なので、 コード的にはRubyですが、実際はJavaのVMで動きます しかも、JRubyならJavaのクラスが呼べるので、 自分のフレームワークに詰め込んだ、 使い慣れたライブラリを使えるのもいい感じです(`・ω・´) b これは非常に理想的ですし、 「JRuby on Rails」で開発された事例もあるということで、、 いろいろ調べていたわけですが・・・ JRubyを基点に情報をたどったところ、 目に付いたのが「Groovy」という言語 最近のJavaは、JRubyやJython(Javaで実装したPython)のように、 他の言語をJavaで実装するのが流行になっています (たぶん、Java6の目玉がこれだった気が) それと同時に出てきたのが「Groovy」だったと思いますが、 名前を知ってはいても、あまり興味はなかったのです ただ、知っていて損はないだろうと、 Wikipediaの記述を読んでみたのですが・・・ ・・・これ、すごすぎない(´・ω・)? 一言で言って、「Groovy」とは、 「Javaをスクリプト言語風に書くための言語」なのです Javaは確かにガチガチに固められた言語であり、 それゆえに堅牢性抜群なのですが、 一方で堅苦しくて、開発が(スクリプト言語に比べて)面倒です しかし、例えば以下のようなコードがあったとします class HelloTest { public HelloTest() { println "Hello, World!" } public static void main(String[] args) { new HelloTest() } } (出典:Wikipedia) 「Hello World!」を出力するだけのコードですが、 これをGroovyで書くと・・・ println "Hello, World!" (出典:Wikipedia) ・・・これだけΣ(・ω・ノ)ノ GroovyはRubyに影響されて作っただけあり、 Rubyに非常に良く似た記法を使うのですが、 実体は紛れもなくJavaであり、Javaのクラスは全て使えます しかも一番恐ろしいのは、実体がJavaでありながら、 「動的型付け」を実現しているところなのです(lll゚Д゚) たぶん、リフレクションを駆使しているのだと思いますが、 それゆえに実行速度は犠牲になっているはず でも、Javaのコードをここまで簡潔に書けるなんて、 想像したこともありませんでした (他のサンプルコードをぜひWikipediaで) このありがたみは、Rubyの簡潔さに触れたからわかるもので、 出た当時にこの記述を見ても何とも思わなかったと思うのですが、 これはものすごい言語ですよ・・・本当に で、Rubyを意識して作った言語であるならば、 当然「Rails」が出てくるわけですが・・・ ・・・「Grails」については調査中!Σ(゚Д゚)ガーン |
|
この記事は旧Blogで書いた記事の再掲です
元の日時は「2007/01/25 13:12:44」です さて前編の続きだ multipart/form-data形式のリクエストを、 Javaクラス内から発行する方法を考えるわけだが、 前回は既存のモジュールをあれこれいじって結局失敗 こうなれば最後の手段、「力技」で勝負である 要は、HTTPリクエストの実態は文字列の通信だから、 リクエストに文字列を仕様通りに流し込めばいいわけだ とはいえ、自力で書いたコードは、 どうにもmultipartと認識されなかったので、 さらに細かくWebで調べたら、「JavaHouse」にコードがあった このコードのままでは動かなかったので、 少し手を入れたのが以下のコードである ※「Parameter」はnameとvalueをセットしただけのモデル ※「TransportFile」は、nameとFileクラスをセットしただけのモデル ※「BOUNDARY」は適当な半角英数文字列 ※「¥r」がなぜか表示されなかったので全角にしているが、実際は半角 /** * multipartデータ出力。 * @param con HTTPコネクション * @throws IOException */ void sendMultipart(HttpURLConnection con) throws IOException { // multipart/form-data形式 con.setRequestProperty("Content-type", "multipart/form-data; boundary=" + BOUNDARY); // データストリームオープン DataOutputStream out = new DataOutputStream(con.getOutputStream()); // MultiPartのデータ作成 // 文字部分 for (int i = 0; i < this.paramList.size(); i++) { Parameter param = this.paramList.get(i); out.writeBytes("--" + BOUNDARY + "¥r\n"); out.writeBytes("Content-Disposition: form-data; "); out.writeBytes("name=\"" + param.getName() + "\"¥r\n"); out.writeBytes("¥r\n"); byte[] byteBuf = param.getValue().getBytes(); for (int j = 0; j < byteBuf.length; j++) { out.writeByte(byteBuf[j]); } out.writeBytes("¥r\n"); } // ファイル部分 BufferedInputStream in = null; for (int i = 0; i < this.fileList.size(); i++) { TransportFile file = this.fileList.get(i); in = new BufferedInputStream( new FileInputStream(file.getFile())); out.writeBytes("--" + BOUNDARY + "¥r\n"); out.writeBytes("Content-Disposition: form-data; "); out.writeBytes("name=\"" + file.getParamName() + "\"; "); out.writeBytes("filename=\"" + file.getFileName() + "\"¥r\n"); out.writeBytes("Content-Type: application/octet-stream¥r\n"); out.writeBytes("¥r\n"); int fileInt = 0; while ((fileInt = in.read()) != -1) { out.writeByte(fileInt); } in.close(); out.writeBytes("¥r\n"); } // ラスト out.writeBytes("--" + BOUNDARY + "--"); out.flush(); out.close(); } とあるクラスのメソッドだけ引っこ抜いたので、 一部不明なところがあるが、なんとなくわかるのではないだろうか 私が詰まったのは2点 ・BOUNDARYの前に"--"が必要だと気づかなかった (仕様を解説するサイトのほとんどがBOUNDARYを"------..."とか書いていて勘違い) ・最後に「"--" + BOUNDARY + "--"」を出力してなかった まあ、今回のことでわかったのは、 やっぱり最後に頼れるのは仕様書と力技、ということか ちなみに当然ながら、この仕様通りにparseすれば、 multipartのリクエストを受け取ることもできるはず 「Jakarta Commons FileUpload」を使いたくない方はお試しを |
|
この記事は旧Blogで書いた記事の再掲です
元の日時は「2007/01/24 21:21:09」です 以前、multipartフォームからデータを取り出す部品は作った 今度は逆、multipart/form-data形式のリクエストを、 Javaクラス内から発行する方法を考えた 「multipart/form-data」でググると、たいてい出てくるのは 「method="POST" enctype="multipart/form-data"」をFORMに指定して・・・という話 だが、欲しいのはこれではない サーバ同士をつなぐAPIがHTTPプロトコルで設計されていたので、 どうしてもクラス内からmultipartリクエストを発行しなければならない (multipartでなければ、データの受け渡しは簡単なのだが・・・) で、思いついたのが、「java.mail」パッケージを使って、 うまいこといかないかな・・・という手段 メールデータももmultipartの一種だから、 ごまかして使えないものかと思ったのだ 結論から言うと、無理だった 先日作ったmultipart部品で受け取っても、 multipart/form-dataとして認識しない (部品のテストは終わっているので、こっちがまずいということはない) デバッガでオブジェクトを覗いてみると、 どうやら余計なデータが大量に含まれているようだ 元々メール用なのだから仕方ない なら、multipart形式の作り方だけでも確認しようと思ったら、 ソースが見つからなかった クラスからリバースするのは面倒だし・・・ こうなったら最後の手段・・・ということで、 「力技」で解決したわけだが、具体的な方法はまた次回 |
|
この記事は旧Blogで書いた記事の再掲です
元の日時は「2007/01/03 11:44:14」です 例の検索エンジンを作っていたところ、一つの問題にぶち当たった 元々、Index化の手順は以下のようになっていた 1. DBから情報を全て引き出す 2. 1.の情報をループさせてDocumentオブジェクトを生成 3. 2.のDocumentをIndexWriterにadd 4. optimize 手順だけ見ればまったく問題ないのだが、 本番に近いデータを使ってテストしてみたところ、問題が発生したのである DBから引き出されたデータは50000件以上 これを一度引っ張り出すわけだから、当然大量のメモリを使用する この件数だからかろうじて実行できるが、 いくら待機サーバを利用するといっても、この数倍のデータを一度に扱えば、 OutOfMemoryがthrowされてもおかしくない これはまずいと、対策を立てたわけだが、 その方法が「オブジェクトの読み書き」である ObjectInputStream/ObjectOutputStreamを利用すると、 Serializableをimplementsしたインスタンスの読み書きができるのである。 ファイルに書き出すなら、FileOutputStreamを引数に与えればOKだ (Serializableにはもっと深い意味があるが・・・それはまた別の機会に) これらを利用して、ファイルキャッシュをハンドリングするクラスを作成し、 メモリ問題は解決したのだった。 もちろん、部品はFrameworkに追加である |








