Spring Data DynamoDBを用いたアプリケーション(1)

【連載】

AWSで作るクラウドネイティブアプリケーションの基本

【第17回】Spring Data DynamoDBを用いたアプリケーション(1)

[2019/07/03 08:00]川畑 光平 ブックマーク ブックマーク

クラウド

前回は、AP型データベースである「Amazon DynamoDB」の概要を説明した上で、テーブルを構築しました。また、アプリケーションからアクセスするためのユーザーを作成するところまでご説明したかと思います。続く今回は、「Spring Data DynamoDB」を使ってデータベースアクセスするアプリケーションを実装してみます。

Spring Data DynamoDBの概要

Spring Data DynamoDBはSpring Dataのコミュニティプロジェクトで、Spring Data JPAなどと同様にデータベースアクセス処理を抽象化/簡易化し、CRUD操作などの処理実装を提供するフレームワークです。主な特徴は、以下の通りです。

  • DynamoDBテーブルに対するCRUDメソッドの実装の提供
  • キーワードを元にしたクエリメソッドによる動的クエリの生成
  • アノテーションベースの簡易なスキーマ表現
  • ページネーション、カスタムデータアクセス/データ射影
  • Spring Data RestとのRESTサポート

今回はこのフレームワークを用いて、DynamoDBにアクセスするアプリケーションを実装してみましょう。

なお、実際に作成したアプリケーションはGitHub上にコミットしています。以降記載されているソースコードでは、import文など本質的でない記述を省略している部分がありますので、実行コードを作成する場合は、必要に応じて適宜GitHub上のソースコードも参照してください。

Spring Data DynamoDBを使うための設定

Spring Data DynamoDBを使用するには、まず、Mavenプロジェクトのpom.xmlで、spring-data-dynamodbのライブラリを定義します。

ブラウザからDynamoDBへアクセスするアプリケーションを作成するには、Webアプリケーションを作るためのspring-boot-starter-web、thymeleafテンプレートエンジンを使用するためのspring-boot-starter-thymeleaf、DynamoDBテーブルのエンティティクラスの実装を簡易化するためのLombokライブラリの追加が必要です。

<dependencies>
  <dependency>
    <groupId>com.github.derjust</groupId>
    <artifactId>spring-data-dynamodb</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
</dependencies>

今回、アプリケーションは以下のコンポーネントで構成しますが、Spring Data DynamoDBで最低限作成しなければならない必須のクラスは以下の通りです。

なお、thymeleafテンプレートエンジンに関する説明は省略しますが、必要に応じて、Thymeleaf公式ドキュメントMacchinetta Frameworkテンプレートエンジンを参照してください。

コンポーネント 説明 必須
WebApp SpringBootアプリケーションを実行する起動クラス
MvcConfig Webアプリケーションの設定を行うクラス
DomainConfig サービスレイヤの設定を行うクラス
DynamoDBConfig DynamoDBへの接続に関する設定クラス
SampleModel 画面からのインプットパラメータを表すモデル
SampleController 画面からのリクエストを受け付け、Serviceを実行し、結果をテンプレートエンジンに渡す
SampleModelMapper SampleModelとMynaviSampleTableのパラメータをマッピングする
SampleService トランザクション境界となり、Repositoryを実行する
SampleRepository データベースアクセスを実行する
MynaviSampleTable DynamoDBのテーブルを表現するエンティティクラス

以降、各々のクラスについて解説を進めていきますが、事前にAWS公式ページにある「設定ファイルと認証情報ファイル」を参考に、ユーザーホームフォルダに.awsディレクトリを作成し、前回取得したCSV形式の認証キーに記載されているユーザー認証情報を保存してください。ファイル名は「credential」、形式は以下の通りです。

[default]
aws_access_key_id=XXXXXXXXXXXXXXXX
aws_secret_access_key=YYYYYYYYYYYYYYYYYYYYYYYYYYYYY

それでは、実装していくクラスについて説明します。

まず最初が、SpringBoot起動クラスと、各種の設定クラスです。@SpringBootApplicaitonアノテーションが付与された起動クラスは、同一パッケージにある@Configurationアノテーションが付与された設定クラス及び、設定クラス内で@ComponentScanされたパッケージにあるクラスを読み取ります。今回は目的に応じて以下の3つに分類して設定クラスを作成します。

  • MvcConfig:SpringMVCの設定クラスであるWebMvcConfigurerを実装した設定クラス
  • DomainConfig:Serviceをコンポーネントスキャンで読み取る設定クラス
  • DynamoDBConfig:DynamoDBの接続を行う設定クラス

設定クラスは必ずしも複数である必要はなく、1つにまとめても動作上問題ありません。ただし、クラス名と役割を対応付けて作成しておいたほうが、後々混乱することなく、クラス名から設定内容を識別できるのでベターでしょう。

package org.debugroom.mynavi.sample.spring.data.dynamodb.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebApp {

    public static void main(String[] args) {
        SpringApplication.run(WebApp.class, args);
    }

}

同一パッケージに配置するMvcConfigクラスでは、HTMLやCSSなどの静的リソースのURLと実際のリソースの物理配置の対応付けの定義をResourceHandlerRegistryに追加しておきます。また、Controllerクラスを読み取るために、ComponentScanアノテーションに該当のパッケージを指定しておきます。

package org.debugroom.mynavi.sample.spring.data.dynamodb.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@ComponentScan("org.debugroom.mynavi.sample.spring.data.dynamodb.app.web")
@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
          .addResourceLocations("classpath:/static/");
    }

}

また、DomainConfigクラスでは、Serviceなどビジネスロジックレイヤに属するコンポーネントがあるパッケージをスキャンする定義を追加しておきます。

