AWS 1ヶ月導入記 part 5 AWS SDK for Javaを用いたプログラミング


目次

みなさん、こんにちは!フリューでモバイルサイト開発を行っている鷲見といいます。

現在、あるソーシャルプラットフォーム上のアプリケーションを構築するプロジェクトでの、クラウド環境の導入の進行状況をそのまま記事にしています。

もう実はプロジェクト自体は終了しているのですが、気にせずそのまま行きます。

前回はSimpleDBの制限の回避方法についてお話しました。

クラウド1ヶ月導入記 part 1 比較編

クラウド1ヶ月導入記 part 2 見積編

Amazon Web Services 1ヶ月導入記 part 1 データベース編

Amazon Web Services 1ヶ月導入記 part 2 アーキテクチャ設計編

Amazon Web Services 1ヶ月導入記 part 3 SimpleDBの特徴と制限

Amazon Web Services 1ヶ月導入記 part 4 SimpleDBの制限を回避する

今回はAWS SDK for Javaを使って、プログラムからSimpleDBへの接続を行うを方法を解説したいとおもいます。


AWS SDK for Javaとは?

AWS SDK for Javaとは、AWSが提供しているJavaのプログラムからAWSのAPIを簡単に呼び出すためのライブラリです。アカウントに関する設定を少し行うだけで本当に簡単にAPIを呼び出すことができます。

AWS SDKの対応言語

私たちは開発にJavaを利用するので、AWS SDK for Javaを利用していますが、その他の言語向けにも以下のようなSDKが提供されています。

  • AWS SDK for Java
  • AWS SDK for PHP
  • AWS SDK for .NET
  • AWS SDK for Ruby
  • AWS SDK for Android
  • AWS SDK for iOS

AWS SDK for Javaが対応しているAWSのサービス

現在AWS SDK for Javaから利用可能なAWSのサービスは以下のとおりです。

  • Amazon CloudWatch
  • Amazon ElastiCache
  • Amazon Elastic Compute Cloud
  • Amazon Elastic MapReduce
  • Amazon Relational Database Service
  • Amazon Simple Email Service
  • Amazon Simple Notification Service
  • Amazon Simple Queue Service
  • Amazon Simple Storage Service
  • Amazon SimpleDB
  • Amazon Virtual Private Cloud
  • Auto Scaling
  • AWS CloudFormation
  • AWS Elastic Beanstalk
  • AWS Import/Export
  • AWS Identity and Access Management
  • Elastic Load Balancing

上のサービスに先日追加されたばかりのElastiCacheが含まれていることからも分かることなのですが、AWSが提供しているライブラリなので、AWSに新しいサービスが提供されたり、既存のサービスに新しい機能が提供されたりして、APIに変更が加わった際には、リリースとほぼ同時にSDKもバージョンアップが行われているのも大きな特徴です。

AWS SDK for Javaの利用条件

AWS SDK for Javaを利用条件は以下のとおりです。

  • Java SDK 5.0以降を利用していること
  • Apache Commonsライブラリ(Codec, HTTP Client, Logging)が利用できること
  • 利用するAWSサービスのサインアップが完了していること

※上記は2011年9月15日現在の情報です。最新情報はAWSのホームページを参照してください。

AWS SDK for Java


サンプルプログラム

今回は東京リージョンで以下のようなドメインを作り、データを投入し、情報を取得するといったサンプルプログラムです。

Employee

アイテム名 name pref unit manager
Emp1 鷲見 京都 開発
企画
Emp2 九岡 福井 開発 佐藤
Emp3 川下 宮崎 企画 鈴木
import java.util.ArrayList;
import java.util.List;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.simpledb.AmazonSimpleDB;
import com.amazonaws.services.simpledb.AmazonSimpleDBClient;
import com.amazonaws.services.simpledb.model.Attribute;
import com.amazonaws.services.simpledb.model.BatchPutAttributesRequest;
import com.amazonaws.services.simpledb.model.CreateDomainRequest;
import com.amazonaws.services.simpledb.model.GetAttributesRequest;
import com.amazonaws.services.simpledb.model.GetAttributesResult;
import com.amazonaws.services.simpledb.model.Item;
import com.amazonaws.services.simpledb.model.ReplaceableAttribute;
import com.amazonaws.services.simpledb.model.ReplaceableItem;
import com.amazonaws.services.simpledb.model.SelectRequest;

