[Play Framework 2.7] Play Framework2.7(Scala)をステップ実行できるようにするまで。

# 環境構築法

色んなサイトで環境構築方法が記載されていますが、
今回は「ここを見ればPlay Frameworkをステップ実行できる。」
というところまでの環境構築法を記載していきます。

# 環境構築の前提

下記条件で環境構築で行います。
主にWindows上だけで環境構築を行います。

##### ホストOS

* Windows 10
* [ScalaIDE-4.7.0](http://scala-ide.org/)
  - EclipseをベースにしたScala用IDE 
  - Eclipseベースなだけあって非常に重い、使いにくい、出来れば使いたくない！
* [Chocolatey](https://chocolatey.org/)  
  - Windows用パッケージ管理ソフトで非常に便利

##### 筆者の能力

* 過去にPlay Framework 2.5以前を使った経験あり。
* Activatorを使っていたが、数年経った現在sbtに置き換わり完全浦島太郎状態。
  * [ActivatorはEOL(End Of Life)との事](https://qiita.com/TKR/items/9200ca19e14376b305b5)。

##### ここでは伝えない事

* Chocolateyのインストール方法 ... [こちらのサイト](https://qiita.com/konta220/items/95b40b4647a737cb51aa) が詳しく載せてくれています。
* Eclipseの使い方 ... Eclipseに対してPlayFrameworkアプリのインポートやデバッグ方法は伝えるが、Eclipseの使い方を伝える為のページではない。

# 以下環境構築方法

### 必須アプリのインストール

Chocolateyを使用して、下記アプリをインストールします。

* jdk8 (現在Ver 8.0.211) ... Java SE Development Kit 8(Javaアプリ開発時に必須のキット)
* sbt (現在Ver 1.2.8) ... Scalaのビルドツールでありパッケージ管理ソフト(間違ってたらごめんなさい。)

管理者モードのコマンドプロンプトから主にコマンドを実行していきます。

Windows上で `Winキー + R` でファイル名を指定して実行が出来ます。
ここで `cmd` と入力した後、 `Ctrl + Shift + Enter` を押下すると、**管理者モード** でコマンドプロンプトを立ち上げる事が出来ます。

その後下記コマンドを実行しましょう。

``` cmd:コマンドプロンプト(管理者モード)
Microsoft Windows [Version 10.0.18362.113]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Windows\system32> cinst -y sbt jdk8
```

これでインストールは完了ですが、jdk8でsbtを立ち上げる度に下記警告が出るようになります。
`Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256M; support was removed in 8.0`

その為、`C:\Program Files (x86)\sbt\conf\sbtconfig.txt` を書き換えましょう。

``` ruby:sbtconfig.txt
# Set the java args to high
-Xmx512M
# -XX:MaxPermSize=256m (この行をコメントアウト!!!!)
-XX:ReservedCodeCacheSize=128m

# Set the extra SBT options
-Dsbt.log.format=true
```


### Play Framework用のテンプレートの作成

コマンドプロンプトを再立ち上げ後、
`sbt new` コマンドを実行してplay frameworkのテンプレートを指定します。
※下記パスは一例です。任意のパスで問題ありません。

``` cmd:コマンドプロンプト
Microsoft Windows [Version 10.0.18362.113]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Windows\system32> cd c:\Users\User
C:\Users\User> mkdir scala
C:\Users\User> cd scala

C:\Users\User\scala> sbt new playframework/play-scala-seed.g8
[info] Set current project to scala (in build file:/C:/Users/User/scala/)
[info] Set current project to scala (in build file:/C:/Users/User/scala/)

This template generates a Play Scala project

name [play-scala-seed]: <何も入力せずEnter>
organization [com.example]: <何も入力せずEnter>
```

すると 場合によっては下記例外が出ると思いますが、[こちらによると](https://github.com/playframework/play-scala-seed.g8/issues/56) どうもみんな同じ問題に直面しているようですが、内容的に問題ないようです。

``` cmd:コマンドプロンプト
java.io.IOException: Unable to delete file: C:\Users\User\AppData\Local\Temp\giter8-xxxxxxx\src\main\g8\.gitignore
<<中略>>
[error] java.io.IOException: Unable to delete file: C:\Users\User\AppData\Local\Temp\giter8-5858236389700\src\main\g8\.gitignore
[error] Use 'last' for the full log.
```

**環境によっては `sbt new`コマンドで非常に時間がかかる可能性があります。**

以上でテンプレートの作成は終わりです。

### Play Frameworkの動作確認

コマンドプロンプトから `sbt run` コマンドを入力して、
作成したPlay Frameworkのアプリが動作するか確認しましょう。

``` cmd:コマンドプロンプト
Microsoft Windows [Version 10.0.18362.113]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Windows\system32> cd c:\Users\User\scala\play-scala-seed
c:\Users\User\scala\play-scala-seed> sbt run
```

`sbt run` がPlayサーバーの実行です。
コマンドの詳細は [先ほども載せたこちらのサイト](https://qiita.com/TKR/items/9200ca19e14376b305b5) が詳しくまとめて下さっています。
またこの `sbt run` コマンドは **初回実行時、必要なプラグインを自動でダウンロードします。**
これには **非常に時間がかかりますので、気長に待ちましょう。**

下記ログが表示されれば成功です。

``` cmd:コマンドプロンプト
--- (Running the application, auto-reloading is enabled) ---

[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Enter to stop and go back to the console...)
```

ブラウザから [http://localhost:9000](http://localhost:9000)にアクセスしてみて動作するか確認してみて下さい。
**※こちらも初回アクセス時、PC環境によっては非常に時間がかかります。**
「Welcome to Play!」と表示されれば成功です。
![play001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/e0d7bca9-fb94-3307-a714-8fbdc5dd6b79.png)

以上が動作確認です。
`CTRL + D` でサーバーを終了させましょう。

### Play Framework用のテンプレートの書き換え。

##### Eclipseのプロジェクトを作成するための準備をする。

Eclipseからプロジェクトをインポート出来るようにします。
まず play frameworkアプリ(play-scala-seed)のパス内に `play-scala-seed\project\plugins.sbt` を開け、 
`addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.2")` を追加します。

``` scala:play-scala-seed\project\plugins.sbt
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.2")
addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0")
// 下記行を追加
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.2")
```

##### Eclipse上で表示されるviews.htmlのエラーを非表示にする。

次に `play-scala-seed\build.sbt` に `EclipseKeys.preTasks := Seq(compile in Compile, compile in Test)` を加えます。

``` scala:play-scala-seed\build.sbt
EclipseKeys.preTasks := Seq(compile in Compile, compile in Test) // 追加
resolvers += "scalaz-bintray" at http://dl.bintray.com/scalaz/releases"
```

これを行うことで、将来的に
`object ***** is not a member of package views.html.*****.scala` というEclipse上で表示されるエラーを非表示にする事が出来ます。

詳細は下記サイトをご確認下さい。

* [stack overflow](https://stackoverflow.com/questions/38288891/play-framework-java-and-eclipse-luna
)
* [Play Framework公式](https://www.playframework.com/documentation/2.7.x/IDE)

##### Eclipseプロジェクトを作成する。

その後、下記コマンドを実行します。
[こちらのページ](https://www.playframework.com/documentation/2.7.x/IDE) に詳しく記載されています。

``` cmd:コマンドプロンプト
c:\Users\User\scala\play-scala-seed> sbt

[info] Loading settings for project play-scala-seed-build from plugins.sbt ...
<中略 多少時間がかかる。>

[play-scala-seed] $ eclipse with-source=true

<中略 結構時間がかかる。>
[info] Successfully created Eclipse project files for project(s):
[info] play-scala-seed

[play-scala-seed] $ exit
```

これでEclipseのプロジェクトが作成されました。

### ScalaIDEをセットアップする。

[こちらのサイト](http://scala-ide.org/) からダウンロードします。
ダウンロード完了後、解凍して、eclipse.exeを起動します。

初回起動時、下記パスが出ますが、そのままで問題ありません。

![play002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/ae954b6e-247e-db97-d113-2172af31e6c4.png)

Launchを押下しましょう。

起動が終わったら `File -> Import` を押下します。
![play003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/cb00cb72-fbbb-8bbc-972b-aeb7b5abc334.png)

その後、`General -> Existing Projects into Workspace` を選択後、ダイアログ下部の `Next` を押下します。
![play004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/4600c977-e247-3e63-72ed-92844835f34d.png)

その後、右上のBrowseから `c:\Users\User\scala\play-scala-seed` を選択し ダイアログ下部の `Finish` を押下しましょう。
![play005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/74d1a949-36f6-91b1-1cd0-699c8b7e1792.png)

以上でScalaIDEにProjectをインポートする事できました。

### Scala IDEでプロジェクトのデバッグ設定を行う。

画面上部の `Run -> Debug Configurations...` を選択します。
その後、`Remote Java Application` をダブルクリックし、
画面下部のように設定します。
![play006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/e661b8de-1d73-f5be-18a1-577d55e8e4ad.png)

次に `Revert` の左にある `Select one...` を押下し
`Use configuration specific settigs` にチェックを入れ、
`Scala Remote Launcher` を選択し、ダイアログ下部の `OK` を押下します。
![play007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/b90d77c4-098c-6380-9c33-05fbd5a8edd1.png)

その後、 `Apply` を押下します。

### ブレークポイントで処理を止めよう。

コマンドプロンプトから下記コマンドを入力します。
`sbt run -jvm-debug 9999`

``` cmd:コマンドプロンプト
C:\Users\User\scala\play-scala-seed> sbt run -jvm-debug 9999
```

すると下記ログが表示されます。

``` cmd:コマンドプロンプト
Listening for transport dt_socket at address: 9999
<中略>
(Server started, use Enter to stop and go back to the console...)
```

この状態で下記 ScalaIDEからブレークポイントを仕掛けます。

* **必ず`sbt run -jvm-debug 9999`コマンドを入力後、下記ScalaIDEの操作を行うように下さい。**

赤枠部分をダブルクリックするとブレークポイントを仕掛ける事が出来ます。
![play008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/f1e2efbf-e80d-a75b-1cf7-0aea45149b36.png)

次にデバッグを実行します。
画面上部の虫マークの下矢印マークを押下し、その中にある `play debug` を選択します。
![play009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/5a4cfb85-4859-25bc-a407-57f714cd5b9e.png)

この際にEclipseからエラーが表示された場合は何かしら間違っている可能性があります。

それではブレークポイントで処理が止まるか確認しましょう。
[http://localhost:9000](http://localhost:9000)にアクセスし、ScalaIDEで処理が止まるか確認します。

無事ブレークポイントで処理が止まれば成功です。

### エラーが発生した場合

#### Scala コードにブレークポイントを設定できない。
chocolateyからインストールしたEclipseだと何故かScalaコードに対してブレークポイントを設定できませんでした。
設定がおかしいのか、ScalaIDEプラグインのインストール失敗しているのか全く以て不明ですが、とりあえず無難にScalaIDEに関してはインターネット上からダウンロードした実行ファイルから動作させた方が無難です。

#### ScalaIDEからデバッグを開始すると下図エラーが出る。

![play010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/383232/26ad5567-4166-ad51-53ef-e6129c1d23d1.png)
このエラーのだいたいの問題点は下記4点のうちどちらかです。

* [ScalaIDEのデバッグ設定](https://qiita.com/takmt/items/4132e6ffee20fecf9ad5#scala-ide%E3%81%A7%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E8%A8%AD%E5%AE%9A%E3%82%92%E8%A1%8C%E3%81%86) が間違っている。
* [sbtコマンド](https://qiita.com/takmt/items/4132e6ffee20fecf9ad5#%E3%83%96%E3%83%AC%E3%83%BC%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%81%A7%E5%87%A6%E7%90%86%E3%82%92%E6%AD%A2%E3%82%81%E3%82%88%E3%81%86) が間違ってる。
* [sbtコマンド](https://qiita.com/takmt/items/4132e6ffee20fecf9ad5#%E3%83%96%E3%83%AC%E3%83%BC%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%81%A7%E5%87%A6%E7%90%86%E3%82%92%E6%AD%A2%E3%82%81%E3%82%88%E3%81%86)実行前にEclipseからデバッグをしようとした。
* Eclipseからデバッグを止めたはずなのに、デバッグポートが開きっぱなしになっている。<br>その場合Eclipseを再起動する。

特にsbtコマンドに関しては、

* 〇 ... `sbt run -jvm-debug 9999` **これが正しいコマンドです。**
* × ... `sbt -jvm-debug 9999 run` このように **順番を入れ替えると正しく動作しません。**

以上でステップ実行が出来るようになりました。
しかしながらまだEclipse上では気になる問題点が残っています。

### EclipseからScalaのコンパイルエラーを削除する。

Eclipse上からProblemsウィンドウを見るとErrorがいくつか残っていますが、下記手順を踏むことで消すことが可能です。
※Eclipse上での見栄えの問題なので気にならない人は無視してもらってよいです。

##### build path is cross-compiled with an incompatible version of Scala

[こちらのサイト](https://qiita.com/kunichiko/items/c0cd0b78e7fe26bc7c89) を参考に設定すると良いです。
主に下記設定を変更します。
`Window -> Preferences -> Scala -> Compiler -> Build manager[Tab] -> withVersionClasspathValidator` のチェックボックスを `OFF` にし、 `Apply and Close` で設定を適用します。

##### play cannot find any http request here

ActionのrequestをFormのbindFromRequestに設定する際に、
implicit で暗黙的に設定するようになっている場合、
型情報が宣言されていないと、Eclipse上でエラーとなります。
※ `sbt run` では問題なく動作する為、必要に感じない人は修正しなくてもよいです。

詳細は[こちらを参照](https://stackoverflow.com/questions/41090946/scala-play-2-5-form-bindfromrequest-cannot-find-any-http-request-here)して下さい。

その為、下記のようなコードがあった場合、

``` scala
def loginA = Action.async { implicit request => 
  Forms.form.bindFromRequest.fold( ...
```

下記のように型情報を加えるとEclipse上でのエラーが消えます。

``` scala
def loginA = Action.async { implicit request : Request[AnyContent] => 
  Forms.form.bindFromRequest.fold( ...
```



# 環境構築終了

以上が環境構築方法になります。

もし何かしら間違いや誤りなどありましたらご指摘お願いします。
またコメントやこうしたら良いよみたいなアドバイスがあればコメントいただけると嬉しいです。

# 参考URL

### アプリに関して

* [ScalaIDE](http://scala-ide.org/)
* [sbt](https://www.scala-sbt.org/1.x/docs/ja/index.html)

### Chocolateyに関して

* https://chocolatey.org/
* https://qiita.com/konta220/items/95b40b4647a737cb51aa

### Scala や sbtのコマンドに関して

* https://dwango.github.io/scala_text/sbt-install.html
* https://github.com/playframework/play-scala-seed.g8/issues/56
* https://kazuhira-r.hatenablog.com/entry/20140320/1395336057
* https://qiita.com/TKR/items/9200ca19e14376b305b5
* https://qiita.com/kunichiko/items/c0cd0b78e7fe26bc7c89
* https://stackoverflow.com/questions/38288891/play-framework-java-and-eclipse-luna

### Play Frameworkに関して

* https://www.playframework.com/documentation/2.7.x/Home
* https://www.playframework.com/documentation/2.7.x/IDE