このエントリは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文字略語はどうも苦手です。全然覚えられません・・・。