public class EmployeeTest {

    
    public static void main(String[] args) throws Exception {
        // アカウント情報の設定
        AmazonSimpleDB sdb = new AmazonSimpleDBClient(new PropertiesCredentials(
                EmployeeTest.class.getResourceAsStream("AwsCredentials.properties")));
        
        // リージョンの設定
        sdb.setEndpoint("sdb.ap-northeast-1.amazonaws.com");
        
        String domain="Employee";
        
        try {
            // CreateDomainAPIによるドメイン作成
            System.out.println("CreateDomain:" + domain);
            sdb.createDomain(new CreateDomainRequest(domain));

            List<ReplaceableItem> putData = new ArrayList<ReplaceableItem>();

            putData.add(new ReplaceableItem("Emp1").withAttributes(
                    new ReplaceableAttribute("name", "鷲見", true),
                    new ReplaceableAttribute("pref", "京都", true),
                    new ReplaceableAttribute("unit", "開発", true),
                    new ReplaceableAttribute("unit", "企画", true)));

            putData.add(new ReplaceableItem("Emp2").withAttributes(
                    new ReplaceableAttribute("name", "九岡", true),
                    new ReplaceableAttribute("pref", "福井", true),
                    new ReplaceableAttribute("unit", "開発", true),
                    new ReplaceableAttribute("manager", "佐藤", true)));

            putData.add(new ReplaceableItem("Emp3").withAttributes(
                    new ReplaceableAttribute("name", "川下", true),
                    new ReplaceableAttribute("pref", "宮崎", true),
                    new ReplaceableAttribute("unit", "企画", true),
                    new ReplaceableAttribute("manager", "鈴木", true)));
            
            // BatchPutAttributesAPIによるデータの投入
            System.out.println("BatchPut:" + domain);
            sdb.batchPutAttributes(new BatchPutAttributesRequest(domain, putData));
            
            // GetAttributesAPIによるデータの取得    
            GetAttributesRequest getAttributesRequest = new GetAttributesRequest(domain,"Emp1");
            GetAttributesResult getResult = sdb.getAttributes(getAttributesRequest);
            System.out.print("Get Attributes Emp1[");
            for(Attribute attribute : getResult.getAttributes()){
                System.out.print(attribute.getName());
                System.out.print(":" + attribute.getValue()+" ");
            }
            System.out.println("]");
            
            // SelectAPIによるデータの取得
            String selectExpression = "select * from `" + domain + "` where unit = '企画'";
            System.out.println("Select: " + selectExpression);
            SelectRequest selectRequest = new SelectRequest(selectExpression);
            for (Item item : sdb.select(selectRequest).getItems()) {
                System.out.print(item.getName()+"[");
                for (Attribute attribute : item.getAttributes()) {
                    System.out.print(attribute.getName());
                    System.out.print(":" + attribute.getValue()+" ");
                }
                System.out.println("]");
            }
        } catch (AmazonServiceException ase) {
            ase.printStackTrace();
        } catch (AmazonClientException ace) {
            ace.printStackTrace();
        }
    }
}

クライアントの生成とアカウントとリージョンの設定

// アカウント情報の設定
AmazonSimpleDB sdb = new AmazonSimpleDBClient(new PropertiesCredentials(
     EmployeeTest.class.getResourceAsStream("AwsCredentials.properties")));

AWS SDKではAmazonSimpleDBインターフェースを実装するクライアントを生成し、クライアントのメソッドを通じてAPIの操作を行います。クライアントの生成時にアカウントの情報を設定します。アカウント情報はAWSCredentials.propertiesからアカウントのAccess Key IDとSecret Access Keyの情報を読み込みます。

AWS Credentials.propertiesファイルの内容は以下のようになっています。

secretKey={アカウントのSecret Access Key}
accessKey={アカウントのAccess Key ID}

また、クライアントはデフォルトのままではus-eastリージョンに接続するようになっているので、東京リージョンに設定するようにリージョンの設定を行います。

// リージョンの設定
sdb.setEndpoint("sdb.ap-northeast-1.amazonaws.com");

ドメインの作成

sdb.createDomain(new CreateDomainRequest(domain));

AWS SDK for Javaではクライアントに準備されているメソッドに対し、各メソッドに応じたRequestを渡します。Requestにはドメイン情報やアイテム情報など操作対象の情報を設定します。

ドメインの作成ではCreateDomainRequestにドメイン名を設定し、createDomainメソッドに渡して実行しています。

BatchPutAttributes APIによるデータの投入

List<ReplaceableItem> putData = new ArrayList<ReplaceableItem>();

putData.add(new ReplaceableItem("Emp1").withAttributes(
        new ReplaceableAttribute("name", "鷲見", true),
        new ReplaceableAttribute("pref", "京都", true),
        new ReplaceableAttribute("unit", "開発", true),
        new ReplaceableAttribute("unit", "企画", true)));

