Spring BootでREST APIを実装する

Spring BootでREST APIを実装するときのツールの組み合わせについて、2018年6月時点での個人的なベストプラクティスをまとめてみました。

#### 開発環境（IDE）

##### 選択肢

- [Eclipse](https://www.eclipse.org/) + [Spring Tool Suite (STS)](https://spring.io/tools/sts)
- [IntelliJ IDEA](https://www.jetbrains.com/idea/) 


→ IDEとしてはAndroidの公式開発環境に採用されていることもあり、今後はIntelliJ IDEAが普及していきそうだが、Spring開発サポート機能を利用するにはUltimate Editionが必要となる。ライセンスを購入するほどでもないプロジェクトではEclipseを使うのが良い。

##### 参考

- https://www.jetbrains.com/idea/features/editions_comparison_matrix.html

#### ビルドツール

##### 選択肢

* Gradle
* Maven

→ Groovyで柔軟に処理が書けるGradleが今後主流になっていきそう。とはいえ依存関係解決とビルドに使うのみであればMavenでも十分である。

##### 参考

* https://gradle.org/maven-vs-gradle/
* http://sassembla.github.io/Public/12:05:27%2018-03-20/12:05:27%2018-03-20.html

#### HTTP通信の制御（REST APIとJava APIの相互変換）

##### 選択肢

* spring-boot-starter-web：Spring MVC
* spring-boot-starter-jersey：JAX-RS

→ JAX-RSはJavaの標準仕様であり、運用レベルで使える実装ライブラリも充実してきているので、spring-boot-starter-jerseyを使うのが良い。

##### 参考

* https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-starter
* https://dzone.com/articles/lets-compare-jax-rs-vs-spring-for-rest-endpoints


#### アスペクト指向プログラミング（AOP）

##### 選択肢

* Spring AOP (XMLスキーマによる設定)
- Spring AOP (AspectJアノテーションによる設定)
- AspectJ

→ Spring AOPをAspectJアノテーションで設定するのが簡単で、設定もコードにまとめることができてことができる。ただし、Spring管理外のインスタンスにアスペクトを設定したい場合や、メソッド実行以外のタイミングに設定したい場合にはAspectJを使う必要がある。

##### 参考

* https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop
* https://www.eclipse.org/aspectj/

#### データベースアクセス

##### 選択肢

* spring-boot-starter-jdbc：JDBCをそのまま使う
* spring-boot-starter-data-jpa：JPAベースのO/Rマッパー

→ spring-boot-starter-data-jpaを使うと単純なデータベース操作はSQLなしで記述できるため便利である。

なお、各DBとの接続するには対応するコネクターを導入する必要がある。（例えばMySQLの場合はmysql-connector-javaを導入する。）

##### 参考

* http://javatechnology.net/spring/spring-boot-mysql-connect/

#### コネクションプール

##### 選択肢

- [HikariCP](https://github.com/brettwooldridge/HikariCP)
- [Tomcat JDBC Connection Pool](https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html)
- [Commons DBCP2](https://commons.apache.org/proper/commons-dbcp/)

→ パフォーマンスが優れていて、Spring Bootでも推奨されているHikariCPを使うのが良い。

#### トランザクション管理

##### 選択肢

* Spring Frameworkのトランザクション管理機能
* [Atomikos Transactions](http://www.atomikos.com/)
* [JOTM](http://jotm.ow2.org/xwiki/bin/view/Main/WebHome)

→ 単一のトランザクション対象リソース（DB、MQなど）に対してトランザクションを使う場合はSpring Frameworkのトランザクション管理機能で十分である。Springのリファレンスでは、複数のリソースにまたがってトランザクションを使いたい場合には、SpringとアプリケーションサーバーのJTA機能を組み合わせるか、Atomikosなどのトランザクションライブラリを使うかのどちらかとすると良いとのこと。

##### 参考

- https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction

#### コード生成ライブラリ

##### 選択肢

* [Lombok](https://projectlombok.org/)
* [AutoValue](https://github.com/google/auto/tree/master/value)

→ AutoValueは厳密にImmutable Value Classを作るためのライブラリとなっているが、Lombokでは一般的なクラスにアクセッサメソッドを追加するだけ、といった使い方もでき、使い道が多くて良い。ただし、コード生成機能を拡張したい場合はAutoValueのExtensionを実装するのが良い。（Lombokでは[ExtensionMethod](https://projectlombok.org/features/experimental/ExtensionMethod)が試験的にサポートされているが、正式版に取り込まれるかは不明である。）

##### 参考

* [Value Objects in Java with AutoValue and Lombok](https://richardleggett.com/blog/2017/01/14/value-objects-in-java-with-autovalue-and-lombok/)

#### 設定ファイルの読み込み

spring-boot-configuration-processorを使うと簡単に設定ファイルの読み込みができる。3つの設定ファイルの読み込み方法が提供されている。

* `@Value`を使ってメンバ変数に設定ファイルのあるキーに対応する値を設定する
* `Environment`インターフェースを使って設定ファイルの値を取得するコードを記述する
* `@ConfigurationProperties`を使ってBeanに設定ファイルの内容を設定する

→ 設定は階層構造を持つことが多いため、`@ConfigurationProperties`を使うのが簡単である。

##### 参考

* https://qiita.com/kazuki43zoo/items/0ce92fce6d6f3b7bf8eb
* https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html


#### ロギング

##### 選択肢

* [SLF4J](https://www.slf4j.org/) + [Logback](http://logback.qos.ch/)
* [Java Util Logging](https://docs.oracle.com/javase/8/docs/api//java/util/logging/package-summary.html)
* [Log4J2](https://logging.apache.org/log4j/2.x/)

→ 今後はSLF4J + Logbackが主流になっていきそう。他のロギングシステムを使っている場合でも[Bridging legacy APIs](https://www.slf4j.org/legacy.html)に紹介される方法でSLF4Jに集約できる。

##### 参考

* https://ishiis.net/2016/08/25/spring-boot-logger/
* https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html

#### テスト

特に問題がなければspring-boot-testを使うのが良い。[AssertJ](https://joel-costigliola.github.io/assertj/)（アサーション）、[Hamcrest](http://hamcrest.org/JavaHamcrest/)（マッチ操作）、[Mockito](http://mockito.org/)（モック）などテストに必要なライブラリは一通り揃っている。

##### 参考

* https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html