EclipseからAWSの機械学習サービスを使用する

# はじめに
Eclipse（ローカル環境）で開発しているJava（Spring Boot）アプリケーションからAWSの機械学習サービスを使うのに苦労したので備忘録として残しておきます。

AWSの機械学習サービスといっても色々ありますが、今回私が使用したのは[Amazon Comprehend](https://aws.amazon.com/jp/comprehend/)（自然言語処理サービス）です。[公式ドキュメント](https://docs.aws.amazon.com/comprehend/latest/dg/what-is.html)に従って設定すればよいのですが、簡単そうで意外とハマりました。

# 環境
以下、私の環境です。
- Windows 10
- Eclipse 2019
- Java 11
- Spring Boot 2.6.4

# AWS IAMの作成
まずはIAMを作成します。

認証情報タイプは「アクセスキー・プログラムによるアクセス」を選択します。
![1_プログラムによるアクセス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643541/1cc70c2a-1aaa-7241-f663-ddaea7e3b680.png)

今回はポリシーとして"ComprehendFullAccess"を選択します。
![2_ポリシー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643541/1d2ed166-b6a6-309e-73c3-0066367d5f82.png)

IAMの作成を完了すると最後に「アクセスキーID」と「シークレットアクセスキー」が表示されますので、CSVをダウンロードして手元に控えておきましょう。

# AWS SDKの導入
機械学習サービスに限らずですが、AWSをJavaアプリケーションから使うためのAPIとして[AWS SDK for Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html)が提供されています。その中でもEclipse専用のSDKがあるため、Eclipseマーケットプレースからインストールします。
<img width="500" alt="3_ツールキット.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643541/2fddb1a1-06f8-a48b-e9b2-6685c6f9f9c7.png">

インストール後、Eclipseを再起動してこちらのポップアップが出た場合、先ほど控えたアクセスキー（「アクセスキーID」と「シークレットアクセスキー」）を入力します。
<img width="300" alt="7_ポップアップ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643541/e45e9cfc-026d-5a52-f713-8382dd94cd9f.png">

ポップアップが出ない場合でも、[ウィンドウ] - [設定] - [AWSツールキット]から入力できます。
![8_AWSツールキット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643541/c0eef87d-4b4a-0e06-82e8-de91db4269b4.png)

プロファイル名はひとまず`default`のままで問題ありません。アクセスキーを入力し、[適用して閉じる]を押下すると、拡張子なしの証明書ファイル（`credentials`）が`C:\Users\<ユーザ名>\.aws`に自動的に作成されます。

証明書ファイルは以下のような内容になっています。

```:credentials
[default]
aws_access_key_id=<アクセスキーID>
aws_secret_access_key=<シークレットアクセスキー>
```

また、必要があればビルドツールもインストールしておきます。
- Mavenの場合：[https://maven.apache.org/](https://maven.apache.org/)
- Gradleの場合：[https://gradle.org/](https://gradle.org/)

# 環境変数の設定
次に下記3つの環境変数を設定します。
- `AWS_ACCESS_KEY_ID`：アクセスキーID
- `AWS_REGION`：今回は東京リージョンが利用可能なため`ap-northeast-1`を設定しますが、使用するサービスが対応しているリージョンに適宜変更してください。
- `AWS_SECRET_ACCESS_KEY`：シークレットアクセスキー
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643541/96c3f211-d48d-afb9-89af-7a335b122f90.png)

# サンプルコードを動かす
いよいよサンプルコードの動作確認です。今回は一例として、感情分析を行う[DetectSentiment.java](https://docs.aws.amazon.com/code-samples/latest/catalog/javav2-comprehend-src-main-java-com-example-comprehend-DetectSentiment.java.html)をコピペして利用させていただきます。新規にSpringプロジェクト（ビルドツールはGradleを使用）を作成し、`DetectSentiment.java`を配置します。サンプルコード内のクラス名や`text`、`region`、`languageCode`を必要に応じて適宜変更します。

このままだと`import`文のところでエラーが出るため、[Setting up a Gradle project](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-gradle.html)を参考に`build.gradle`に下記を追記します。

```:build.gradle
dependencies {
    ...
    implementation platform('software.amazon.awssdk:bom:2.17.145')
    implementation 'software.amazon.awssdk:comprehend'
    ...
}
```

エラーが消えたので`DetectSentiment.java`を実行します！
が、Eclipseのコンソール上に下記のエラーが出力されました。

```
software.amazon.awssdk.core.exception.SdkClientException: Unable to load credentials from system settings. Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) or system property (aws.accessKeyId).
```

環境変数にセットした「アクセスキーID」と「シークレットアクセスキー」がうまく読み込めてないと思われます・・・。

改めて公式ドキュメント[Using credentials](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html)を確認したところ、[EnvironmentVariableCredentialsProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/EnvironmentVariableCredentialsProvider.html)クラスを使用しないとシステム環境変数が読み込めないようです。ということで`DetectSentiment.java`に下記を追記しました。

```java:DetectSentiment.java
import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider;  //追記
...
ComprehendClient comClient = ComprehendClient.builder()
        .region(region) 
        .credentialsProvider(EnvironmentVariableCredentialsProvider.create())  //追記
        .build();
...
```

`DetectSentiment.java`を再度実行！動きました！長いログがコンソールに出力されますが、下から13行目？くらいに`The Neutral value is 〇〇〇`と分析結果が見事に出力されました。

# 補足
[Amazon Comprehend Developer Guide](https://docs.aws.amazon.com/comprehend/latest/dg/get-started-api-sentiment.html)のサンプルコードだと`import com.amazonaws`の記述が見られます。一方、今回使用した[AWS Code Sample Catalog](https://docs.aws.amazon.com/code-samples/latest/catalog/javav2-comprehend-src-main-java-com-example-comprehend-DetectSentiment.java.html)では`import software.amazon.awssdk`になっています。この違いはAWS SDK for Javaのバージョン違いによるものです（[参考](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration-whats-different.html)）。

# 最後に
AWSの機械学習サービスをJavaアプリケーションで使うという題材の日本語記事が非常に少なく、必然的に英語の公式ドキュメントで調べることになりました。振り返ってみると特別難しいことはしてないのですが、思ったより大変な道のりでした・・・。

また、EclipseからAmazon Comprehendを使用するときの設定について説明しましたが、その他のAWS機械学習サービスを使用する際にも共通的に使える部分が多いのではないかと思います。今後、JavaからAWS機械学習サービスを使うのに挑戦する方の一助になれば幸いです。