最近Scalaでちょっとしたjarアプリを作ることが多いのでその手順をまとめておきます。まだ発展途上とは言え2.0.2になったことでScala IDE for Eclipseも実用に耐えうるところまできているように思います。あとは、リファクタリング機能とクイックフィックス機能がもう少し良くなると良いですが、コンパイルエラーが出た際に、どうするべきかということがポップアップメニューで出るのでその点で助かっています。
ちなみに今回この記事を書こうと思ったのは、今までSbt0.11.2まで利用できた実行jarを作るproguardというプラグインが利用できなくなってしまったこともあり、sbt-assemblyを利用したものを再度書くことにしました。
環境確認
まず、環境情報の確認です。Macのパッケージ管理システムで利用できる2012/07/28現在でできる限り最新安定版を利用しています。
- Java(TM) SE Runtime Environment (build 1.6.0_33-b03-424-11M3720)
- Homebrew 0.9.2
- Scala code runner version 2.9.2 -- Copyright 2002-2011, LAMP/EPFL
- sbt launcher version 0.11.3-2
- Eclipse 3.6.2
- Scala IDE for Eclipse 2.0.2
$ java -version
と実行するとインストールされ、バージョンが確認できます。ソースコード付きのJDKを入れたい方は、この記事を参照。
Homebrewはリンク先を参照してインストールの事。XCodeとCommand line toolsのインストールも必要です。
Scalaとsbtのインストールは
$ brew install scala $ brew install sbt
で完了です。バージョンアップの際には、
$ brew update $ brew upgrade scala $ brew upgrade sbt
を実行します。Eclipse 3.6.2とScala IDE for Eclipse 2.0.2のインストールはリンク先のインストール方法に従って下さい。
というわけで、環境は整ったということでお題であるEclipseでデバッグ可能な外部jarライブラリを内包する実行可能jarを作ってきます。お題は、
「特定のハッシュタグを含むツイートをファイルに保存し続けるアプリ」
です。すでに実装したものが、GitHubの方にMITライセンスでpushしてありますので、ソースコードだけが欲しい場合はこちらをcloneしてお使いください。
プロジェクトの作成
まず、プロジェクトの作成です。ここではtweet_recorderとします。有りそうな名前ですねw
$ mkdir tweet_recorder $ cd tweet_recorder
次にjarを作るまでに雛形を作成します。なお基本的にこのtweet_recorderディレクトリから操作していきます。
$ mkdir -p src/main/scala $ echo 'object TweetRecorder { def main(args: Array[String]) = println("Hi!") }' > src/main/scala/TweetRecorder.scala $ vim build.sbt
build.sbtを編集
name := "tweet_recorder" version := "1.0" scalaVersion := "2.9.2"
次に念のためにsbtもバージョン指定しておきます。
$ mkdir project
$ vim project/build.properties
project/build.propertiesを編集
sbt.version=0.11.3
とここまでで、プロジェクトのひな形は完成。
というわけで早速sbtでビルド、実行してみます。
$ sbt > compile [success] Total time: 15 s, completed 2012/07/29 9:00:22 > run Hi! [success] Total time: 1 s, completed 2012/07/29 9:00:36 > exit
これで大丈夫なことを確かめます。
実行jarの作成
次にjar化できるようにします。他にもjar化させるものはいくつかありますがsbt-assemblyが非常に良い出来だったので、これを使います。
$ vim project/plugins.sbt
project/plugins.sbtを編集
resolvers += Resolver.url("artifactory", url("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases"))(Resolver.ivyStylePatterns) addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.8.3")
$ vim build.sbt
build.sbtを編集
import AssemblyKeys._ // put this at the top of the file assemblySettings name := "tweet_recorder" version := "1.0" scalaVersion := "2.9.2" mainClass in assembly := Some("TweetRecorder")
他にも設定が、github内に書いてありますが、ここではmainメソッドのあるクラスの定義だけ設定します。
そして早速jarを作ってみます。assemblyコマンドでjar作成とのことです。
早速、jarを作成、実行してみましょう。
$ sbt > assembly [info] Done packaging. [success] Total time: 107 s, completed 2012/07/29 9:14:19 > exit $ java -jar target/tweet_recorder-assembly-1.0.jar Hi!
これでOKそうですね。
実行jarへの3rdパーティjarライブラリの梱包
ちなみにもうライブラリとしてtwitter4jを使うことがわかっているので、twitter4jの必要なライブラリとソースをプロジェクトにコピーしてビルドしてみましょう。tmpディレクトリに一度ダウンロードし、削除します。
$ mkdir lib $ mkdir lib-src $ mkdir tmp $ cd tmp $ curl -O http://twitter4j.org/en/twitter4j-2.2.6.zip $ unzip twitter4j-2.2.6.zip $ cp lib/twitter4j-core-2.2.6.jar ../lib $ cp lib/twitter4j-stream-2.2.6.jar ../lib $ cp twitter4j-core/twitter4j-core-2.2.6-sources.jar ../lib-src $ cp twitter4j-stream/twitter4j-stream-2.2.6-sources.jar ../lib-src $ cd .. $ rm -rf tmp $ sbt > assembly [info] Including twitter4j-core-2.2.6.jar [info] Including twitter4j-stream-2.2.6.jar [success] Total time: 1 s, completed 2012/07/29 9:32:14 > exit $ java -jar target/tweet_recorder-assembly-1.0.jar Hi!
これでライブラリの実行jarへの内包も大丈夫そうです。
Eclipseへのsbtプロジェクトのインポート
次に、Eclipseにインポートできるようにします。sbteclipseを使います。
$ vim project/plugins.sbt
project/plugins.sbtを編集して、末尾に追記します。
resolvers += Resolver.url("artifactory", url("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases"))(Resolver.ivyStylePatterns) addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.8.3") addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
編集後、eclipseコマンドを実行します。
$ sbt > eclipse [info] Successfully created Eclipse project files for project(s): [info] tweet_recorder > assembly [info] Including twitter4j-core-2.2.6.jar [info] Including twitter4j-stream-2.2.6.jar [success] Total time: 1 s, completed 2012/07/29 9:32:14 > exit $ java -jar target/tweet_recorder-assembly-1.0.jar Hi!
eclipseプロジェクトの作成も、実行jarの作成もOKそうです。
次に、Eclipseへのインポートです。ScalaパースペクティブのPackage Explorerビューの右クリックメニューにて。Import > General > Existing Projects into Workspaceを選択して、Nextを押します。
Select root directoryで、プロジェクトのフォルダを選択して、Finishボタンを押します。この際に、copyをせずにそのままそのフォルダを利用します。これは今後sbtでビルドを利用するためです。
Twitter4jのStreamingAPIを使った実装とビルド
これでプロジェクトのインポートが終わったので、早速ちょっとコードを書いてデバッグで止めていましょう。
早速サンプルコードを書いてみます。
TweetRecorder.scalaを編集して
import twitter4j.conf.ConfigurationBuilder import twitter4j.TwitterStreamFactory import twitter4j.FilterQuery import twitter4j.StatusListener import twitter4j.Status import twitter4j.StatusDeletionNotice import java.io.PrintWriter import java.io.FileWriter object TweetRecorder { def main(args: Array[String]) = { val conf = new ConfigurationBuilder().setUser(args(0)).setPassword(args(1)).build val twitterStream = new TwitterStreamFactory(conf).getInstance() twitterStream.addListener(new Listener) twitterStream.filter(new FilterQuery().track(args.slice(2, args.length))) } class Listener extends StatusListener { override def onStatus(status: Status) = { val tweet = status.getCreatedAt().toLocaleString() + "," + status.getUser().getScreenName() + "," + status.getText() val writer = new PrintWriter(new FileWriter("tweet_recoder.csv", true)) writer.println(tweet) writer.close println(tweet) } override def onDeletionNotice(statusDeletionNotice: StatusDeletionNotice) = {} override def onTrackLimitationNotice(numberOfLimitedStatuses: Int) = {} override def onException(ex: Exception) = {} override def onScrubGeo(userId: Long, upToStatusId: Long) = {} } }
これでOK。起動する時に第一引数がtwitterのアカウントのID、第二引数がtwitterのアカウントのパスワード、第三引数以降は追跡したいキーワード(英単語か#ではじまるハッシュタグのみ) を半角スペース区切りで追加という感じになります。右クリックでDebag As > Scala Applicationを選択してデバッグ実行で引数が無いという例外が投げられて失敗したあと。
虫アイコンのドロップダウンメニューのDebug ConfigurationのArgumentsタグでそれぞれの引数を設定して実行します。
今回は、単語をすごい量のツイートが流れていそうなhttpに設定して実行します。コンソールに
2012/07/29 11:06:30,Vasilisa_Anime,http://t.co/nKcvZJw7 2012/07/29 11:06:30,Neylianavera,esteeeen; x_x @Georgejsm. http://t.co/Ap5vLa1R
のように表示されればOK。今回は日付、ユーザーID、ツイートをカンマ区切りで表示してます。
最後にビルドして実際に動くか確かめて見ましょう。
今回は、2chまとめのタグ#MT2とニコ動の#nicovideoで検索してみます。
$ sbt > assembly [info] Including twitter4j-core-2.2.6.jar [info] Including twitter4j-stream-2.2.6.jar [success] Total time: 1 s, completed 2012/07/29 9:32:14 > exit $ java -jar target/tweet_recorder-assembly-1.0.jar sifue password \#MT2 \#nicovideo 2012/07/29 11:35:08,nicorank_bot,毎時ランキング第1位:じょしらく 第三席「無情風呂」「浅草参り」「真田小ZOO」 http://t.co/0U9SZFnQ #nicovideo #so18447313 2012/07/29 11:35 現在 2012/07/29 11:35:09,2chtitle,「あっ、こいつインド人だな」って思う仕草 インド人とのつきあい方?インドの常識とビジネスの奥義 を Amazon でチェック! http://t.co/Lf2sWYQ5 #MT2 #まとめ 2012/07/29 11:35:12,zyazya11,RT @Mell_Ta: ニコニコ有名歌い手がポケモン割れ発覚 http://t.co/qQh9eCvL #MT2 今ぐるたみんが熱い
以上のように表示され無事利用できるようです。これで好きなハッシュタグのツイートなどを保存して解析したりするのに使えますね。
ちゃんとtweet_recoder.csvというファイルを確かめても保存できているようです。
以上でScala2.9.2でsbt-assemblyを使ってEclipseでデバック可能な3rdパーティjarを含む実行jarを作るまでの手順を終わりとします。お疲れ様でした。