putData.add(new ReplaceableItem("Emp2").withAttributes(
        new ReplaceableAttribute("name", "九岡", true),
        new ReplaceableAttribute("pref", "福井", true),
        new ReplaceableAttribute("unit", "開発", true),
        new ReplaceableAttribute("manager", "佐藤", true)));

putData.add(new ReplaceableItem("Emp3").withAttributes(
        new ReplaceableAttribute("name", "川下", true),
        new ReplaceableAttribute("pref", "宮崎", true),
        new ReplaceableAttribute("unit", "企画", true),
        new ReplaceableAttribute("manager", "鈴木", true)));
            
// BatchPutAttributesAPIによるデータの投入
System.out.println("BatchPut:" + domain);
sdb.batchPutAttributes(new BatchPutAttributesRequest(domain, putData));

データの投入・更新にはPutAttributes APIとBatchPutAttributes APIの二種類があります。複数のアイテムに対して操作を行う際にはBatchPutAttributes APIを利用します。

投入するアイテムはReplaceableItemとしてアイテム名を指定して生成し、属性はReplaceableAttributeとして生成したReplaceableItemに設定します。なお、同じ属性に複数の値を設定する場合は、同じ属性名のReplaceableAttributeを複数設定します。(下記Emp1のunitの例を確認してください)

BatchPutAttributesAPIの場合は生成したReplaceableItemをListにしてリクエストに渡し、batchPutAttributesメソッドに渡して実行します。

GetAttributes APIによるデータの取得

// GetAttributesAPIによるデータの取得   
GetAttributesRequest getAttributesRequest = new GetAttributesRequest(domain,"Emp1");
GetAttributesResult getResult = sdb.getAttributes(getAttributesRequest);
System.out.print("Get Attributes Emp1[");
for(Attribute attribute : getResult.getAttributes()){
     System.out.print(attribute.getName());
     System.out.print(":" + attribute.getValue()+" ");
}
System.out.println("]");

データの取得にはGetAttributes APIとSelect APIを利用します。

GetAttributes APIはドメイン名とアイテム名を指定して属性情報を取得します。

実行結果はAPIに応じた形のGetAttributesResultで返されます。GetAttributesResultには該当アイテムの属性情報であるAttributeのリストが設定されています。

Select APIによるデータの取得

// SelectAPIによるデータの取得
String selectExpression = "select * from `" + domain + "` where unit = '企画'";
System.out.println("Select: " + selectExpression);
SelectRequest selectRequest = new SelectRequest(selectExpression);
for (Item item : sdb.select(selectRequest).getItems()) {
     System.out.print(item.getName()+"[");
     for (Attribute attribute : item.getAttributes()) {
          System.out.print(attribute.getName());
          System.out.print(":" + attribute.getValue()+" ");
     }
     System.out.println("]");
}

Select APIはSelectのSQLに対応した表現を用いてデータを取得します。下記の例ではSQLそのままになっています。

指定できるSQLには制限はありますが、ほぼSQLそのままで実行することが可能です。

実行結果はAPIに応じた形のSelectResultで返されます。GetAttributesResultとは異なり、アイテムを複数取得することが出来るため、ResultにはItemを複数保持し、各Itemが属性情報であるAttributeのListを保持しています。

実行結果

実行結果は以下のようになります。

CreateDomain:Employee
BatchPut:Employee
Get Attributes Emp1[unit:企画 unit:開発 name:鷲見 pref:京都 ]
Select: select * from `Employee` where unit = '企画'
Emp1[unit:開発 unit:企画 name:鷲見 pref:京都 ]
Emp3[unit:企画 manager:鈴木 name:川下 pref:宮崎 ]

まとめ

今回はAWS SDK for Javaを用いてSimpleDBを操作するプログラムを解説しました。

AWS SDK for JavaでのSimpleDBプログラミングでは

  • AmazonSimpleDBを実装するクライアントを生成する
  • クライアントにアカウント情報・リージョン情報を設定する
  • クライアントに準備されているAPIのメソッドを実行する。
  • 各メソッドに沿ったRequest,Resultが準備されている

ということを確認しました。

AWS SDK for Javaを利用すれば簡単にSimpleDBを操作することが出来ることを確認していただけたと思います。

また、今回は触れませんでしたが、属性の削除、アイテムの削除、ドメインの削除、統計情報の取得などといったメソッドもAWS SDK for Javaには準備されています。

さて、次回はSimpleDBのデータとJavaオブジェクトのマッピングを行うことのできるO/Rマッパーである『SimpleJPA』について、サンプルプログラムを交えて解説したいと思います。