カスタム検索

2009年4月28日火曜日

Grailsで帳票!JasperReport 出力編

めずらしく引き続きJasperReportです。
今回は jasper ファイルから pdf を出力します。

ざっくりコードから!
  1. def report="sample.jasper"  
  2. def ds=new JRXmlDataSource("http://localhost:8080/jasper/book/xmllist","/list/book")  
  3. def print = JasperFillManager.fillReport(report,[:], ds)  
  4. def pdf=new File("test.pdf")  
  5. JasperExportManager.exportReportToPdfFile(print,pdf.getAbsolutePath())  


reportに帳票ファイルのパスを指定(File型は使えないので注意)

今回はXMLを読み込むのでデータソースにJRXmlDataSourceを作成、前回アクションでxmlを生成するようにしたので、そのURIと、データの基準となるxpathを指定

JasperFillManager.fillReport でレポートファイルと、帳票パラメーター(今回はなしなので空のマップ)、データソースを渡して JasperPrint を作成します。

JasperExportManager.exportReportToPdfFile で出力先のファイルを指定して実行

これでPDFが出力されます。
小さな帳票だったら爆速です!(BIRTと比べて)
ブラウザに表示したい場合は JasperExportManager.exportReportToPdf でPDFのbyte配列がかえるので、これをストリームに返してやればOKです(contentTypeとかはちゃんとセットしてね)

Grailsで帳票!JasperReport 帳票準備編

GrailsでJasperReportの帳票を出力する方法
長いので帳票準備編と出力編に分けます |-`)
XMLを使って出す方法です。
レポートからDB経由して直接引っ張り込む方法もありますが、帳票にあまりロジック的なものをいれたくないので・・・

・Jasperのライブラリをプロジェクトに追加する
公式サイトからjasperreports-3.5.0.jarをダウンロードしてきてプロジェクトの lib フォルダへ突っ込む
PDF出力にiTextを使っているので、iTextと、日本語出力用にiTextAsian.jarとiTextAsianCmaps.jarを入れます。

・DomainをXMLで出力出来るようにする
以下のような感じでxmlを返すアクションを作りましょう。
as XMLは import grails.converters.XML をしてやる必要があります。

  1. def xmllist = {  
  2.   render(text:Book.list() as XML,contentType:"text/xml",encoding:"UTF-8")      
  3. }  


・XMLのサンプルデータを取得し、iReportへデータソースの定義をする
上記のアクションにアクセスするとブラウザにXMLが表示されます。(またはダウンロード)
このXMLを保存し、iReportから新規データソースを作成で、XML file datasourceを選択します。



適当な名称と、XMLを指定、Create a datasource using this expressionを選択して xpath を指定します。



・レポートへフィールドをセットする
Field項目の追加で、Descriptionにフィールド名(XMLのノード名)を入れます
追加されたフィールドをレポートへドラッグします
(値が日本語の場合はフォントを日本語フォントに変更します)



Preview を選択するとXMLから読み込まれた値が表示されます。
Previewした時点でテンプレートがコンパイルされ、同名の.jasperファイルが作成されます。
(iReport3.5ではコンパイルの方法がPreviewしか見つかりませんでした・・・)

ここでは日本語がサクっと出るのですが、このままだとPDFにした時に日本語が表示されません。
レポートのXMLを見ると(DesignerとPreviewの間にあるXML)fontタグがあるのですが、こいつにPDF出力用の設定をしてやる必要があります。
(iReport3.5ではここはGUIでは編集出来ないっぽいです)

以下平成角ゴの例です。
  1. <font fontName="Hiragino Kaku Gothic Pro" pdfFontName="HeiseiKakuGo-W5" pdfEncoding="UniJIS-UCS2-H" isPdfEmbedded="true"/>  


これで帳票の準備は完了です。
次回はこのjasperファイルを使ってプログラムから帳票を出力します

2009年4月27日月曜日

Grails 1.1 でやってはいけない事(warするとエラーな件について)

とあるGrails1.1のプロジェクトでwarしてTomcatにのっけたら動かないとの事で、、、その時点での1.1.1のSNAPSHOTでやってみたら動いたという情報を元に原因を探してみる事に

結論からいくと、saxonというXSLTプロセッサのライブラリがあると起動に失敗するっぽい
起動時に applicationContext.xml の定義を読む込み所で失敗しているので、ここで使うxmlのparserがsaxonのライブラリと衝突を起こしているっぽい感じ

過去の 1.0.3 とか、1.1.1-SNAPSHOTで動く所を見るとソース上の凡ミスっぽい感じもするけど・・・
(最新の1.1.1-SNAPSHOTにアップデートしたら今度はrun-appも出来なくなった、、、本当に近日リリースされるのだろうか |-`;) )

