Twitter sphere of #twitter4j #twtr_hack
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Twitter sphere of #twitter4j #twtr_hack

on

  • 4,727 views

griffon using twitter4j

griffon using twitter4j

Statistics

Views

Total Views
4,727
Views on SlideShare
3,096
Embed Views
1,631

Actions

Likes
3
Downloads
5
Comments
0

7 Embeds 1,631

http://samuraism.jp 1207
http://d.hatena.ne.jp 375
http://localhost 24
http://webcache.googleusercontent.com 9
http://hatenatunnel.appspot.com 7
http://freerss.net 6
http://us-w1.rockmelt.com 3
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Twitter sphere of #twitter4j #twtr_hack Presentation Transcript

  • 1. TwitterSphere ofTwitter4J 2012/02/23 @kimukou2628  
  • 2. ● 今日のソース ○ https://bitbucket.org/kimukou_26/twittersphere4j/src ○ にMercurial(HG)で上げてます<練習がてら● bitbucketには ○ githubみたいな ■ 最新レポジトリのソースのzipダウンロード機能 ○ ないみたいなのでごめんなさい● Windowsの場合は UTF-8のソースなので ○ http://www.asukaze.net/etc/vcs/hg-fixutf8.html ■ を参考にしてダウンロードしてください● MacのGUIクライアントだと ○ MacHg という物があるようです  
  • 3. ソース取得後の動かす前の事前設定(1)● OAuthアプリケーションキーの取得 ○ アプリの登録を行います ○ Twitter にログイン後、下記にアクセス ■ http://twitter.com/apps ○ 「create new application」をクリックしてアプリケーションを 登録 ○ 登録したアプリの詳細をみる。 ○ My Access Tokenをクリック。 ■ consumerKey ■ consumerSecret ■ accessToken ■ accessTokenSecret ○ を取得  
  • 4. ソース取得後の動かす前の事前設定(2)● TwitterSphere4J/griffon-app/resources の中の ○ twitter4j.properties_n をコピー ○ twitter4j.properties_t を作成● 取得した情報をtwitter4j.properties_t の方に書込 ○ その際に # のコメントは外します ● 実行手順) ○ Macの場合 ■ sh runw.sh で実行 ○ Winの場合 ■ runw.bat のJAVA_HOMEを修正、実行
  • 5. ソース取得後の動かす前の事前設定(3)● IDEA11を使って実行したい場合 ○ IDEAインストール ■ startupgroovy で情報まとめられていますので下記参照 ■ https://bitbucket.org/kyon_mm/startupgroovy/wiki/Home   ○ Griffon関係のIDEA上の設定 ■ なんらかのgriffonプロジェクトを作ったり動かす時に ■ GRIFFONのパスをModule(UseLibrary)として追加する必要があり <Androidとかも同じ ○ 詳細は下記URLのブログを参照 ■ http://d.hatena.ne.jp/waman/20111209/1323454481
  • 6. 〜基礎知識編〜
  • 7. 元にしているプログラム● JavaOne 2009 のGriffon のデモアプリ● @kazuchikaさんブログに まとめあり● http://d.hatena.ne. jp/ksky/20090613/p1
  • 8. どんなプログラムなの?● NASA World Wind ○ http://worldwind.arc.nasa.gov/java/index.html● という地球儀を表示するjavaライブラリ● を使ってTwitterの呟きを地球儀上に置く   ● 大元は ○ Twitterのxml,atomをRESTで取得していた ○ griffonが0.2の頃のプログラムだからそのままでは動かな いよ 
  • 9. griffonって何?● codehausさんで作られている● Groovy製のMVCイメージのGUIフレームワークです(デフォルトSwing拡張)● pluginでjavafxにも対応は出来ます(groovyFX ○ codehaus さん ■ SpringSource=>VMWare って感じの系列 ■ jetty(Androidの人なら i-jettyで知っている人多いかな?)も提供● 詳しく知りたい人は ○ @kiy0taka さんのGマガジンのGriffon連載をぜひ ■ http://grails.jp/g_mag_jp/ ■ Griffon不定期便〜G*ワークショップ編〜 ● http://www.slideshare.net/kiy0taka/griffong  
  • 10. griffonの概略イメージ(1)● Model・・グローバル変数とか記述● View ・・表示テンプレート(JSPイメージに近い)● Controller・・実際のアクション処理を書く● Service ・・抽象化した共通処理書く ○ 使っている人が少ないようで挙動が微妙な面も View Controller Model Service
  • 11. griffonの概略イメージ(2) ● BuildConfig.groovy ○ ローカルpluginの参照 ○ mavenからdllしてくるjar記述 ● lib ○ mavenから落とせないjar等を入れるところ ● script ○ griffonコマンドに割込みする処理を記述します ○ 主にant(Builder)を使ってant処理記述 ○ 今回は下記の処理に記述します ■ eventCompileEnd ● コンパイルした後等 ● gant ○ antのgroovy拡張です ○ http://www.ruimo. com/publication/groovyconf/gant.pdf ○ に解説あります  
  • 12. groovyってなに?● javaにおけるスクリプト拡張、いわゆる簡単に使う為の糊み たいな物です(DSLも勿論かけます)● GroovyConsole等を使うとjavaライブラリを簡単に試す事が 出来ます ○ groovyConsole  ● 最近だと ○ NTTデータ さん関連の日経記事が載りました ■ 2012/2/15 ○ http://www.ntts.co.jp/products/grails/index.html
  • 13. Griffonに日本で一番詳しい方の一人ですJenkinsのコミッターとしても有名です さん達とお仕事できる かも~
  • 14. 今回一寸だけ楽になった事● IDEA11で有料版提供されてたGriffonの機能 <Grailsは有料版のみ提供 ○ 無料版 でも提供されるようになった事! ○ ステップデバックも多少は出来るようになるよ! ○ IDEA10より使い勝手はあがりました ● でもデスクトップGUIアプリって人気無いんです よねー(griffonの一文字も記述無し ○ InfoQ IntelliJ IDEA 11 - 新機能 ■ http://www.infoq.com/jp/news/2012/02/idea11
  • 15. 〜デモ〜
  • 16. 〜Twitter(4J)絡みの解説〜
  • 17. ● http://twitter4j.org/ja/api-support.html● の対応表を後で確認しながら読み返して頂けると● 理解は深まると思います ○ もしくは● Twitter API ポケットリファレンス (POCKET REFERENCE) ○ 山本 裕介 (著)● を見比べながら確認してください
  • 18. トレンド取得 def getTrends = { に記述 Twitter API ポケットリファレンス P218 ● トレンド取得コード ● 途中からxmlが廃止されてたみたい ○ 元はxml操作コード ● JSON直接操作 (trends.json)def parser = new JsonParser()jsonText = new URL("http://api.twitter.com/1/trends.json").openStream().textdef obj = parser.parseObject(jsonText)trendNames = obj.trends.collect{it.name} ● Twitter4J書換(trends/:woeid.json 日本トレンド絞込に P225)def trends = twitter.getLocationTrends(locatonID).trendstrendNames = trends.collect{it.name}
  • 19. statuses/public_timeline.json def getPublicResults() に記述 Twitter API ポケットリファレンス P93XMLをパースする方法の場合(旧コード)def doc = slurpAPIStream("http://twitter.com/statuses/public_timeline.xml")doc.status.each { results << [ icon: it.user.profile_image_url as String, tweet: it.text as String, user: it.user.screen_name as String ] Expanddoの} オブジェクトが List追加  されているイメージ
  • 20. Twitter4Jに書換コード(location情報も取れればセット)twitter.getPublicTimeline().each{ st-> println "getPublicResults:" +st.dump() if(model.japanf){ println "st.place=" + st.place?.dump() eachクロージャの中の f("ja".equals(st.place?.country))return return分はcontinue扱いです if(!service.chkLangage(st.text))return } results << [ icon: st.user.profileImageUrl as String, //Stringに明示的に型変換 tweet: st.text, user: st.user.screenName ] f(st.geoLocation!=null){ results.last().pos =Position.fromDegrees(st.geoLocation.latitude,st.geoLocation.longitude,0) } //一度検索済みの場合 else if(model.uMap.get(st.user.screenName)?.pos != null){ results.last().pos = model.uMap.get(st.user.screenName).pos }}
  • 21. search.json def getSearchResults(search) { に記述 Twitter API ポケットリファレンス P247XMLをパースする方法の場合(旧コード)def url = "http://search.twitter.com/search.atom?q=${URLEncoder.encode(search)}&rpp=${model.searchLimit}"//println "url="+urldef doc = service.slurpAPIStream(url)//println "doc="+doc.dump()doc.entry.each { results << [ icon: it.link[1]["@href"] as String, tweet: it.title as String, user: (it.author.uri as String)[19..-1] //19文字目から末尾までという意味 ]} 
  • 22. Twitter4Jに書換コード(location情報も取れればセット)def q = new Query(search);q.setRpp(model.searchLimit); //検索リミット数//日本語限定の検索(過去7日になる)if(model.japanf){ setLangを指定すると q.setLang(slocale) 直近7日間の検索 q.setLocale(slocale) になってしまうらしい}if(twitter==null)twitter = new TwitterFactory().getInstance()def arr = twitter.search(q).getTweets();arr.each{ results << [ icon: it.profileImageUrl as String, tweet: it.text, user: it.fromUser ] if(it.geoLocation!=null){ results.last().pos =Position.fromDegrees(it.geoLocation.latitude,it.geoLocation.longitude,0) } //一度検索済みの場合 else if(model.uMap.get(it.fromUser)?.pos != null){ results.last().pos = model.uMap.get(it.fromUser).pos }}
  • 23. users/show.json def addLocation(def tweet) { に記述 Twitter API ポケットリファレンス P153XMLをパースする方法の場合(旧コード)def twitterUser = slurpAPIStream("http://twitter.com/statuses/public_timeline.xml$tweet.user")//位置情報をRESTするサービスに問い合わせdef gnm = service.slurpAPIStream("http://ws.geonames.org/search?maxRows=1&q=${URLEncoder.encode(twitterUser.location asString)}")if (gnm.geoname.size()) { tweet.pos = Position.fromDegrees( Float.parseFloat(gnm.geoname[0].lat as String), Float.parseFloat(gnm.geoname[0].lng as String), 0);} 
  • 24. Twitter4Jに書換コードdef user =twitter.showUser(tweet.user)//位置情報の取得tweet.pos = service.getPosition user,model.tweetListPos//ユーザ座標の記録 showuser呼びまくるとdef posObj = new Expando() APIが直ぐ無くなるので 状態は保存するposObj.pos = tweet.posmodel.uMap.put(tweet.user,posObj) ● Map等で複数の値を持つオブジェクト等を値にしたい時 ○ Expando を使うと便利です ■ プログラミングGroovy P206 のコラムに記載があります ○ 動的にプロパティ(値,関数)を生成できます  def obj = new Expando()   obj.name =ほげほげ println "obj.name = ${obj.name}"
  • 25. statuses/sample.json def getStreamResults(){ に記述 Twitter API ポケットリファレンス P273if(stream == null ){ stream = new TwitterStreamFactory().instance stream.addListener(listener)}stream.sample() statuses/filter.json def getFilterResults = { に記述 Twitter API ポケットリファレンス P273FilterQuery query = new FilterQuery()query.track([search] as String[])stream.filter(query) 
  • 26. StatusListener記述(1)listener = [ onStatus: { st -> if(model.japanf){ println "st.place=" + st.place?.dump() if(st.place !=null && !"ja".equals(st.place?.country))return if(!service.chkLangage(st.text))return } model.tweetList << [ icon: st?.user?.profileImageUrl as String, tweet: st?.text, user: st?.user?.screenName ] if(st?.geoLocation!=null){ model.tweetList.last().pos =Position.fromDegrees(st.geoLocation.latitude,st.geoLocation. longitude,0) } //一度User検索済みの場合 else if(model.uMap.get(st?.user?.screenName)?.pos != null){ model.tweetList.last().pos = model.uMap.get(st?.user?.screenName).pos } //model.tweetListPos = 0 //model.searching = false if(model.searching==false)nextTweet() }, 
  • 27. StatusListener記述(2)listener = [ 〜略〜 //http://twitter4j.org/ja/code-examples.html onDeletionNotice:{statusDeletionNotice-> println "Got a status deletion notice id:" + statusDeletionNotice.statusId }, onTrackLimitationNotice:{numberOfLimitedStatuses-> println "Got track limitation notice:" + numberOfLimitedStatuses }, onScrubGeo:{ userId,upToStatusId -> println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId) }, onException: { ex -> ex.printStackTrace() },//] as UserStreamAdapter] as StatusListener  ● Streaming処理で使っているリスナー定義です (コールバック処理)
  • 28. def getAsyncResults = { Twitter API ポケットリファレンス ??if(asyncTwitter == null ){ asyncTwitter = new AsyncTwitterFactory().instance asyncTwitter.addListener asynclistener }//asyncTwitter.updateStatus(args[0]);Paging page = new Paging(1,20)asyncTwitter.getHomeTimeline(page)//asyncTwitter.getDirectMessages(page)//asyncTwitter.getMentions(page)  自分で定義した プロパティ関数 呼んでるイメージ
  • 29. TwitterAdapter記述 <AsyncTwitter処理で使用listener = [ gotHomeTimeline:{statuses -> List results = [] statuses?.each {st-> if(model.japanf){ if(st.place !=null && !"ja".equals(st.place?.country))return if(!service.chkLangage(st.text))return } results << [ icon: st?.user?.profileImageUrl as String, tweet: st?.text, user: st?.user?.screenName ] if(st?.geoLocation!=null){ results.last().pos =Position.fromDegrees(st?.geoLocation?.latitude,st?.geoLocation?. longitude,0) }//一度検索済みの場合 else if(model.uMap.get(st.user.screenName)?.pos != null){ results.last().pos = model.uMap.get(st.user.screenName).pos } } edt { model.tweetListPos = 0 model.tweetList = results model.searching = false if(model.searching==false)nextTweet() } }, 〜略〜] as TwitterAdapter
  • 30. Streaming等の停止は・・・ def onSearch = { に記述//streaming 一度止める//ストリーミング受信if(stream!=null){ stream.cleanUp() stream=null viewの表示と同期を取りたい変数に関しては} edt{//非同期検索 //実際の処理if(asyncTwitter!=null){ } asyncTwitter.shutdown() asyncTwitter=null 依存しなくても問題無い非同期処理は} doOutside{  //実際の処理//GUIと連動している変数は同期を取る }edt { クロージャの中に記述します model.tweetListPos = 0 model.tweetList?.clear()}  ● ModelでBindable、Viewでbind と記述されている変数に関しては edt で書換す る方が良いとされています (値が変わると画面の表示状態が連動して動く為) ● http://www.slideshare.net/kiy0taka/griffong のP46に対応表あり
  • 31. 〜今回はまった処〜
  • 32. griffon plugin編<twitter plugin>(1)● def twitterと記述するとinstanceが自動DI(インジェクション)されるはずなのにイ ンスタンスがNullでくる事がある ○ if(twitter==null)twitter = new TwitterFactory().getInstance() ■ の記述を追記  ● 「griffon install-plugin twitter」 でPluginをインストール時● twitter4j.propertiesはinstall時に作るけど、動かす時にclassの位置にコピーし てくれない ■ => ○ script/_Events.groovyでclassフォルダにコピー処理記述● twitter-core 、しかも古いのしか標準ではサポートしていないよ ○ => ○ じゃあローカル参照しますか ■ 公式にはあまり推奨されていないので多少手を入れる必要があり 
  • 33. griffon plugin編<twitter plugin>(2)griffon-twitter/dependencies.groovy package-pluginの時に参照(公式推奨の記述 正確にはプラグインの griffon-app/conf/BuildConfig.groovy が変換されたものらしい//runtime org.twitter4j:twitter4j-core:2.2.0runtime org.twitter4j:twitter4j-core:2.2.6-SNAPSHOTruntime org.twitter4j:twitter4j-stream:2.2.6-SNAPSHOTruntime org.twitter4j:twitter4j-async:2.2.6-SNAPSHOT griffon-twitter/script/_Events.groovy ローカル参照でも動かせるようにする時に記述する compileに変更しておかないとエラーになるので注意!(詳細は次ページ//compile org.twitter4j:twitter4j-core:2.2.0compile org.twitter4j:twitter4j-core:2.2.6-SNAPSHOTcompile org.twitter4j:twitter4j-stream:2.2.6-SNAPSHOTcompile org.twitter4j:twitter4j-async:2.2.6-SNAPSHOT 
  • 34. プラグインのローカル参照記述個所 相対パスでOKですgriffon-app/conf/BuildConfig.groovy 末尾追記 griffon.plugin.location.eclipse-support="../griffon-eclipse-support" griffon.plugin.location.twitter="../griffon-twitter" プラグイン側の修正 grails pluginと微妙に作りが違うので小手先技が必要griffon-twitter/script/_Events.groovy //mavenからjarをDL(ダウンロード)してくる記述 eventSetClasspath = { cl -> manager.parseDependencies { 等記述  //addon のjarコピー記述 eventCopyLibsEnd = { jardir -> def twitterLibDir = "${getPluginDirForName(twitter).file}/addon" ant.copy(todir: jardir, overwrite: true ) { fileset(dir: twitterLibDir, includes: *.jar) } 
  • 35. addon-jarの正規の挙動的には● install-plugin 時に ○ griffon-app/conf/Builder.groovy ■ root.TwitterGriffonAddon.addon=true ○ の追記処理の記述が追加されています ■ griffon-twitter/scripts/_install.groovy に記載あり ● が ○ 相対参照しているときはどうもadd-onは動くような挙動する気がする ○ コントローラ等のEventに対して、DSL記述により イベント割込を付加するイメージなので、その場合は必要かも ■ 今回はその割込イベント未使用なので記述を有効にしてません   ○ 使用サンプルの tweetagile は 0.9.4では動きませんでした ■ http://sourceforge.net/projects/tweetagile/develop    
  • 36. Nasa World Wind 編● pluginアップデートで処理関数の記述が変更● デフォルトのフォントが日本語未対応 ■ => ○ 日本語呟きが化ける ■ => ○ アプリ側でfontを設定して表示 ○ IPAフォントを griffon-app/resources にいれて ○ script/_Events.groovy でclassフォルダにコピー処理記 述● 地表から300km以下になると地表表示が出来ない ○ 350km辺りで調整 ■ plugin 自体は worldwind-0.6.680.14215.jar を使っていますが最新の1.2でも同じなので公式のその まま使う
  • 37. script/_Events.groovyの記述例 ○の箇所(antの知識は必要かもeventCompileEnd = {msg-> println "==compile end(${msg})==" growlNotify("eventCompileEnd")   srcDir ="${basedir}/griffon-app/resources" destDir = "${classesDir}" ant.copy(file:"${srcDir}/twitter4j.properties_t",tofile:"${destDir}/twitter4j. properties",overwrite:true) //ant.copy(file:"${srcDir}/twitter4j.properties_n",tofile:"${destDir}/twitter4j. properties",overwrite:true)   destDir = "${basedir}/staging" copySetting(destDir)   //need TTF & DDL Copy (defaul griffon-app/resources only image file) //○ srcDir ="${basedir}/griffon-app/resources" destDir = "${classesDir}" 設定は手動でコピーし ant.copy(todir: destDir, overwrite: true ) { ましょう。 fileset(dir: srcDir, includes: *.ddl,*.TTF) な話は結構あります }}  
  • 38. giffon-app/controllers/twittersphere4j/TwitterSphere4JController.groovy//コントローラ初期化時に最初に通る関数void mvcGroupInit(Map args) { if(model.vfont==null) def fontname="ipag.ttf" InputStream is=getClass().classLoader.getResourceAsStream(fontname) model.vfont = Font.createFont(Font.TRUETYPE_FONT, is).deriveFont(12.0f) is.close() } //コントローラ終了時(アプリケーション終了時)に必ず通る関数void mvcGroupDestroy() { //viewが初期化された後に通るイベントプロパティ関数def onStartupEnd = {    giffon-app/views/twittersphere4j/TwitterSphere4JView.groovy def addTweet(pos, user, tweet, tweetImage) { bean(ga.attributes, insets: [inset, 48 + inset * 2, inset, inset], font:model.vfont, //☆ 追加
  • 39. StremingAPIで国で絞り込めない● @jontaniさんに教えて頂いた language_detection で 呟き内容の言語判定で対応 ○ http://d.hatena.ne. jp/n_shuyo/touch/20111125/language_detection
  • 40. giffon-app/service/twittersphere4j/TwitterSphere4JService.groovydef chkLangage = {msg -> //http://code.google.com/p/language-detection/wiki/ProjectHomeJa def detector = DetectorFactory.create() detector.append(msg) String cn = detector.detect() println "detector.detect()=$cn" if( !"ja".equals(cn) ) return false return true} ● ファイル構成は ○ lib/langdetect.jar ○ setting/profiles● に配置● script/_Events.groovyに下記にコピー処理記述追記 ○ stanging
  • 41. IDEAでpropertiesのnative2ascill変換のやり方側が悩んだ● 結論から言うと下記な形。デフォルトでONになってない
  • 42. IDEAの操作的にはこんな感じ
  • 43. 一応Springの技術的には● UTF-8 encoding and Spring message sources ○ http://www.cakesolutions. net/teamblogs/2009/04/02/utf-8-encoding-and- message-sources/ ■ みたいな話はあって   ○ org.springframework.context.support. ResourceBundleMessageSource ● => ○ org.springframework.context.support. ReloadableResourceBundleMessageSource   ○ に差し替えれば可能な記述はあるのですが・・orz 
  • 44. Springとは● GrailsやGriffon等Groovy系のFWで使われているコアライブ ラリ群です ○ SpringSourceで開発されています ■ 国内ではSeasar人気ですが ● 日本人のひがやすおさんが作られていて ● マニュアルが日本人ドキュメントの為 ■ 日本人は英語ドキュメント嫌いな人が多いんですよね ~ ■ だから海外の会社系FWは日本語マニュアル揃えた りする労力が・・・ 
  • 45. 〜griffonの 基本オペレーション (IDEA)〜
  • 46. griffonコマンドの発行● ベースはコマンドライン開発FWなのでコマンドでコンパイル、実行できたりします● IDEA上からのコマンド実行は下記な感じ(「griffon clean」実行例 ○ griffon の部分は いらない感じです
  • 47. よく使うコマンド● griffon clean ○ コンパイル済みのクラスファイル、 直下のstadingフォルダを削除します (エラーが出た場合はjavaプロセスを終了して再実行)● griffon run-app ○ IDEAの実行ボタンと同じ● griffon install-plugin XXX ○ http://griffon.codehaus.org/Plugins ○ http://svn.codehaus.org/griffon/plugins/ ○ に公開されているPluginをインストールして機能拡張が出来ます● griffon interactive ○ 継続実行が速くできるという奴ですけど。 ■ コマンドライン実行では重宝 ○ IDEAでやるとOutOfmemoryがよく出るorz
  • 48. 〜開発時によく困る事〜
  • 49. 認証情報等が入ったファイルの管理● 認証情報が入った twitter4j.properties って上げちゃうの恐 いですよね(下記みたいな呟きが出てしまう     ● その場合は ○ scripts/_Events.groovy にファイル名変えてコピーの処理を記述 ■ DVCS管理用のダミーファイルは用意しておきましょう ○ .hgignore(.gitignore)に除外処理を書いておきましょう 
  • 50. script/_Events.groovyの記述例eventCompileEnd = {msg-> println "==compile end(${msg})==" growlNotify("eventCompileEnd")  //上がキー書いた方、下がキー書いていない方の記述例(認証いらない奴なら下でOK) srcDir ="${basedir}/griffon-app/resources" destDir = "${classesDir}" ant.copy(file:"${srcDir}/twitter4j.properties_t",tofile:"${destDir} /twitter4j.properties",overwrite:true) //ant.copy(file:"${srcDir}/twitter4j.properties_n", tofile:"${destDir}/twitter4j.properties",overwrite:true)   destDir = "${basedir}/staging" copySetting(destDir)   //need TTF & ddl Copy (defaul griffon-app/resources only image file) srcDir ="${basedir}/griffon-app/resources" destDir = "${classesDir}" ant.copy(todir: destDir, overwrite: true ) { fileset(dir: srcDir, includes: *.ddl,*.TTF) }}   
  • 51. 立ち上がらないんだけど?● プロセスが正常終了しない場合 ○ GUIが立ち上がっていない状態で、タスクマネージャで、 jqs、javaのプロセスが立ち上がっていたら強制終了しま しょう ■ エラーが発生したりするとSwingプロセスが残ってしま う ○ mac等 ■ ps -aux | grep java 等で確認して kill -9 で ■ コンソール実行している場合は command +・ で
  • 52. 変更が反映されない、コンパイルエラーが・・● griffon clean コマンドを実行します ○ 実行の仕方は以下(IDEAから実行するときは 「clean」) ○ cleanコマンドで エラーが出るときはタスクマネージャ等(ps)でjavaプロセス がいないか確認しましょう
  • 53. ClassNotFoundExceptionが・・● jarのコピー失敗 ○ griffon run-app 実行時 ○ $HOME/.ivy からjarの存在チェック ● 無ければ maven Repo から自動DL ○ $HOME/.ivy =>stanging フォルダ にコピー ● のどの段階かでライブラリが破損している(DL失敗)恐れがあります 1. stangingフォルダのjarのサイズが小さくないか a. 「griffon clean」コマンドを行う 2. $HOME/.ivyの位置にjarが存在するかサイズがおかしく ないか a. サイズがおかしい場合=>そのjarを消して再実行 b. ダウンロードが動いていないとき i. BuildConfig.groovy に事前にDL記述を書いて落とす    
  • 54. griffon-app/conf/BuildConfig.groovy 記述例 language_detection内部でjsonicを使っているのその記述例griffon.project.dependency.resolution = { // inherit Griffon default dependencies inherits("global") { } log "warn" // log level of Ivy resolver, either error, warn, info, debug or verbose repositories { griffonPlugins() griffonHome() griffonCentral() // uncomment the below to enable remote dependency resolution // from public Maven repositories //mavenLocal() //mavenCentral() mavenRepo "http://maven.seasar.org/maven2/" //DL(ダウンロード)元のMavenレポジトリ } dependencies { // specify dependencies here under either build, compile, runtime, test or provided scopes eg. // runtime mysql:mysql-connector-java:5.1.5 //jarの中の関連参照なら runtime compile net.arnx.jsonic:jsonic:1.2.0 //ソースのコンパイルに必要ならcompile }}  
  • 55. 〜知っておくと  一寸コードが  読みやすくなる事〜
  • 56. groovy編(1) ● println "obj=$obj" な形でコンソール出力できます ○ うまく表示されない時は ${obj} のように記述 ● オブジェクトの中身は dump() コマンドで表示可能です ○ println "obj=${obj.dump()}" ● オプジェクとのNullチェックは下記のように書けば不要です ○ println "obj=${obj?.dump()}" ○ この場合、objがnullならnullと出力されます ● オブジェクトのプロパティにはダイレクトにアクセスできます ○ obj.A = "テスト" ○ println "obj=${obj.A}" ● 厳密にはこういう話です https://gist.github.com/1041631   class Hoge { def xxx = 10   def getXxx() { 100 } } def h = new Hoge() assert h.xxx == 100 // getXxxがあればそちら優先 assert h.@xxx == 10 // フィールド値をダイレクトで取得 assert h.getXxx() == 100 // メソッド値をダイレクトで取得
  • 57. groovy編(2) ● def funcA() { } と書くと関数に見えますが、 実はプロパティ扱い(クロージャ変数)です! ○ def func(num){} ■ = ○ def func = {num -> } ○ と同じ意味になります。 ○ また引数の型の方も省略する書き方も可能です(自動判 別  ● void funcB(){ } みたいな書き方は普通の関数      
  • 58. groovy編(3)● クロージャってなんじゃらほ? ○ { }で囲んだ部分の記述 で表現されるCloureという名前のクラスです ■ http://groovy.codehaus.org/api/groovy/lang/Closure.html ○ javascript 等のコールバック関数記述イメージが近いかも ○ 参考資料) ■ Groovyでクロージャ内部で設定してもらった値を利用する ■ http://d.hatena.ne.jp/fumokmm/20101008/1286547976 ■ 下記は testというクロージャ変数の例 test { println it // => 一つ目の引数 println this // => このクラス println owner // => このクロージャ保有者 println delegate // => このクロージャ移譲先(Objective-Cでいう親クラス参照) println that // thatで指定された文字列 map.count = 1 // mapも参照できる map.clos = { that * 3 } }
  • 59. griffon編・・SwingBuilder編(1)● Plugin拡張をしていない場合、Viewは SwingBuilderというSwingのDSL拡張で記述 ○ http://groovy.codehaus.org/Japanese+Swing+Builder ○ http://groovy.codehaus.org/Alphabetical+Widgets+List ■ の記載情報が編集する為の情報のベースになります ● 「プログラミングGroovy 」の P139  から数ページ少し解説があります ● IBMの技術資料 ○ http://www.ibm.com/developerworks/jp/java/library/j- groovy09299/index.html● @toby55kij さん SwingBuilderでGroupLayoutを使ってみる。 ○ http://www.tobikkiri.org/2009/08/swingbuildergrouplayout.html  
  • 60. griffon編・・SwingBuilder編(2)● よく使う奴を列挙してみます ● レイアウト系 ○ hbox { } ・・ 横レイアウト ○ vbox { } ・・縦レイアウト ○ レイアウト() みたいに記載するとその直後の奴はそのレイ アウトで配置できます ■ borderLayout() ■ cardLayout() ■ gridBugLayout() ● http://desmontandojava.blogspot. com/2012/02/swingbuilder-series-layouts. html
  • 61. GUIパーツの記載イメージ● 下記みたいにmapイメージで書けます ○ 変数名:値 ○ どんな値があるかは、下記みたいに ■ dump()してみるか ■ IDEAで候補出してみるか ● http://d.hatena.ne. jp/masanobuimai/20090105#1231168963 ■ みたいな方法もありますprogressBar(id:hoge,maximum: bind { model.tweetList?.size() ?: 1 }, value: bind {model.tweetListPos})println hoge.dump() 値の連動関連づけです Modelクラスの中でBindableと記載があ る物が対象になります (今回は全体に付いている)
  • 62. griffon編・・SwingBuilder編(3)● controllerとの関連づけはactionPerformed等に 記載します ○ 普通のjavaだとListnerが渡されていますが ○ groovyの場合はクロージャを渡します ■ 渡し方の記載例は次ページbutton(getMessage("view.label.Search"), actionPerformed: controller.onSearch, enabled:bind {!model.searching}, margin: new Insets(5, 10, 15, 20)) 
  • 63. griffon編・・SwingBuilder編(4)● viewで関連づけるClousure参照の記述例ではまることも・・ ○ OK例 ■ button(id:DLGBTN1,text:btn1, actionPerformed:{controller.&action()}) ● closure代入(既存Closureに対してappend(追記) ■ button(id:DLGBTN2,text:btn2, actionPerformed:controller.action) ● closure参照 ■ button(id:DLGBTN3,text:btn3, actionPerformed:controller.&action) ● MethodClosure参照 ○ NG例 ■ button(id:DLGBTN4,text:btn4, actionPerformed:{controller.&action}) ● MethodClosure参照をClosure代入しようとしたから駄目
  • 64. griffon編・・SwingBuilder編(5)● 普通のjavaのパーツを SwingBuilder上に設定する場合2パターンの方 法があります ○ 単純に埋め込み ■ widget ■ http://groovy.codehaus.org/SwingBuilder.widget ● widget(new hogehoge())   ○ SwingBuilderにDSL関連づけする場合 ■ registerFactory ■ registerBeanFactory ● registerFactory("migLayout", new LayoutFactory(MigLayout)) ● registerBeanFactory("led", Led)
  • 65. griffon編(1)● griffon自体のイメージをつかむには ● @waman10da さん Griffon の世界 ○ http://www5.ocn.ne. jp/~coast/programming/groovy/griffon.html   ○ あたりが一番詳しいです。 ○ ただかなり高度な内容もありますので(数学知識も必要) ○ わからないところは読み飛ばしてよいかと思います 
  • 66. griffon編(2)● LL言語は基本エディタで開発するのが前提なので ○ =>「最低限以外は自分で書換」 等のお話が多い ■ 解らなければ末尾の方に載っけている、自分より詳し い方々に聞くと良いかも● serviceクラスをコマンドで作る時 ○ griffon create-service twittersphere4j.TwitterSphere4JService ○ Controller に def service という形で参照したい時 ○ Application.groovyに下記の★ 記述を追加 twittersphere4j { model = twittersphere4j.TwitterSphere4JModel view = twittersphere4j.TwitterSphere4JView controller = twittersphere4j.TwitterSphere4JController service = twittersphere4j.TwitterSphere4JService //★ }
  • 67. griffon編(3)● airbag plugin とかの説明そのままだと動かなかったり(汗 ○ http://griffon.codehaus.org/Airbag+Plugin ■ 実はTwitterSphere4JView.groovyの 記述修正が必要だったりとか・・・   ○ application(title: TwitterSphere4J, ■ => ○ mainWindow = application(title: TwitterSphere4J,
  • 68. IDEAを使うと多少楽になるので● キーマップに慣れましょう ○ eclipseと大分違うので混乱はします ○ http://www.jetbrains.com/idea/docs/IntelliJIDEA_ReferenceCard.pdf ● @masanobuimai さんブログIDEA周りの話を読みましょう ○ 初めてIntelliJに触れる人へ ■ http://d.hatena.ne.jp/masanobuimai/20091017/1255784181 ■ http://d.hatena.ne.jp/masanobuimai/20091021/1256129174   ○ モダンなIntelliJ環境の構築方法 http://d.hatena.ne. jp/masanobuimai/20100726%231280151977● IDEAに詳しい人に効いてみましょう
  • 69. 〜今後に期待編〜
  • 70. IDEA11で現状残念な処<use griffon(1)● griffon-app/conf/BuildConfig.groovy ○ griffon.plugin.location.プラグイン名が認識しない・・。 ○ 手動で追加も出来ない
  • 71. IDEA11で現状残念な処<use griffon(2)● ivy経由で取得したjarがうまく認識しない ○ 従ってIDEAの強力機能 => リアルタイム補完 ×     ● maven だと下記の記事参考になるようなんだけど・・● @yusukeyさんの記事 Mars Phoenix の最後の Tweet を IntelliJ IDEA 8 と Twitter4J を使ってデコードする ○ http://samuraism.jp/diary/2008/11/15/1226684171300.html@masanobuimai さん記事 Scripting IDE for DSL awareness ○ http://d.hatena.ne.jp/masanobuimai/20091021#1256129173
  • 72. IDEA11で現状残念な処<use griffon(3)● スレッド周りの処理にブレークポイントを貼っても止まらない 事が多い● 普通のJavaプログラムでもそうなんですが ○ スレッドプログラムでエラー ■ => ○ 処理中断 でストール な現象になる事が多い ● src/main/java がちゃんと認識しない ○ その他の部品等は src/main/java,src/main/groovy とディレクトリを掘ってい れます   
  • 73. IDEAで今後出来たらいいなと思うこと● Viewのプレビュー表示 ○ IDEA11でAndroidのレイアウトプレビューが出来るよう になったのでこちらも期待したいなー ● groovyファイル(Controller)の関数表示がツリー に出てくると楽 ○ 今は関数名等を検索しないと駄目 ○ 関数Jumpが今は出来ない >< 
  • 74. eclipseではどう?● griffon-eclipse-support plugin ○ griffonコマンドを実行するたびに.classpath等更新 ○ 公式のだとWinXP等空白パスあるのでは動きません ■ => ○ 修正してローカル参照で動かしています ○ 一応jarのクラスパスは通っているのでエラーは出ないけど・・  ● groovy eclipse plugin 自体が ○ def 等に代入した変数に対して補完きかない ○ そもそもブレークポイントでとまらない事が多い ■ Grailsでは止まるので<STS対応されている為か
  • 75. NetBeansでは?● NetBeansインストール後手動で下記のPlugin等 を追加する必要があり (すみません。最新版で確認する時間ありませんでした) ● Netbeans griffon plugin ○ http://plugins.netbeans. org/PluginPortal/faces/PluginDetailPage.jsp? pluginid=18664 ● Netbeans gradle plugin ○ http://plugins.netbeans.org/plugin/41776/gradle
  • 76. 〜groovyを勉強するには〜
  • 77. ネットの情報で学習(お試しレベル● @fumokmm さんのブログ ○ Groovy基礎文法最速マスター ○ http://d.hatena.ne.jp/fumokmm/20100605/1275736594 ○ Groovy全般に関して広い知見を学べます● 日曜プログラマ劇場 ○ http://www.noids.net/groovy/ ● 試す実行環境(Javaは別途必要) ○ @bluepapa32 さん GroovyConsole JavaWebStart ■ http://d.hatena.ne.jp/bluepapa32/20101228/1293466511 ■ gradleの記事が豊富に書かれているブログです
  • 78. ● このインタビューに載っている本を買いましょう ○ 青い本とは何でしょう? 日本鼻メガネの会 の公式読本 でしょうか? ○ http://theinterviews.jp/inda_re/3039859   ■ プログラミングGroovyというタイトルです
  • 79. ネットの情報で学習(少し慣れてきたら● @uehaj さんの Grな日々 ○ http://d.hatena.ne.jp/uehaj/ ■ 最新技術や情報について記載されていますので 中級者~上級者向けかも● @kazuchika さんの Groovyラボ ○ http://d.hatena.ne.jp/ksky/ ○ JavaOne等の情報も絡めたお話があります  ● @bikisuke さんの bikisuke in Action ○ http://d.hatena.ne.jp/bikisuke/ Spockのお話とかがあります
  • 80. ネットの情報で学習(少し慣れてきたら● @nobusueさん nobusueの日記 ○ http://d.hatena.ne.jp/nobusue/  ● @genzouw さんゲンゾウ用ポストイット ○ http://d.hatena.ne.jp/genzouw/  ● @kiy0taka さんblog4j 2.0 ○ http://d.hatena.ne.jp/kiy0taka/ ○ Griffon、Jenkinsの情報が豊富です
  • 81. ネットの情報で学習(少し慣れてきたら● @tyama さんleftovers... ○ http://d.hatena.ne.jp/mottsnite/ ○ Grails情報はここが一番充実  ● @yamadamasaki さんGrails goes on ○ http://grailsgoeson.metabolics.co.jp/ ○ JGGUG主宰の方です● @nobeans さん豆無日記 ○ http://d.hatena.ne.jp/nobeans/ ○ GroovyServの開発者の方です
  • 82. ネットの情報で学習(少し慣れてきたら● @literalice さんLiteral Ice ○ http://monochromeroad.blogspot.com/ ○ gradleの日本語翻訳をメインでされてます ○ http://monochromeroad.com/artifacts/gradle/userguide/userguide. html● @irof さん日々常々 ○ http://d.hatena.ne.jp/irof/ ○ 全国の勉強会を行脚していらっしゃいます ○ すごく知見に富んだ方です● 海外サイトだと下記が超有名(コミッタさん) ○ Groovy Goodnes ■ http://mrhaki.blogspot.com/search/label/Groovy%3AGoodness
  • 83. 下記のクラスタをフォローしましょう● Groovyクラスタ ○ 特にJGGUG講師の方はオススメ   ○ @orange_clover さんまとめ ○ 今すぐフォローすべき Groovy界のスーパーエンジニア ■ http://d.hatena.ne. jp/orangeclover/20110618/1308355956    
  • 84. ● 日本鼻メガネ会クラスタ(#riskrisk #日本鼻メガネの 会) ■ Groovyクラスタと重なっている人が多いです ■ http://riskrisk.hatenablog.com/entry/2012/02/14/032704 ● という組織 ■ ただ有能な方々ばかりでお忙しい方々なので ● インタビューズを遣られている方にはそちらで質問しましょう ● inda_re 先生、kyon_mm先生、mike_neck先生あたり@orange_clover @shinyaa31 @inda_re @riskrisk @kyon_mm @mike_neck @nobusue
  • 85. Groovy系の勉強会に参加しましょう ● JGGUG ○ 日本Groovyユーザ会 ■ 定期的に ■ http://kokucheese.com/main/host/JGGUG ■ http://grails.jp/ ■ #JGGUG ハッシュタグ   ○ Grailsドキュメント会 (名古屋) ■ Grailsのドキュメント翻訳をされている @tyama さんが メインで開催されています ■ http://kokucheese.com/main/host/+Grails%E3% 83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83% B3%E3%83%88%E4%BC%9AGrailsに関して  日本で一番詳しい方の一人  
  • 86. Groovy系の勉強会に参加しましょう● StartupGroovy ○ 2012 /02 / 18 ■ 開催まとめ ● http://d.hatena.ne. jp/absj31/20120218/1329636558 ○ http://kokucheese.com/event/index/26942/ ■ 2回目も要望があれば企画されるそうです