« Back to Home

SDKで身近になるAmazon Web Service

このエントリはJava Advent Calendar 2011 第4日目のエントリです。
« 第3日目のエントリ第5日目のエントリ »

今日はAWSについて書こうと思います。というのは、最近ノーリスクとかマッシュアップとかいって、従量コストで利用できるWebモジュールの需要が(私の中で)高まってるからなのですが・・・。

AWSと言えばEC2やS3が有名ですが、他にもいろいろなサービスが提供されています。今日はその中でもシンプルで、単体でも役立ちそうなサービスをJava用のSDKから使う方法について紹介します。

この全てのサービス名に"Simple"と付いているのは偶然です。これを基準に選んだわけではありません。本当です。

なお記載のコードを実行するためには、AWSのアカウント登録と各サービスの有効化が必要です。また一応、従量課金サービスですので使い方によって料金が発生することがあります。

AWS SDK for Java

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";

Amazon Simple Storage Service (S3)

まずはご存知S3から使ってみることにします。S3は、キーに紐づくオブジェクトを格納できるストレージで、かなり大きなオブジェクトも格納できるのが特徴です。今は5テラバイトまで格納できるようです。

Amazon S3

例として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の内容が出力されます。

Amazon SimpleDB

次はSimpleDBに挑戦してみましょう。SimpleDBは、複数の属性(カラムに当たります)を持つデータセット(レコード)を格納できるデータベースです。スキーマ定義は不要で、各データセットの属性を自由に設定できます。

Amazon 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にすれば、参照前に挿入した全てのデータセットを参照できるようになります。

Amazon Simple Email Service (SES)

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

AWSにはTomcat互換のアプリケーションコンテナ、Elastic Beanstalkというサービスもあります。そこから今回のS3・SimpleDB・SESを利用すれば、簡単にいろいろなWebサービスを構築できそうですね。

余談ですが、AWSで頻繁に使われる3文字略語はどうも苦手です。全然覚えられません・・・。