2009.4.28 追記
最新版はSubVersionではなく、Gitで管理されているもよう、SVNのリポジトリは信頼しちゃダメ!
多分コレ

特に理由がなければ、こちらの方法をを使った方が使いやすいし良いと思います :)

2009年4月21日火曜日

Grails+HiberObjectsでJPAなモデリング

HiberObjectsというEclipseのPluginでHibernate+JPAをGUIモデリングで作れるのですが、これがGrailsに対応していると言う事で使ってみました。

公式サイトはコチラ

最新のEclipseをダウンロードしてきてpluginをセット、Grailsは1.1を使いました。
公式の説明にしたがってHiberObjectsを有効にしていきます、公式のは少し古いみたいでオプションが一部違いましたが、
特に気にするような項目もなかったのでそのまま続行。

公式には Deselect Add Hibernate libraries とありますが、後でHibernate関係でライブラリが見つからないよとエラーが出るのでチェックを入れておきました。
(1.1からはHibernateが完全なPluginとなり、GRAILS_HOMEのlibフォルダにHibernate系のライブラリが入らなくなった為)

設定画面はこんな感じです。




HiberObjectsを有効にしたら、クラスダイアグラムを作ってUMLを描いていくとJavaコードと、hibernate.cfg.xml が生成されます。


あとは generate-all なり、scaffold=true なりして run-app すると普通に CRUD が出来ま、、、、せんでした |-`)
Create,Read,Deleteとリレーション系はちゃんと実装されてるんですが、Editでエラーになります。
ソース見たら自動生成されるファイルに version がありませんでした(´・ω・`)
(クラスに手動で Long version フィールドを追加してやれば CRUD できました)

他にもクラスダイアグラムで削除したクラスやインターフェースが生成され続けるとか、まだまだ微妙な所もあります・・・
Groovyで普通のドメインみたいに作ってくれてUMLが描けるのかと思ってwktkしてたのでちょっと残念、でもGrailsに対応しようとしてくれる辺りが素敵です、今後に期待!

2009年4月20日月曜日

TextmateでGrailsを開発する5つのステップ

GrailsのIDEでは現在以下があります。

・Eclipse
いわずがなとも。Groovy Pluginを入れておくと便利。
だけどGroovyはダイナミックだからJavaほど恩赦は受けられない。

・NetBeans
Grailsへの対応を結構しっかりやっている。
けどコマンド系(run-app とか create-controller とか)の処理はイマイチな気がする。
なんかタスクがうまく落ちなかったりする。

