Apache Ant に組み込みの mail タスクを使用すると、提供されたユーザー・リストに基づいて E メールを送信し、ビルド・プロセスの完了を通知することができます。しかし時間が経過すると、ユーザーの E メール・アドレスが変更されたり、プロジェクトから外れるユーザーが出てきたりするなどして、mail タスクはあまり便利な機能ではなくなります。
Twitter.com が提供する API は公開されており、ユーザーはこの API を使用することで、さまざまなソース (携帯電話、テレビ、ゲーム・コンソールなど) から Twitter アカウントの近況アップデートをすることができます。ビルド完了のアップデートを Twitter アカウントに投稿することで、プロジェクト・チームの開発者やテスターに対し、新しいビルドが利用できるようになったことを即座に通知することができます。これにより、対象となるユーザーは、通知を受け取るか受け取らないかを自由に選択することができ、そこにビルド・エンジニアが関与する必要がないというメリットがもたらされます。
この記事では Twitter クライアントの役割を持つ Ant タスクを作成する方法について説明します。この Ant タスクでは、オープンソースの Java™ ライブラリーを使用して Twitter とやり取りし、このタスクに関連付けられた Twitter アカウントの近況アップデートを通じて、ビルド・ステータスを通知します。この記事のサンプル・コードは「ダウンロード」セクションからダウンロードすることができます。
ビルド通知システムに Twitter を使用するためには、Twitter アカウントを作成してクライアント・アプリケーションを登録する必要があります。
最初のステップは至って簡単です。Twitter.com にナビゲートし、アカウントを作成します。私は説明用に tweet_task という名前のアカウントを作成しました。http://twitter.com/tweet_task にアクセスすると、現在までの近況アップデートを見ることができます。
Twitter アカウントの近況アップデートに使用されるすべてのクライアント・アプリケーションと同様、この記事で作成するクライアント・アプリケーションを使用する前に、まずこのアプリケーションを Twitter に登録する必要があります。OAuth クライアントを登録するための Twitter のページ (http://twitter.com/oauth_clients/new) を開き、表示されるフォームに入力します (図 1)。
図 1. Twitter にアプリケーションを登録する
このフォームの「Application Icon (アプリケーションのアイコン)」フィールドには、クライアント・アプリケーションのアイコンとして使用する画像のファイル名を入力するか、あるいは「Browse (参照)」をクリックしてその画像ファイルを指定します。画像は GIF、JPG、PNG のいずれかのファイルであり、700KB 以下でなければなりません。「Application Name (アプリケーション名)」には、twitter という単語が含まれなければ、どんな名前でも付けることができます (このクライアントを使用して近況アップデートをする場合には必ず、クライアントの名前をサブタイトルとして含める必要があることを忘れないでください。この記事の説明用として、私は tweet_task_client という名前を選びました。これは、すべての近況アップデートに tweet_task_client というサブタイトルが付いていることでわかると思います)。「Description (アプリケーションの説明)」フィールドには、このアプリケーションの簡単な説明を入力します。「Application Website (アプリケーションのウェブサイトURL)」フィールドが空白であってはならないことに注意してください。そこで、アプリケーションの URL を入力します (この URL は無効なものでも構いません)。「Organization (所属会社/団体)」フィールドと、それに関連する「Website (サイト)」フィールドはオプションです。「Application Type (アプリケーションの種類)」として「Client (クライアントアプリケーション)」を選択し、「Default Access type (デフォルトのアクセス・タイプ)」として「Read & Write (読み書き)」を選択します。「Use Twitter for login (Twitterでログインする)」では、隣の「Yes, use Twitter for login (はい、Twitterをログインに使用します。)」を選択します。
アプリケーションが登録されると、「Consumer key (コンシューマー・キー)」と「Consumer secret (コンシューマー・シークレット)」のトークンを含む画面が表示されます。これらをメモし、安全なところに保管します。
Twitter4J は、OAuth のサポートが組み込まれたオープンソースの非公式の Java ライブラリーです。Twitter4J の Web サイト (「参考文献」を参照) から最新リリースをダウンロードし、クラスパスに追加します。
クライアントから Twitter アカウントの近況アップデートをできるようにするためには、そのための権限をクライアントに与える必要があります。リスト 1 は、アプリケーションからアカウントへのアクセスを承認するための URL を生成する簡単なプログラムです。
リスト 1. Twitter4JRegister.java
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;
import twitter4j.http.RequestToken;
public class Twitter4JRegister {
public static void main(String args[]) throws Exception {
Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer("consumer key", "consumer secret");
RequestToken requestToken = twitter.getOAuthRequestToken();
AccessToken accessToken = null;
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(System.in));
while (null == accessToken) {
System.out
.println("Open the following URL and grant access to your account:");
System.out.println(requestToken.getAuthorizationURL());
System.out
.print("Enter the generated PIN:");
String pin = bufferedReader.readLine();
try {
if (pin.length() > 0) {
accessToken = twitter
.getOAuthAccessToken(requestToken, pin);
} else {
accessToken = twitter.getOAuthAccessToken();
}
} catch (TwitterException e) {
if (401 == e.getStatusCode()) {
System.out.println("Unable to get the access token.");
} else {
e.printStackTrace();
}
}
}
storeAccessToken(accessToken);
Status status = twitter.updateStatus("Client installed");
System.out.println("Successfully updated the status to ["
+ status.getText() + "].");
System.exit(0);
}
private static void storeAccessToken(AccessToken accessToken) {
try {
FileOutputStream fileOutputStream = new FileOutputStream(
"token.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(
fileOutputStream);
objectOutputStream.writeObject(accessToken.getToken());
objectOutputStream.flush();
fileOutputStream = new FileOutputStream("tokenSecret.txt");
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(accessToken.getTokenSecret());
objectOutputStream.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
|
リスト 1 のコードを Twitter4JRegister.java というファイルに入力し、コンシューマー・キーとコンシューマー・シークレットのプレースホルダーを皆さんのキーとシークレットで置き換えたら、そのコードをコンパイルします。コンパイルされたコードを実行し、生成された URL をブラウザーのアドレス・バーに入力します。ログインには、先ほど作成した Twitter アカウントのユーザー名とパスワードを使います。PIN が生成されて表示されたら、その PIN をコンソールに入力します。
トークン・オブジェクトとトークン・シークレット・オブジェクトは、それぞれ token.txt、tokenSecret.txt という別のファイルにシリアライズされます。クライアントはこの 2 つのオブジェクトを使用し、今後のすべてのトランザクションでアカウントを認証します。この 2 つのファイルは、バックアップを取っておいてください。削除してしまうと、再度プログラムを実行して新しい URL を生成し、この 2 つのオブジェクトを作成しなければなりません。アカウントのユーザー名とパスワードを決してコードの中で使わないように注意してください。トークンとトークン・シークレットは、(データベースやレジストリなど) 任意の場所に永続化することができますが、この記事ではファイルにシリアライズする方法のみを示します。
これでユーザーがトークンを利用できるようになったので、クライアント・アプリケーションを作成してトークンを使ったテストを行い、Twitter アカウントの近況アップデートをすることができます。リスト 2 は、Twitter4JUpdate というクライアント・アプリケーションのコードを示しています。
リスト 2. Twitter4JUpdate.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;
public class Twitter4JUpdate {
public static void main(String args[]) throws Exception {
TwitterFactory factory = new TwitterFactory();
AccessToken accessToken = loadAccessToken();
Twitter twitter = factory.getOAuthAuthorizedInstance("consumer key",
"consumer secret", accessToken);
Status status = twitter.updateStatus("Client registered");
System.out.println("Successfully updated the status to ["
+ status.getText() + "].");
System.exit(0);
}
private static AccessToken loadAccessToken() {
String token = null;
String tokenSecret = null;
try {
FileInputStream fileInputStream = new FileInputStream("token.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(
fileInputStream);
token = (String) objectInputStream.readObject();
fileInputStream = new FileInputStream("tokenSecret.txt");
objectInputStream = new ObjectInputStream(fileInputStream);
tokenSecret = (String) objectInputStream.readObject();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new AccessToken(token, tokenSecret);
}
}
|
先ほどと同様、リスト 2 のコンシューマー・キーとコンシューマー・シークレットを皆さんのものに置き換えます。先ほど示したファイル以外のどこかにトークン・オブジェクトとトークン・シークレット・オブジェクトを永続化した場合には、その 2 つのオブジェクトを取得できるように loadAccessToken() メソッドを作成し直す必要があります。
Twitter4JUpdate.java をコンパイルします。Twitter アカウントの近況アップデートが適切に行われることを確認するためには、下記のコマンドを使用し、表示させたい近況アップデートを update に指定します。
java Twitter4JUpdate update |
入力した近況アップデートが適切に表示されるかどうかを twitter.com で確認します。
カスタムの Ant タスクを作成して Twitter アカウントの近況アップデートを行う
カスタムの Ant タスクを作成するには、org.apache.tools.ant.Task タスクを継承して execute() メソッドをオーバーライドするだけのことです (「参考文献」を参照)。ランタイム変数はすべて、適切な set メソッドと get メソッドを持つプライベートなクラス属性として定義されます。コマンドライン・パラメーターを使って Twitter アカウントの近況を設定する代わりに、ビルド・ファイルの中でストリング値を設定します。すると、Ant タスクはそのストリング値を使って近況アップデートを行います。
リスト 3 のコードを TweetTask.java というファイルに入力し、先ほどと同様にコンシューマー・キーとコンシューマー・シークレットを置き換えます。
リスト 3. TweetTask.java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import org.apache.tools.ant.Task;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;
public class TweetTask extends Task {
private String status;
public void execute() {
try {
TwitterFactory factory = new TwitterFactory();
AccessToken accessToken = loadAccessToken();
Twitter twitter = factory.getOAuthAuthorizedInstance(
"consumer key", "consumer secret", accessToken);
Status updatedStatus = twitter.updateStatus(status);
System.out.println("Updated status to: "
+ updatedStatus.getText());
} catch (TwitterException e) {
e.printStackTrace();
}
}
private AccessToken loadAccessToken() {
String token = null;
String tokenSecret = null;
try {
FileInputStream fileInputStream = new FileInputStream(
"accessToken.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(
fileInputStream);
token = (String) objectInputStream.readObject();
fileInputStream = new FileInputStream("accessTokenSecret.txt");
objectInputStream = new ObjectInputStream(fileInputStream);
tokenSecret = (String) objectInputStream.readObject();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new AccessToken(token, tokenSecret);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
|
リスト 3 ではリスト 2 の main() メソッドを Ant タスクの execute() メソッドにリファクタリングしていることに注意してください。またリスト 3 では loadAccessToken() メソッドをリファクタリングし、単純に static 修飾子を削除して loadAccessToken() メソッドをクラス・メソッドからインスタンス・メソッドに変更しています (先ほど示したファイル以外のどこかにトークン・オブジェクトとトークン・シークレット・オブジェクトを永続化した場合には、リスト 2 で使用したメソッドと同じメソッドを再利用します)。TweetTask.java をコンパイルします。
今度は Ant の build.xml ファイルを作成し (リスト 4)、カスタムの TweetTask タスクをテストします。
リスト 4. build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project default="default" basedir=".">
<taskdef name="tweet"
classname="TweetTask"
classpath="Twitter4J Jar file" />
<target name="default">
<tstamp>
<format property="build.completed"
pattern="HH:mm:ss z dd-MM-yyyy" />
</tstamp>
<tweet status="build completed at ${build.completed}" />
</target>
</project>
|
Twitter4J の Web サイトからダウンロードしたものと同じ JAR ファイルが、このカスタム・タスクのクラスパスに追加されていることに注意してください。classpath 属性の値を、ダウンロードしたファイルの名前で置き換えます。mypackage.customtasks などのパッケージの中に TweetTask.java ファイルを配置した場合には、そのパッケージ名を classname 属性に反映する必要があります。この記事で示した例に従ってトークン・オブジェクトとトークン・シークレット・オブジェクトをローカル・ファイルにシリアライズした場合には、token.txt ファイルと tokenSecret.txt ファイルは、この build.xml ファイルと同じディレクトリーの中に配置されている必要があります。そうでないとビルドが適切に完了しません。
Ant で build.xml ファイルを実行します。実行が終了したら、Twitter アカウントをチェックし、カスタム・タスクによって適切に近況アップデートが行われ、「build completed at [時刻 タイムゾーン 日付]」という内容が表示されることを確認します (図 2)。
図 2. ビルド完了の近況アップデートが Twitter に表示された様子
これで、プロジェクトの関係者全員が Twitter のツイートをフォローすることで、ビルド完了時に通知を受けられるようになりました。
この記事では、Twitter の OAuth メカニズムを使用して、クライアント Java プログラムから Twitter アカウントの近況アップデートを行う方法を説明しました。この手法により、オープンソース・プロジェクトのビルド・エンジニアはビルドのメーリング・リストの保守および更新作業から解放されます (こうした作業は彼らが行うべき作業ではありません)。プロジェクトに関心を持つ開発者、テスター、その他誰でも、Twitter アカウントを購読 (つまり「フォロー」) することで、ビルドが完了したときに瞬時に通知を受けることができます。万が一 twitter.com を利用できない場合、あるいはプロジェクトのアカウントがセキュリティー侵害を受けた場合には、代替手段として mail タスクを使用して、ビルド・ステータスをユーザーに知らせることができます。
Twitter はこの 4 年間で飛躍的にその利用が増大してきました。その結果 status.net、Jaiku、NotePub などのミニブログが生まれています。この記事で紹介した近況アップデートのタスクを拡張することで、それらのサービスを利用したり、Facebook でプロジェクトの近況アップデートを行ったりすることができるようになります。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Sample code for this article | j-tweettask.zip | 7KB | HTTP |
学ぶために
- Apache Ant は Java をビルドするためのデファクト標準ツールです。
- Ant タスクについてのマニュアルのセクションを調べてください。ここには独自のタスクを作成する方法についても説明されています。
- Twitter を使い始めてください。
- Twitter API Wiki を訪れ、Twitter をプログラムで使用する方法を調べてください。
- Twitter の OAuth クライアントで登録を行ってください。Twitter アカウントを開くと、アプリケーションを登録することができます。
- AOuth のサイトを訪れ、セキュアな承認のためのオープン・プロトコル、AOuth について学んでください。
- Twitter4J は Twitter API のための非公式の Java ライブラリーです。
- developerWorks の Java technology ゾーンには、Java プログラミングのあらゆる側面を網羅した記事が豊富に用意されています。
製品や技術を入手するために
- Twitter4J をダウンロードしてください。
議論するために
- My developerWorks コミュニティーに加わってください。開発者向けのブログ、フォーラム、グループ、ウィキなど利用しながら、他の developerWorks ユーザーとやり取りしてください。
