Twitter4jでつぶやく

ClojureTwitterbotを作ろうと思い、TWitterライブラリを探してみたら、Twitter4Jは扱いが簡単そうだったので試してみた。
Twitter4Jは最新の安定バージョンである2.1.0を使用した。
まずは、Twitter4Jのサンプルコードを参考に、つぶやくコードを書いてみた。

(ns twitter.hellobot
  (:import (twitter4j TwitterFactory Twitter)))

(def user-id "******")
(def password "******")

(def twitter (. (TwitterFactory.) getInstance user-id password))

(. twitter updateStatus "Hello, world!")

実行すると、twitterインスタンスの取得でエラーとなる。

(def twitter (. (TwitterFactory.) getInstance user-id password)) ←◆ここでエラー

getInstanceメソッドが見えないようだ。

No matching method found: getInstance for class twitter4j.TwitterFactory
  [Thrown class java.lang.IllegalArgumentException]

Restarts:
 0: [ABORT] Return to SLIME's top level.

Backtrace:
  0: clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:85)
  1: clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
  2: clojure.lang.Compiler$InstanceMethodExpr.eval(Compiler.java:1150)
  3: clojure.lang.Compiler$DefExpr.eval(Compiler.java:298)
  4: clojure.lang.Compiler.eval(Compiler.java:4537)

何が原因が良く分からないので、とりあえずclojureのバージョンを1.1.0に上げて試してみたら、以下のエラーとなった。

Can't call public method of non-public class: public java.lang.Object twitter4j.TwitterFactoryBase.getInstance(java.lang.String,java.lang.String)
  [Thrown class java.lang.IllegalArgumentException]

Restarts:
 0: [ABORT] Return to SLIME's top level.

Backtrace:
  0: clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:85)
  1: clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
  2: clojure.lang.Compiler$InstanceMethodExpr.eval(Compiler.java:1206)
  3: clojure.lang.Compiler$DefExpr.eval(Compiler.java:302)
  4: clojure.lang.Compiler.eval(Compiler.java:4647)
  5: clojure.core$eval__5236.invoke(core.clj:2017)

バージョン1.1.0ではエラーメッセージが親切になっている。
TwitterFactoryBaseクラスはTwitterFactoryクラスの親クラスであり、そのクラスがgetInstanceメソッドを実装している。エラーを見ると親クラスTwitterFactoryBaseも可視属性がpublicでないと駄目のようだ。
リフレクションの仕様?時間ができたら調べてみよう。

面倒になってきたので、twitter4jのソースを修正し、TwitterFactoryBaseクラスをpublicにしてみる。

twitter.hellobot> (def twitter (. (TwitterFactory.) getInstance user-id password))
#'twitter.hellobot/twitter
twitter.hellobot> 

正常にインスタンスを取得できたようだ。
一歩前進だが、いきあたりばったり方式でちょっと鬱。

twitterインスタンスが取得できたので、つぶやいてみる。

twitter.hellobot> (. twitter updateStatus "hello, world!")
#<StatusJSONImpl StatusJSONImpl{createdAt=Sat Jan 30 21:32:43 JST 2010, 
  id=8409854604, text='hello, world!', ...以下略...
twitter.hellobot> 

http://twitter.com/ で確認してみる。
書き込めた。\(^▽^)/


Twitter4Jは依存ライブラリが無いので、jarファイル一つで済むので、なかなか良いです。
オープンソースで公開して頂ける作者に感謝です。