Spring Bootを使ったWebアプリケーションのテンプレートを社内OSSとして開発・メンテナンス

# 概要

筆者は、Java向けOSSであるSpring Bootを使ったWebアプリケーションのテンプレートプロジェクト（以下、「本テンプレート」と記します）を、日立ソリューションズ内のOSSとして2年半開発・メンテナンスしてきました。

本テンプレートを開発するにあたって、社内ニーズ・メンテナンスコストの低減・ノウハウの実装と展開を実現するためにさまざまなツールを利用し、実装を行いました。本記事では本テンプレートにて実装している内容と各種ツールの活用方法を記します。

# 動機

2年半前、筆者は全社に対してソフトウェア技術の知見の収集と伝達を行う部署に所属していました。特に、社内でもニーズが高かったJavaによるWebアプリケーションの開発について知見を収集・伝達を行うことが主な業務でした。
その業務を通して、社内からお話を伺っていると、以下のようなご意見・ご要望を頂くことが多くありました。

- Javaを使ったWebアプリケーションを開発したいが、数あるOSSのから何を選べばよいか分からない
- [The Twelve-Factor App](https://12factor.net/ja/)が設計・開発のベストプラクティスとよく言われているが、実際にどのように実装すれば分からない
- 自動テストをどのように書けばわからない
- etc

これらのご意見・ご要望に対応するために、実際に動作するWebアプリケーションを社内OSSとして公開・開発することを考え、実践してみることにしました。

# 主な技術要素

「Javaを使ったWebアプリケーション」と一言で言ってもさまざまな選択肢があります。個人的な趣向も多分に含まれていますが、以下のものを選定しました。

- Webフレームワークとして、[Spring Boot](https://spring.io/projects/spring-boot)
- データベースアクセスとして、[Spring Data JDBC](https://spring.io/projects/spring-data-jdbc)
    - SQL文を直接書きたいという要望が多かったため
- ビルドツールとして、[Gradle](https://gradle.org/)
- HTMLテンプレートエンジンとして、[Thymeleaf](https://www.thymeleaf.org/)
- CSSフレームワークとして、[BootStrap](https://getbootstrap.com/)

これらの選定の理由は以下の通りです。

- 社内における要望を随時ヒアリングし、それらの要望を満たすものを選択
- 社内外にて情報が極力多いもの

ただし、これらの技術要素は絶対的なものではなく、プロジェクトに併せて任意の技術要素を使ってくださいとご案内しています。例えば、CSSフレームワークとしてBootStrap以外のものを使いたいと言った場合は、適宜必要な修正箇所をご案内しています。

# 実装内容

上記の主たる技術要素を使って、本テンプレートを作成していきました。ここでは、本テンプレートを作成するにあたって工夫した点や注意した点を記します。

## Webアプリケーション本体

データベーステーブルに対して、CRUD（Create・Read・Update・Delete）処理を行うものを実装しています。[Ruby on Rails](https://rubyonrails.org/)になじみがある人に対しては、Scaffoldで作られるWebアプリケーションのSpring Boot版と表現すると想像つきやすいかもしれません。
非常に単純なWebアプリケーションですが、データベースへのアクセス方法とデータの取り扱い方法を学べるサンプルになると考え、実装しています。

また、単純にユーザ名とパスワードによる[Spring Security](https://spring.io/projects/spring-security)を使った認証・認可の機能を実装しています。

実装しているビジネスロジックは上記のように大変単純なものですが、The Twelve-Factor Appに沿った実装をしています。Spring Bootはとくに意識せずとも自然とThe Twelve-Factor Appに沿った実装ができるフレームワークですが、以下の点については追加で設定しました。

- III. 設定
    - データベースなどへの接続先を環境変数経由で設定するようにpropertiesファイルに設定例を記述しています。
- XI. ログ
    - 標準出力が基本ですが、ローカル開発では併せてファイル出力するように設定しています。標準出力ではログが後から見返せないことがあるためです。
    - デバッグ時に役立つように、発行するSQLやメソッドの引数・戻り値をログに出力するようにしています。

## CI/CD

弊社ではソースコード管理システムとして著名な[GitLab](https://about.gitlab.com/)を活用しています。そのため、[GitLab CI/CD](https://docs.gitlab.com/ee/ci/)を使ってCI/CDを動かすように設定しています。

CI/CDとしては以下のものを動かしています。

### 自動テスト・カバレッジ

自動テストを実装するのは、Webアプリケーションを実装することとは別の技術が必要となります。具体的には[JUnit 5](https://junit.org/junit5/)、[Mockito](https://site.mockito.org/)、[Hamcrest](https://github.com/hamcrest/JavaHamcrest)、[Spring Bootが提供するテスト支援機能](https://docs.spring.io/spring-boot/docs/2.6.1/reference/htmlsingle/#features.testing)などが挙げられます。これらの使い方を示すために自動テストも実装して公開しています。

また、カバレッジを[Jacoco](https://www.eclemma.org/jacoco/)で取得し、明確にテストが不足している部分がないことを数値として確認できるようにしています。

### ライセンス情報取得

最近のOSSはそれ自身が数多くのOSSで構成されています。そのため、無意識に意図しないライセンス配下にあるOSSを利用してしまう危険性があります。

そこで、Gradleのプラグインである[com.github.hierynomus.license-report](https://plugins.gradle.org/plugin/com.github.hierynomus.license-report)を利用して、利用しているOSSのライセンス情報を取得するようにしています。

### ライブラリの更新情報

数多くのOSSを使うことになります。それぞれのOSSについて最新バージョンを利用したいと思っていますが、日々それぞれのOSSの情報をチェックするのは手間です。

そこで、Gradleのプラグインである[com.github.ben-manes.versions](https://plugins.gradle.org/plugin/com.github.ben-manes.versions)を利用して各OSSのバージョン情報を取得しています。

Spring Bootのバージョンアップがおおむね1ヶ月に1回のペースで行われているため、そのタイミングに合わせて依存するライブラリの更新情報の確認を行っています。

### フォーマット

コーディング規約は細部まで突き詰めるとキリがありません。[CheckStyle](https://checkstyle.sourceforge.io/)などで都度チェックすることも考えたのですが、高々ソースコードのフォーマットにそこまで労力をかける必要もないと考えました。

そこで、[Google Java Style Guide](https://google.github.io/styleguide/javaguide.html)を基準に、[com.diffplug.gradle.spotless](https://plugins.gradle.org/plugin/com.diffplug.gradle.spotless)で自動修正可能なものだけをチェック・自動修正するようにしています。

### 各種ドキュメント生成

プロジェクト参加者に周知が必要な各種ドキュメントもGitLab CI/CDにて作成し、[GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/)の機能を使って公開しています。

ドキュメントは、クラスやメソッドの詳細情報を記したJavaDocや上記のライセンス情報の取得結果、ライブラリの更新情報、テスト結果やカバレッジ情報などです。また、以下に述べるFlywayと[SchemaSpy](https://schemaspy.org/)を使ってデータベースの定義情報もドキュメントとして生成するようにしています。

## データベースマイグレーション

[Flyway](https://flywaydb.org/)を使ったデータベースマイグレーションの仕組みを取り入れています。Flywayは[命名規則](https://flywaydb.org/documentation/concepts/migrations#naming)に沿わないと意図しない挙動を引き起こすことになるので、具体的な使い方を用意するようにしました。

## コンテナ化

[Jib](https://github.com/GoogleContainerTools/jib)を使ってJavaのアプリケーションのコンテナ化を実現しています。また、FAQとしてよく上がる、[イメージのCreation Timeが48年以上になっている](https://github.com/GoogleContainerTools/jib/blob/v3.1.4-gradle/docs/faq.md#why-is-my-image-created-48-years-ago)事象への対応も予め実施しています。

# ドキュメント

実装だけでなく、日本語で実装の詳細や利用しているツールの使い方を知るためにドキュメントを随時作成しています。

まずは本テンプレートのカスタマイズの方法についてドキュメントを作成しました。上記の技術要素やCI/CDの設定は絶対的なものではなく、要件に応じてカスタマイズできるように修正点を明記しています。

Spring Boot自身の使い方が不慣れな人のために、実装の詳細についてJavaDocとしてソースコード内に記述しています。

各種ツールについては、以下のものについて入門編のドキュメントを作成しました。

- Git
- Gradle
- Flyway
- SchemaSpy

さらにSpring Bootのバージョンアップ情報やJavaのバージョンアップ情報の作成、Spring Bootのバージョンアップ時の注意点などの文章を作成・社内公開も実施しています。

# 展開

GitLabのテンプレート機能を使って最新版の本テンプレートを利用できるようにしています。このため、ブラウザ上でプロジェクト名だけ入力すれば、本テンプレートのコピーが自分のリポジトリですぐ使えるようになります。

# メンテナンス

Spring Bootのバージョンアップに併せて本テンプレートもバージョンアップするようにしています。このタイミングで関連ライブラリやGradleのバージョンアップも行っています。

動作確認は、自動テストの実行と手動での打鍵の両面で取るようにしています。複雑な実装をしていないので、おおむね1～2営業日の時間でパッチレベルのバージョンアップ作業は完了します。

2.5から2.6へのバージョンアップと言った非互換性が含まれるバージョンアップ時については、もう少し時間をかけて各種ドキュメントやログを読み込み、バージョンアップ対応を行います。

# 評価

社内OSSとして公開し、事前に使用許諾なども必要としていないためどれぐらいの利用者がいるか正確には分かっていません。フィードバックや問合せを時折頂きますので、全く使われていないという状態ではないです。

また、新規でJavaを使ったWebアプリケーションを開発するプロジェクトに対しては、本テンプレートをご紹介して利用を促しています。

新規プロジェクトでない場合でも、「実装の参考にしている」「GitLabの使い方の参考にしている」と言った本テンプレートの一部を取り上げて活用しているというフィードバックも多くいただいています。

# まとめ

本記事では実際に動作するWebアプリケーションのテンプレートプロジェクトを作成・公開したことを記しました。結果として、複数プロジェクトで活用いただき全社におけるシステム開発の効率向上に寄与することができました。採用した技術やツール、考え方を参考にしていただければ幸いです。