・IntelliJ
無料お試し期間でしか使った事ない |-`)
一番公式な感じ?
高いのであんまり興味無し

と、いくつかあるのですが、どれも重いんですよねぇ
開発はサクサク動かしたいもんです。

というわけでMacな人にはTextmateをオススメします。
Textmateは有料ですがサクサク動いて色々とカスタマイズする事で凄く便利になります。
Grails向けのおすすめカスタマイズを5つ紹介します。

・日本語表示
textmateはデフォで日本語表示が出来ないので、ココらへんを参考に日本語フォントを入れて表示出来るようにしましょう
はじめはつぶれた日本語に違和感がありますが、慣れるとなんてことないです、むしろ幅が揃って良いという気分でいましょう

・Groovy Grailsバンドル
.gsp 表示のシンタックスハイライトや、便利なスニペット(rt[tab]で render(text:"") とか)がつまってます
ココからダウロードできます

・Groovyバンドル
.groovy 表示のシンタックスハイライトや、次のRun Selected Snippetの為にいれておきましょう
ココからダウンロードできます

・Run Selected Snippet
Groovyバンドルの機能の一つです
選択した部分の Groovy を実行できます
GroovyではJavaのクラスへいくつかの便利な機能が付加されてます、詳しくはGroovy JDKにのってますが、
これらの挙動等をちょっとテストしたい時に最適です

例えばテキストファイルの中身を改行でループして、タブ区切りにした1個目の値をごにょごにょしたいな〜と思った時に、
コントローラーを通してやったりせずに、Groovyファイル上の適当な場所に、その部分のコードだけを書いてちょこちょこ動かして確認すれば良いのです

  1. def infile=new File("test.csv")  
  2. infile.splitEachLine("\t") { line ->  
  3.   println line[0]  
  4. }  


この出力は通常、ウインドが開いてhtml表示されるのですが、ちょこちょこ動かしたい場合はウインドをいちいち閉じるのがめんどいです
Bundle Editorから Run Selected Snippet を見てみると、 exit_show_html となっている部分が2カ所あります
これが通常の出力になってますので、これを exit_show_tool_tip に変更してやります
すると、 tooltip として結果が表示され、ちょっと動かしてやれば消えるのでサクサク使えます

ただ1画面ぐらい出力がされると tooltip では不便です、でもって exit_show_html の出力は html が解析されてしまうので、htmlを見たい時には不便です
なので新規ドキュメントとして開いてやりましょう
今度は exit_show_html の部分を exit_create_new_document に変えてやればOKです

exit_show_tool_tip で tooltip 表示
exit_create_new_document で 新規ドキュメント表示

大事な事なので2回言っておきます :)
この二つを作っておけば大体のケースには対応出来るでしょう。

・リファレンスリンク

Groovyバンドルには Groovy JDK というGroovyの拡張部分がわかるAPIを開くコマンドが追加されます
Grailsでは Groovy 以外にも色々なフレームワーク、ライブラリが使われていますので、これらもサッと開けると便利です
Groovy JDKのコマンドをコピーして、URLの部分を http://grails.jp/links.html に変えましょう
Grails関連のAPI等がざっくり見れます :)




アジャイルなフレームワークにはアジャイルな開発環境を。
これであなたもGroovy!なGrailsライフをおくれる事間違い無し!

GlassFishとBirtの切ない関係

GlassFIshが謎の停止をするので色々とさぐっていったらBirtで帳票を出した時に止まるっぽい

Birtの負荷かな?と思ってJettyとTomcatでアホのように負荷をかけてみたけどまったくとまる様子がない。
というかGlassFIshでは起動直後でも5セッションで帳票を出すと止まる・・・
4セッションだとほとんど止まらない、なんじゃこりゃ

Birt側の問題かと思って最新版に乗せ変えたりもしてみたけど状況は変わらず
うーん、おとなしくjasperReportにしようかなー、Birtである必要性もないし・・・

なんかわかったら続報を入れます

4/23 追記
GlassFish v3の最新版では正しく動作しました
ただしv3ではメモリ関係がv2より厳しいようです、特に -XX:MaxPermSize の指定は必須です

GlassFIsh v3とTomcat、JettyでOKとなると、v2.1に何か衝突する問題がありそうです
Sunからはv3ではまだCluster等が出来ないので本番環境はv2.1を推奨との事ですが、この状態ではv3を使わざるを得ない感じですね・・・
結局しばらくClusterは上位(Apache等)で処理してやるのが良いかもしれません

2009年4月14日火曜日

Grailsで帳票!JasperReport ざっくり評価編

Javaで帳票といえば長い事BIRTを愛用してきたんだけど、食わず嫌いもよくないと言う事で有名なJasperReportを使ってみた、せっかくなんでGrailsで。

まずJasperReportの仕組み。

jasperReportは jrxml というXMLファイルをコンパイルして jasper ファイルを生成して、そこにパラメーターやらデータソースやらを与えて帳票を出力してくれる

出力形式は XLSやPDF、HTML、CSV等が出せる(XLSはPOI、PDFはiTextを使用)

XMLファイルを作成するには iReport というGUIソフトがある
iReportには Classic 扱いの 3.0 と 現行の 3.5 がある
3.5 はNetBeansベースのアプリ(NetBeans用のPluginもある)でマルチプラットフォームなので良さげな感じだが、
Classicに比べると設定出来る項目が少なかったりする
でもMacな自分には選択肢がないので設定出来ない項目はXMLに直接書く事にする :(

一応メニューもマルチランゲージになっているが、ほとんど英語
とりあえず iReport を立ち上げて適当に帳票作ってみて Preview すると日本語もちゃんと通るっぽい

ざーっくり使ってみた感じ、BIRTとの比較等
レポート的に出来る事、出来ない事の比較はあんまりしてないです、とりあえずJavaで帳票出すって所を視野に入れての感想です

ここが○
・データソースがレポート内部と外部がちゃんと別れている所
XMLをURLから動的に生成していたので、BIRTではデータソースから動的に設定する必要があった
そうするとサンプルデータの準備も面倒だし、動的なURLを解析してXMLをパースしてくれないので、設定に不便だった・・・
iReportではアプリ上に別データソースとしてサンプルファイルをセットしておけばいいのですごくらくちん!
データソースを複数用意しといて切替も簡単、実際にコードから生成する時もデータソースを別であてるだけなので、これは凄くいい!

・ファイルがコンパイル出来る
xmlファイルをコンパイルにしてjasperにしておけば印刷時にコンパイルがいらないのでちょっと早いかも?

・テーブルの部分が別エディタとなっている
BIRTでは同じ帳票上でグリッドとか細かく触らないといけない&重たくて反応が遅れるのでイライラする
でも使いかっては今の所BIRTの方が良い(なれてるだけか)

・プログラムに組み込むのが簡単
BIRTではライブラリも含め色々と仕掛けが必要だったが、JasperReportはいくつかのライブラリいれるだけで後はソース上からさくっと作れた、そのままストリーム返しも出来そうだしいい感じ

・PDF周りの設定がしっかり出来る
PDF上のフォントのエンコード、フォント毎にPDFヘの埋め込みするしない、
PDFのバージョン、セキュリティ関係などなど今なら指定し放題!
BIRTではあるのかもしれないけど、触ってる範囲では出来ないっぽい

ここが×
・幅の%指定がない?
BIRTでは大きさに%指定ができ、ものによって大きくなったり小さくなったりが出来たがjasperReportではないっぽい

・iReportが微妙すぎる
NetBeans版は色々と微妙・・・まだこれからなのかな、Classic版を使ったらもっとハッピーになれるのかしら


次回はBIRTでXMLから帳票を出力しているのがあったので、XMLから帳票を作ってみる編
(ああ、次回ネタが溜まりすぎ・・・)

GroovyのURL Classが素敵すぎる件について

以前、別のURLのデータを取得するのにhttpBuilderを使ったり、httpClientを使ったりしてごにょごにょ書いてたんですが、
mottsniteさんがボソっとURLのgetTextでとれるよ。と言っていたので試してみた。

  1. def url=new URL("http://www.yahoo.co.jp")  
  2. println url.getText()  


( ゚д゚)

(つд⊂)ゴシゴシ

(;゚д゚)

(つд⊂)ゴシゴシ
  _, ._
(;゚ Д゚)ぁぁぁああぁぁ!?

なにこれ、素敵すぎます。
まだあんまり試してないけど、日本語もすんなり通るし、すげぇ。

ストリームしてファイルダウンロードもいけるみたい。
RESTしたいとかには答えられないのかもしれないですが通常使用ならこれで十分っぽいですね。

FileのgetTextもそうですが、こういうのを見るとまさにGroovy!って感じしますね :)

2009年4月13日月曜日

GrailsのServiceでServletContextを使う

もの凄いピンポイントネタですが。

GrailsのController上ではServletContextが勝手に注入されてます。
Service上では注入されてません、そしてSpringBeanでもないので注入も出来ません。
なんか簡単にとる方法ないのかなーと思ってググったら「コントローラーから渡したらええんちゃうん?」みたいな答えしかなくてしょんぼり。
サービスだけで使いたいのよ、BlazeDSとかWebサービスとかさ。

で、grailsApplicationは注入可能なので、こっからたどって取得します。

def grailsApplication

で grailsApplication を注入して、そこからparentのcontextを取得し(SpringのXmlWebApplicationContext)、そこからServletContextがとれます。

def sc=grailsApplication.getParentContext().getServletContext()

やったね :D

GrailsのServiceでServletContext

2009年4月9日木曜日

クエリチューニングについて本気出して考えてみた

Grailsでアプリを作っていると、O/Rマッピングに頼りっぱなしで、重い所だけたまにHQLを書いていたのだが、
さすがにDBの規模が大きくなるとそうも言ってられないよなーと思い、クエリチューニングに乗り出す事にした。
(indexの最適な付け方も良くわからないし :D )

まずは現在のボトルネックを探す。
今までは体感とシステム上で時間を計測してたけど、DBの事はDBに聞けって事でログ解析をする事に。
ここらへんを参考にした)

postgresのログ解析には pgfouine と pqa というのがあるらしい、前者は php、後者は ruby だ。
これはもちろん pgfouine だろう! php も ruby もよく知らないけど groovy 好きっ子としては ruby に行ったら負けかなと思っている。

ITProの記事を参考に、postgres のログを出力する設定をする

んで pgfouine を実行・・・!しようと思ったら動かない。GDというライブラリが必要らしい。
Macにデフォで入っている php にはこれが組み込まれていない。調べてみると MacPorts でインストールすると簡単らしい。
ということで MacPorts から php をインストール、、、長い、、、長い、、、しかもCPUフルに使いやがる、そういう事は先に言ってくれと。

無事インストールが終わった所で pgfouine を起動してみる。
  1. php pgfouine.php -logtype stderr -file log/postgresql-xxxx-xx-xx_xxxxxx.log -format html-with-graphs -report vanfu_sql.html=overall,hourly,bytype,slowest,n-mosttime,n-mostfrequent,n-slowestaverage,n-mostfrequenterrors,tsung  


とりあえず出力オプション全部付けてみた :p



おー、なんかかっこいいですね!
ちょっと試しで3分ほど適当にシステムを稼働させて集計した結果、SELECT件数が 4,179、、、うーんO/Rマッピングが遅いと言われるのがわかります。
まあ逆に考えれば1クエリ0.01秒の改善でも3分あたり40秒もの改善になるって事ですね。

とりあえず現状の確認方法まで
次回はGrails向けのチューニング方法をまとめようと思います。

2009年4月7日火曜日

GrailsでblazeDSプッシュ配信!その1

blazeDSといえばプッシュ機能がついていますが、grailsのflex pluginでは定義されてないので使う事が出来ません。

せっかくあるんだし、サーバから一斉にメッセージ配信とかなんかカッコイイ(ここ重要)ので実装してみました。
まずは plugin を改良して streaming と polling の定義を追加します。

service-config.xml を編集します。

services の中に以下の定義を追加。
  1. <service id="message-service" class="flex.messaging.services.MessageService">  
  2.   <adapters>  
  3.     <adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" />  
  4.   </adapters>  
  5.   
  6.   <default-channels>  
  7.     <channel ref="grails-streaming-amf"/>  
  8.     <channel ref="grails-polling-amf"/>  
  9.   </default-channels>  
  10.   
  11.   <destination id="sb-1" />  
  12. </service>  


*デフォで入っている default-channels が services 全体になっているので、はじめから定義されている remoting-service の中に正しく入れてやる

desitination ってのが接続するキーになります、このタグの中にある security って項目を使うと別のユーザ管理と認証が出来ます。
(acegi と連動出来たら素敵ですが、とりあえず認証無しで)

channelsに以下を追加
  1. <channel-definition id="grails-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">  
  2.     <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>  
  3.     <properties>  
  4.         <idle-timeout-minutes>0</idle-timeout-minutes>  
  5.         <max-streaming-clients>10</max-streaming-clients>  
  6.         <server-to-client-heartbeat-millis>5000</server-to-client-heartbeat-millis>  
  7.         <user-agent-settings>  
  8.             <user-agent match-on="MSIE" kickstart-bytes="2048" max-streaming-connections-per-session="1"/>  
  9.             <user-agent match-on="Firefox" kickstart-bytes="2048" max-streaming-connections-per-session="1"/>  
  10.         </user-agent-settings>  
  11.     </properties>  
  12. </channel-definition>  
  13.   
  14. <channel-definition id="grails-polling-amf" class="mx.messaging.channels.AMFChannel">  
  15.     <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>  
  16.     <properties>  
  17.         <polling-enabled>true</polling-enabled>  
  18.         <polling-interval-seconds>4</polling-interval-seconds>  
  19.     </properties>  
  20. </channel-definition>  


FlexPlugin では GrailsBootstrapService というクラスが BlazeDS の起動時に読み込まれるので、ここで MessageClientListener を登録してやります。

  1. MessageClient.addMessageClientCreatedListener(new ClientWatcher())  


ClientWatcher は MessageClientListener を implements したクラス、サンプルでこんなのを用意してみました。

  1. package org.codehaus.groovy.grails.plugins.flex;  
  2.   
  3. import flex.messaging.MessageClient;  
  4. import flex.messaging.MessageClientListener;  
  5.   
  6. public class ClientWatcher implements MessageClientListener {  
  7.  /** 
  8.   * クライアントが接続したときに呼ばれる。 
  9.   */  
  10.  public void messageClientCreated(MessageClient msgClient) {  
  11.    println "connect client"  
  12.     
  13.   // 自身をクライアントの切断を監視するリスナとしても登録する。  
  14.   msgClient.addMessageClientDestroyedListener(this);  
  15.  }  
  16.   
  17.  /** 
  18.   * クライアントが切断したときに呼ばれる。 
  19.   */  
  20.  public void messageClientDestroyed(MessageClient msgClient) {  
  21.   println "disconnect client"  
  22.   
  23.   // 明示的にセッションを破棄する。  
  24.   msgClient.getFlexSession().timeout();  
  25.  }  
  26. }  


でもクラスを直指定はいけてないので、Acegi風にDefaultConfigで対応するクラスを乗せ変えられるようにしてみました。

  1. // Configのロード  
  2. GroovyClassLoader classLoader = new GroovyClassLoader(getClass().getClassLoader())  
  3. ConfigObject config  
  4. ConfigObject flexConfig  
  5. try {  
  6.   flexConfig=new ConfigSlurper().parse(classLoader.loadClass('FlexConfig'))  
  7. catch(Exception e) {  
  8. }  
  9.   
  10. if(flexConfig) {  
  11.   config=flexConfig  
  12. else {  
  13.   config=new ConfigSlurper().parse(classLoader.loadClass('DefaultFlexConfig'))  
  14. }  
  15.   
  16. // クライアントの接続を監視する  
  17. def className="${config.flex.blazeDs.messageClientListener}"  
  18. def clientListener=classLoader.loadClass(className).newInstance()  
  19. MessageClient.addMessageClientCreatedListener(clientListener)  


ここをやっている時、Class.forName() でエラー出てハマっていたので Google先生に聞いてみたら自分が教えてくれた あるあるw
でも GroovyClassLoader を定義してるんでそっちを使ってみた

これで下準備は完了!
次回は接続&メッセージ送信編

この件の事もあるし、要望あれば plugin 公開してもいいかな・・・)

2009年4月6日月曜日

マカーがSubversionを1.6へ移行する道程

Grailsが1.1になってplugin repositoryを設定出来るようになったりして使ってみようと思ったんだけど、どうやらSubversion1.6でないとだめらしい
(Macにデフォで入ってるのは1.4.4なわけですよ)

1.6の新機能詳細はこちら
Mac用のバイナリがここにあるので、これをインストール

/usr/bin/svn を1.6に置き換え、既存のプロジェクトを操作してみる・・・
特に問題無し、.svnの中身は自動でアップグレードしてくれるらしい

ただし下位互換が無いので、一度プロジェクトを1.6にしてしまったら全ユーザが1.6にする必要あり!

・その他、Subversionを使ってたアプリの設定変更
EclipseのSubclipseを1.6用のものに置き換え(アップデートサイトが1.4.x系とは別なんで注意)
Textmateの Preferences > Advanced > Shell Variables の TM_SVN を 1.6 の svn のパスに変更(ここに設定してあったのすっかり忘れてた)

2009年4月3日金曜日

merapiがもたらすAirとJavaの素敵な関係

Air(Flex)でJavaを呼び出すという夢のようなライブラリが登場したようです。
まだベータですが試してみましたのでつらつらと書いていきます。

参考
公式サイト
マイコミの紹介
javaとairを繋ぐmerapiを使ってみた。


まずはJava側の実装から



merapi本体を解凍した中にある framework/java/libs にあるのがJava側で必要なライブラリ
適当なクラスを作って、IMessageHandler を implements する

public static void main の中で Bridge クラスに、自身を regist する

  1. public class MerapiTest implements IMessageHandler {  
  2.  public static void main(String[] args) {  
  3.   System.out.println("start");  
  4.   Bridge.getInstance().registerMessageHandler("merapiSample"new MerapiTest());  
  5.  }  
  6. }  


第一引数でBridgeに登録するID(タイプと呼ぶらしい)、第二引数が自身のJavaクラスのインスタンス

flexから呼ばれた時に handleMessage がcallされるのでこれをクラスに書いておく(インターフェース定義されてます)

  1. public void handleMessage(IMessage obj) {  
  2.   try {  
  3.     System.out.println("flex > java :"+((Message)obj).getData());  
  4.     Message response = new Message("merapiSample""hello merapi");  
  5.     Bridge.getInstance().sendMessage(response);  
  6.   } catch(Exception e) {  
  7.     System.out.println("Caught Exception");  
  8.   }  
  9. }  


IMessageというのがFlexから受け取るデータ、MessageにキャストしてgetDataすると中身を取得出来る。
System.out.println("flex > java :"+((Message)obj).getData());

void なんで return値はなし、Flexに情報を返したい場合は Bridge の sendMessageを使う。
Messageの第一引数にregistしたのと同じIDを指定、第二引数に送りたいデータをセットする。
Message response = new Message("merapiSample", "hello merapi");
Bridge.getInstance().sendMessage(response);

続いてFlex側の実装



merapi本体を解凍した中にある framework/flex/libs にあるのがflex側で必要なライブラリ

まずはBridgeのインスタンスを作成する
  1. <merapi:BridgeInstance id="bridge" result="handleMessage(event)" />  


こっちはresultのfunction名を指定出来る、Javaと同じにしとといた方がわかりやすいかもね!

メッセージの送信は以下のように
  1. var message:Message = new Message("merapiSample","from flex");  
  2. bridge.sendMessage(message);  


MessageクラスはJavaとおんなじ使い方でOK

実行方法


まずは java のクラスを起動してやる必要がある
起動して regist した時点で listen 状態で待機される

この状態でFlexを起動してやると、メッセージを送信出来る
Flexが終了した時点でJavaも落ちる

欠点はJavaを起動する必要がある所かな・・・
終了は一緒に終わってくれるので問題なさそうだけど、Airの起動時にJavaが動いてないとエラーになるんで
なんとかしてJavaを起動してAirを起動するような仕組みが必要

うまく使えばクライアントサイドで今以上に色んな事が出来そうですね!
Grailsとの絡みで考えると、Grails1.1からGORMが単体で使えるようになっているのでsqliteを使った生なDBでなく、GORMを使ってHSQLとかでクライアントDBを実装出来たら素敵な気がする!

2009年4月2日木曜日

Airで画面解像度の取得

Airアプリケーションでユーザの画面解像度を取得する方法、忘れそうなのでメモ

Screen.mainScreen.visibleBounds

返り値はRectangle、macの場合 x , y , w , h で x , y はドックとメニュー分の位置がくるので、
領域として使えるのが w と h で、実際の解像度は x+w , y+h で取得可能。

拡大/縮小させたいメインコンテンツを%指定して作っておけば画面サイズにあわせて自動的にフルスクリーンになるアプリが作れそう。

と、思ったけど最大化ボタンを使えばいいじゃん・・・
ご丁寧に maximize() なんてメソッドもありました。

・・・まぁ何か使う時もあるでしょう!