package org.debugroom.mynavi.sample.spring.data.dynamodb.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan("org.debugroom.mynavi.sample.spring.data.dynamodb.domain")
@Configuration
public class DomainConfig {
}

続いて、DynamoDBへの接続で必須になる設定クラスがDynamoDBConfigクラスです。@EnableDynamoDBRepositoriesアノテーションを付与すると、DynamoDBの接続に必要なクラスがアプリケーション起動時に自動で構築されるようになります。@EnableDynamoDBRepositoriesには、同時にDynamoDBテーブルへアクセスするRepositoryクラスがあるベースパッケージを指定しなければなりません。

DynamoDB接続に必要なクラスはSpringBootが自動構築してくれますが、最低限、「接続先のDynamoDBのリージョン」「エンドポイント」「認証情報」の3つを設定する必要があります。

Spring Data DynamoDBも内部的には、DynamoDBとの接続にAWS SDKが提供しているcom.amazonaws.services.dynamodbv2.AmazonDynamoDBを利用しており、com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilderを使って、リージョンや認証情報を含めてインスタンスを作成するのが一般的です。そのため、設定クラス上でAmazonDynamoDBクラスの設定を行ってBean定義します。

なお、AmazonDynamoDBClientBuilderは、デフォルトで、事前に設定しておいた.aws内にあるCredentialの中にあるアクセスIDとシークレットキーを参照する実装になっています。古いWeb記事のサンプルなどでは、アプリケーション内で直接ClientBuilderにアクセスIDとシークレットキーを設定するコードをたまに見かけますが、AWSとしてこのやり方は推奨していないので、アプリケーションにキーを設定するコードを記述するのはやめておきましょう。

以下のコードでは、AwsClientBuilderのEndpointConfigrationに、東京リージョンとDynamoDBのサービスエンドポイントを設定ファイル「application.yml」から取得して、AmazonDynamoDBClientBuilderへ設定しています。

package org.debugroom.mynavi.sample.spring.data.dynamodb.config;

import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableDynamoDBRepositories(basePackages = "org.debugroom.mynavi.sample.spring.data.dynamodb.domain.repository")
public class DynamoDBConfig {

    @Value("${amazon.dynamodb.region}")
    private String region;
    @Value("${amazon.dynamodb.endpoint}")
    private String endpoint;

    @Bean
    public AmazonDynamoDB amazonDynamoDB(){
        return AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(
             new AwsClientBuilder.EndpointConfiguration(endpoint, region)).build();
    }

}

application.ymlの中身は以下のようになっています。

amazon:
  dynamodb:
    region: ap-northeast-1
    endpoint: https://dynamodb.ap-northeast-1.amazonaws.com

●AmazonDynamoDBClientBuilderについて

DynamoDBオブジェクトの生成に利用したAWS SDKのAmazonDynamoDBClientBuilderは、正確に言えば以下の順序で認証情報を取得していく実装になっています。

  1. 環境変数AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEY
  2. システムプロパティaws.accessKeyIdとaws.secretKey
  3. ユーザーのAWS認証情報ファイル
  4. AWSインスタンスプロファイルの認証情報

これまでの設定では、ローカル環境ではユーザーのAWS認証情報ファイルで取得する状態になっていますが、この実装のまま本番環境へ持って行っても、最後のAWSインスタンスプロファイルから認証情報を取得できます。

この辺りの挙動の詳細を知りたい方は、DefaultAWSCredentialsProviderChainの実装を参照してみてください。最後のインスタンスプロファイル情報はアプリケーションを実行するEC2インスタンス、もしくはECSコンテナが持つ認証情報で、インスタンスやコンテナを実行する際、IAMロールから権限を割り当てるオプションがあります。

開発環境/本番環境が変わるからといって、環境依存をなくすためにアプリケーション内でアクセスキーIDやシークレットキーを割り当てる実装は必要ありません。今回説明したように、開発環境(AWS内ではないローカル環境の場合)は.aws配下の認証情報を取得し、本番環境では、インスタンスのプロファイル上から認証情報を取得する実装を心掛けてください。

アプリケーションの設定に関する実装はここまでです。次回は、アプリケーションのDBアクセス処理などの実装を進めていきます。

著者紹介


川畑 光平(KAWABATA Kohei) - NTTデータ 課長代理

金融機関システム業務アプリケーション開発・システム基盤担当を経て、現在はソフトウェア開発自動化関連の研究開発・推進に従事。

Red Hat Certified Engineer、Pivotal Certified Spring Professional、AWS Certified Solutions Architect Professional等の資格を持ち、アプリケーション基盤・クラウドなどさまざまな開発プロジェクト支援にも携わる。2019 APN AWS Top Engineers & Ambassadors選出。

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

もっと知りたい!こちらもオススメ

【連載】対話システムをつくろう! Python超入門 [9] くじびき対話システムを作ろう(前編:繰り返し処理)

【連載】対話システムをつくろう! Python超入門 [9] くじびき対話システムを作ろう(前編:繰り返し処理)

前回、前々回では、日時を教えてくれる対話システムを作成しながら、変数と条件分岐について説明しました。この変数や条件分岐のように、プログラムの処理を構成する重要な要素の1つが「繰り返し処理」です。今回は、繰り返し処理を使ってくじびきをする対話システムを作成しましょう。

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で IT Search+ の人気記事をお届けします

会員登録(無料)

注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
[解説動画] 個人の業務効率化術 - 短時間集中はこうして作る
ミッションステートメント
教えてカナコさん! これならわかるAI入門
知りたい! カナコさん 皆で話そうAIのコト
対話システムをつくろう! Python超入門
Kubernetes入門
AWSで作るクラウドネイティブアプリケーションの基本
PowerShell Core入門
徹底研究! ハイブリッドクラウド
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

ページの先頭に戻る