このエントリはJava Advent Calendar 2011 第4日目のエントリです。
« 第3日目のエントリ・第5日目のエントリ »
今日はAWSについて書こうと思います。というのは、最近ノーリスクとかマッシュアップとかいって、従量コストで利用できるWebモジュールの需要が(私の中で)高まってるからなのですが・・・。
AWSと言えばEC2やS3が有名ですが、他にもいろいろなサービスが提供されています。今日はその中でもシンプルで、単体でも役立ちそうなサービスをJava用のSDKから使う方法について紹介します。
この全てのサービス名に"Simple"と付いているのは偶然です。これを基準に選んだわけではありません。本当です。
なお記載のコードを実行するためには、AWSのアカウント登録と各サービスの有効化が必要です。また一応、従量課金サービスですので使い方によって料金が発生することがあります。
AWSはRESTやSOAPで制御することができますが、SDKを通せばREST/SOAPのリクエスト・レスポンスの処理はSDKに任せて、Javaから手軽にサービスを利用できます。
SDKを使用するには、AWSのページからダウンロードしてクラスパスに含めるか、あるいはmavenを使うならpom.xmlに以下のdependencyを追加します。
<dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-java-sdk</artifactId> <version>1.2.12</version> </dependency>
それぞれのサービスを利用するために、認証が必要になります。AWSのアカウント画面からアクセスキーIDとシークレットアクセスキーを確認してください。これは共通で使いますので、以下のように定数として定義しておきます。
public static final String AWS_ACCESSKEY_ID = "1234567890ABCDEFGHIJ";
public static final String AWS_SECRET_ACCESSKEY
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
まずはご存知S3から使ってみることにします。S3は、キーに紐づくオブジェクトを格納できるストレージで、かなり大きなオブジェクトも格納できるのが特徴です。今は5テラバイトまで格納できるようです。

例としてXMLファイルを格納し、それをまた取り出してみましょう。バケット名はS3のサービス全体で一意でなければならないことに注意してください。
// 認証オブジェクト
AWSCredentials credential
= new BasicAWSCredentials(AWS_ACCESSKEY_ID, AWS_SECRET_ACCESSKEY);
// S3クライアントを作成
AmazonS3Client client = new AmazonS3Client(credential);
// S3でユニークなバケット名
String bucketName = "xxxxxxxx";
// バケットを作成
client.createBucket(bucketName);
// 格納
client.putObject(bucketName, "indian teas", new File("/path/to/indianTeas.xml"));
// 取り出し
S3Object s3Object = client.getObject(bucketName, "indian teas");
// 標準出力へ出力
InputStream is = s3Object.getObjectContent();
ReadableByteChannel from = Channels.newChannel(is);
WritableByteChannel to = Channels.newChannel(System.out);
try {
ByteBuffer buf = ByteBuffer.allocate(0x1000);
while (from.read(buf) != -1) {
buf.flip();
while (buf.hasRemaining()) {
to.write(buf);
}
buf.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
// 削除
client.deleteObject(bucketName, "indian teas");
// バケットを削除
client.deleteBucket(bucketName);
client.shutdown();
このコードを実行すると、わらわらとAmazonHttpClientのログが出力された後、取り出したXMLの内容が出力されます。
次はSimpleDBに挑戦してみましょう。SimpleDBは、複数の属性(カラムに当たります)を持つデータセット(レコード)を格納できるデータベースです。スキーマ定義は不要で、各データセットの属性を自由に設定できます。

以下のコードは簡単なデータ操作を行うものです。
// 認証オブジェクト
AWSCredentials credential
= new BasicAWSCredentials(AWS_ACCESSKEY_ID, AWS_SECRET_ACCESSKEY);
// SimpleDBクライアントを作成
AmazonSimpleDBClient client = new AmazonSimpleDBClient(credential);
// DBドメイン名
String domain = "testDomain";
// ドメインの作成
client.createDomain(new CreateDomainRequest(domain));
// 属性の異なるデータセットを挿入
client.putAttributes(new PutAttributesRequest()
.withDomainName(domain)
.withItemName("Darjeeling")
.withAttributes(
new ReplaceableAttribute("country", "India", Boolean.FALSE),
new ReplaceableAttribute("area", "north-east", Boolean.FALSE)));
client.putAttributes(new PutAttributesRequest()
.withDomainName(domain)
.withItemName("Uva")
.withAttributes(
new ReplaceableAttribute("country", "Sri Lanka", Boolean.FALSE),
new ReplaceableAttribute("island", "Ceylon", Boolean.FALSE),
new ReplaceableAttribute("area", "south-east", Boolean.FALSE)));
// 参照(非SQL)
SelectResult result = client.select(new SelectRequest("select * from testDomain"));
// データセットを表示
List<Item> items = result.getItems();
for (Item item : items) {
System.out.printf("%s:", item.getName());
for (Attribute attr : item.getAttributes()) {
System.out.printf(" %s=%s,", attr.getName(), attr.getValue());
}
System.out.println();
}
// DBドメインを削除
client.deleteDomain(new DeleteDomainRequest(domain));
client.shutdown();
参照するときの非SQLというのが気になりますね。これはSQLを簡略化したような構文で参照条件を記述するものなのですが、詳しくはAWSのドキュメントをご覧ください。"Amazon SimpleDB Quick Reference Card"で検索すればチートシートが見つかると思います。
さて上記のコードを実行すると、運が良ければ以下の出力が得られます。(ログは除いています)
Darjeeling: area=north-east, country=India, Uva: area=south-east, country=Sri Lanka, island=Ceylon,
たまに入れたものが全部出てこないこともあります。これはconsistency、いわゆる読み取り一貫性がオプション扱いになっているからです。SelectRequestオブジェクトのconsistentReadをtrueにすれば、参照前に挿入した全てのデータセットを参照できるようになります。
SESを使うと簡単にメールを送信できます。これには1つ準備が必要になります。AWS管理コンソールのSES画面から、送信者のメールアドレス認証を行っておいてください。同じ画面にProduction Accessの申し込みボタンがありますが、テストだけならそちらの方は必要ありません。
認証を済ませたら、早速送信してみましょう。送信者と受信者には認証したメールアドレスを設定します。
// 認証オブジェクト
AWSCredentials credential
= new BasicAWSCredentials(AWS_ACCESSKEY_ID, AWS_SECRET_ACCESSKEY);
// SESクライアントを作成
AmazonSimpleEmailServiceClient client
= new AmazonSimpleEmailServiceClient(credential);
// 管理コンソールで認証済みのアドレス
String verifiedAddress = "mail@example.com";
// メール送信
client.sendEmail(new SendEmailRequest()
.withSource(verifiedAddress)
.withDestination(new Destination()
.withToAddresses(verifiedAddress))
.withMessage(new Message()
.withSubject(new Content("AWS Simple Email test"))
.withBody(new Body()
.withText(new Content("AWS SESのテストです。"))
.withHtml(new Content("<h1>AWS SES</h1><p>テストです。</p>")))));
client.shutdown();
これでしばらく待つと、メールが届くはずです。
AWSにはTomcat互換のアプリケーションコンテナ、Elastic Beanstalkというサービスもあります。そこから今回のS3・SimpleDB・SESを利用すれば、簡単にいろいろなWebサービスを構築できそうですね。
余談ですが、AWSで頻繁に使われる3文字略語はどうも苦手です。全然覚えられません・・・。