【Java】【Play Framework】Gradleでプロジェクトを起動するまで

数年ぶりに[Play Framework](https://www.playframework.com/)を触ろうとしたら変化があったことと、Gradleを使いたいと思ったので、Gradleを使ったプロジェクトの起動までを忘備録として残しておきます。
Play Frameworkは、JavaまたはScalaを使った開発ができるフルスタックのWebアプリケーションフレームワークです。
今回は比較的入りやすい、Javaでのプロジェクトを想定して書いています。

# この記事での目標
- Play Frameworkを使うのに必要なツールをインストールする
- Gradleを使ってPlay Frameworkの開発用サーバーを起動する

# 環境
- macOS Catalina 10.15.2
- HomeBrew

# 概要
1. [必要なツールをインストールする](#必要なツールをインストールする)
  1. [Java](#java)
  1. [sbt](#sbt)
  1. [Gradle](#gradle)
1. [プロジェクトを作成する](#プロジェクトを作成する)
  1. [テンプレートプロジェクトの作成](#テンプレートプロジェクトの作成)
  1. [任意のディレクトリにプロジェクトをダウンロードしたい時は](#任意のディレクトリにプロジェクトをダウンロードしたい時は)
1. [Gradleを使用したPlay Frameworkプロジェクトの起動](#gradleを使用したplay-frameworkプロジェクトの起動)
 1. [build.gradleの設定](#buildgradleの設定)
 1. [1.3. Applying the plugin](#13-applying-the-plugin)
 1. [3.1. Adding dependencies](#31-adding-dependencies)
 1. [4.1. Targeting a Play version](#41-targeting-a-play-version)
 1. [4.2. Configuring routes style](#42-configuring-routes-style)
 1. [開発用サーバーで起動する](#開発用サーバーで起動する)

# 必要なツールをインストールする
## Java
公式の必要環境の情報([https://www.playframework.com/documentation/2.8.x/Requirements]())を確認すると、`Java SE 1.8 or higher`と表記されているので、Javaの最新版をインストールします。

~~~
brew cask install java
~~~

## [sbt](https://www.scala-sbt.org/)
Java、またはScalaを使用したアプリケーション作成に使用するビルドツールです。
公式の必要環境の情報([https://www.playframework.com/documentation/2.8.x/Requirements]())に`sbt`の記述がありますので、これもインストールします。

~~~
brew install sbt
~~~

## [Gradle](https://gradle.org)
主にJava、Scalaをターゲットにしたビルド自動化システムで、プラグインを使うことで色々なフレームワークやJVM言語への対応ができます。公式のプラグイン情報([https://plugins.gradle.org/]())を見ると、kotlinやSpring bootのなどのプラグインがあります。 
Play Frameworkに関しては、Gradle 5までは本体側に対応があったようですが、Gradle 6からはプラグインでの対応に変更されています。（[https://docs.gradle.org/current/userguide/play_plugin.html]()）

~~~
brew install gradle
~~~

# プロジェクトを作成する
この作業を始める前に、[Gradle Play Pluginの公式](https://gradle.github.io/playframework/)を確認しましょう。サポートするPlay Frameworkのバージョンが記載されています。
実は、現時点（※2019/12）ではPlay Frameworkの2.6系までしかサポートされていません。
ということで、今回は2.6系の最終バージョンである`2.6.25`での作成を目指します。  

## テンプレートプロジェクトの作成
[Play Framework公式の新規プロジェクト作成の解説](https://www.playframework.com/documentation/2.6.x/NewApplication)を確認すると、`Java template`と`Scala template`の2種類の記載があります。
今回はJavaでの開発を目指すため、`Java template`の方を使います。
……が、記載されたコマンドをそのまま実行すると、[Github上のテンプレートプロジェクト](https://github.com/playframework/play-java-seed.g8)から最新のテンプレートをダウンロードして作成してしまいます。
今回は最新（2019/12時点では`2.8.0`）ではなく`2.6.25`で作成するため、ブランチを指定する必要があります。
ブランチを指定する方法を探し回ると、sbtの公式で`--branch`パラメータについて触れているページがありました。  
[sbt - Giter8 parameters](https://www.scala-sbt.org/1.x/docs/sbt-new-and-Templates.html#Giter8+parameters)  
ターミナルで任意のディレクトリへ移動して以下のコマンドを実行します。

~~~
sbt new playframework/play-java-seed.g8 --branch 2.6.x
~~~

しばらくすると、ターミナル上で以下の項目を順番に聞かれます。

~~~
name [play-java-seed]:
organization [com.example]:
~~~

この2つは入力せずにそのままenterで飛ばして構いません。  
処理終了まで待つと、ディレクトリ直下に`play-java-seed`の名前でディレクトリが作成され、その中にテンプレートプロジェクト一式がダウンロードされます。

## 任意のディレクトリにプロジェクトをダウンロードしたい時は
ここまでやるとこう思いませんか？
「このテンプレートプロジェクトを、別のプロジェクト名でダウンロードしたい」
そういう時は、`--name=[プロジェクト名]`オプションを使うことで好きなプロジェクト名で作成できます。
このオプションに関しては、`sbt new`コマンドが内部的に使用している[`Giter8`](http://www.foundweekends.org/giter8/ja/index.html)のヘルプに書かれています。  
[Giter8 - 使用方法](http://www.foundweekends.org/giter8/ja/usage.html#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95) 

以下のコマンドを実行すると、任意のディレクトリ直下に`play-sample`のプロジェクト名で`2.6.x`のテンプレートプロジェクトをダウンロードできます。

~~~
sbt new playframework/play-java-seed.g8 --branch 2.6.x --name=play-sample
~~~

# Gradleを使用したPlay Frameworkプロジェクトの起動
## build.gradleの設定
無事にプロジェクトを作成できたら、プロジェクトをIDEで開いてみましょう。
今回はIDEに関しての話は省略しますが、Android以外のJava開発でよく使われるのは`ecipse`か`IntelliJ IDEA`ですね。
プロジェクトを開いて確認すると、プロジェクトの直下に`build.gradle`というファイルがあります。
このファイルは、Gradleでプロジェクトをビルドするための設定ファイルです。
ダウンロードしてきた時点ではGradle 5ベースの設定になっていますので、これをGradle Play Pluginに対応するために修正していきます。
設定変更の参考にするのは、[Gradle Play Plugin公式](https://gradle.github.io/playframework/)の「1.3. Applying the plugin」、「3.1. Adding dependencies」、「4.1. Targeting a Play version」、「4.2. Configuring routes style」の4項目です。

## 1.3. Applying the plugin
Gradleに読み込むプラグインの設定です。
ダウンロードしてきた時点では、以下のような記述になっています。 
 
~~~build.gradle
plugins {
    id 'play'
    id 'idea'
}
~~~
`id: 'play'`となっている項目が、Gradle 5まで使われていたプラグインを読み込む設定です。
これを以下のようにして、Gradle Play Pluginを読み込む形に変更します。

~~~build.gradle
plugins {
    // id 'play'
    id 'org.gradle.playframework' version '0.9'
    id 'idea'
}
~~~

## 3.1. Adding dependencies
プロジェクトのビルド時に使用する依存ライブラリの設定です。
ダウンロードしてきた時点では、以下のような設定になっています。

~~~build.gradle
dependencies {
    play dependencyFor("com.typesafe.play:play-guice", scalaVersion, playVersion)
    play dependencyFor("com.typesafe.play:play-logback", scalaVersion, playVersion)
    play dependencyFor("com.typesafe.play:filters-helpers", scalaVersion, playVersion)
}
~~~

GradleでのPlay対応が無くなり、Gradle Play Pluginに移行したことで依存ライブラリの設定方法が変更されています。
Gradle Play Plugin公式の解説を参考にして、`2.6.25`に対応したライブラリを読み込むように変更します。

~~~build.gradle
dependencies {
//    play dependencyFor("com.typesafe.play:play-guice", scalaVersion, playVersion)
//    play dependencyFor("com.typesafe.play:play-logback", scalaVersion, playVersion)
//    play dependencyFor("com.typesafe.play:filters-helpers", scalaVersion, playVersion)
    implementation "commons-lang:commons-lang:2.6"
    implementation "com.typesafe.play:play-guice_2.12:2.6.25"
    implementation "ch.qos.logback:logback-classic:1.2.3"
    testImplementation "org.scalatestplus.play:scalatestplus-play_2.12:3.1.2"
}
~~~
今回は`2.6.25`で動かすため、`com.typesafe.play:play-guice`のライブラリバージョンを、Gradle Play Plugin公式で提示された`2.6.15`ではなく、`2.6.25`に変更しています。

## 4.1. Targeting a Play version
ビルド時にターゲットとするPlay Framework、Java, Scalaのバージョンの設定です。
ダウンロードしてきた時点では、以下のような設定になっています。

~~~build.gradle
def playVersion = "2.6.22"
def scalaVersion = System.getProperty("scala.binary.version", /* default = */ "2.12")

...

model {
    components {
        play {
            platform play: playVersion, scala: scalaVersion, java: '1.8'
            injectedRoutesGenerator = true

            sources {
                twirlTemplates {
                    defaultImports = TwirlImports.JAVA
                }
            }
        }
    }
}
~~~
Gradle Play Pluginに移行したことでフォーマットが変更されているので、Gradle Play Plugin公式の記載に従って変更します。
また、今回は使用するPlay Frameworkのバージョンを`2.6.25`としますので、playVersionの記述も変更します。

~~~build.gradle
def playVersion = "2.6.25"
def scalaVersion = System.getProperty("scala.binary.version", /* default = */ "2.12")

...

play {
    platform {
        playVersion=playVersion
        scalaVersion=scalaVersion
        javaVersion=JavaVersion.VERSION_13
    }
}
~~~
`javaVersion`パラメータの設定は、ビルドに使用するJavaのバージョンに合わせて変更します。  
2019/12時点では`brew cask install java`の実行時にバージョンを指定しなければ、Java 13がインストールされます。
ですので、バージョンの情報をGradleで定義された`JavaVersion.VERSION_13`で指定します。
他のバージョンの定義情報についてはGradle公式リファレンスの以下ページに記載されています。  
[JavaVersion (Gradle API 6.0.1)](https://docs.gradle.org/current/javadoc/org/gradle/api/JavaVersion.html)

## 4.2. Configuring routes style
Play FrameworkでURLとControllerを関連付けるのに使用するroutesの形式を`StaticRoutesGenerator`とするか、`InjectedRoutesGenerator`とするかの設定です。
Play Frameworkの`2.4`以降では`InjectedRoutesGenerator`がデフォルトの設定になりますので、以下のように設定を追加します。

~~~build.gradle
play {
    platform {
        playVersion=playVersion
        scalaVersion=scalaVersion
        javaVersion=JavaVersion.VERSION_13
    }
    injectedRoutesGenerator = true
}
~~~

## 開発用サーバーで起動する
ターミナルに戻って、以下のコマンドを実行します。

~~~
gradle runPlay
~~~
ビルドに成功し、開発用サーバーが起動すると、以下のような表示になります。

~~~
BUILD SUCCESSFUL in 1s
7 actionable tasks: 1 executed, 6 up-to-date

Waiting for changes to input files of tasks... (ctrl-d to exit)
<=============> 100% EXECUTING [1m 49s]
> IDLE
~~~
この表示になったら、[http://127.0.0.1:9000]()へブラウザでアクセスします。
こんな画面が表示されていれば、起動成功です。

![スクリーンショット 2019-12-16 18.25.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27600/b8b8379a-4cb9-bcad-582e-868c821022c5.png)