初めてのPlayFramework

ここでは、まっさらの状態からPlayFrameworkの最初の開発を始めるまでを目指す。まっさらと言っても、PCを買うところからではない。

PlayFrameworkとは?

PlayFrameworkScalaを使ってWebアプリを開発する際によく使われるオープンソースのWebアプリケーションフレームワークである。Ruby on Railsからの影響を強く受けている(私はRuby on Railsを触ったことがないのでよく分からない)。Scalaといえば必ず目にするLightbendプログラミング言語Scalaの作成者とAkkaの作成者によって設立した会社)のサポートを受けており、 ScalaでWebやるなら第一候補のFWだ。

準備するもの

まずは三種の神器を準備する。

一応先に話しておくと、IntelliJ IDEA Ultimate ライセンスを買ってScalaプラグインを追加すれば全て解決する(sbtはinstall必要だったかもしれない)。JDKもsbtも別途個別インストールもしているが(IntelliJのライセンスを買う前の名残で)Ultimateを買ってからはIntelliJ内で完結している。IntelliJの有料ライセンスを買う価値があるかって?日常的にJavaScalaで開発していて、あなたがvimmerでもemacs過激派でも、もしくはとりあえずこれさえあればなんでも解決しそうだが痒いところに全然手が届かないしプラグイン地獄になる無料で軽量なVSCode信者でない限りはIntelliJを使うべきだ。もし可能ならば有料版を買おう。たった年3万円払うだけで、自分がスーパーエンジニアになったと錯覚できる。いや、マジで。

JDK

ScalaJVM上で動くので開発にはJDKが必要だ。インストールしよう。Mac ユーザーならbrewとかでもインストールできた気がするが、IntelliJのライセンスを買わないならば、SDKMAN! を使うのがベターだと思う。OpenJDKのほとんどはこれでインストールできるし、sbtや他の色々なsdkもこれを使ってインストールできる。

SDKMAN!のインストール

https://sdkman.io/install

を見ればいい訳だが、一応やっていこう。私はずっと昔(と言っても1年くらい前だが)に環境構築してしまったので、Dockerで作成したUbuntu Container内でやる。Macユーザーもやることは同じ(はず)。

下記のコマンドを実行しよう。通常の環境なら一発で成功すると思うが、私がやった際はまっさらなUbuntu環境だったため、curl, unzip, zipがないと怒られた。

curl -s "https://get.sdkman.io" | bash
root@ed19b7e28c60:/home/admin# curl -s "https://get.sdkman.io" | bash

                                -+syyyyyyys:
                            `/yho:`       -yd.
                         `/yh/`             +m.
                       .oho.                 hy                          .`
                     .sh/`                   :N`                `-/o`  `+dyyo:.
                   .yh:`                     `M-          `-/osysoym  :hs` `-+sys:      hhyssssssssy+
                 .sh:`                       `N:          ms/-``  yy.yh-      -hy.    `.N-````````+N.
               `od/`                         `N-       -/oM-      ddd+`     `sd:     hNNm        -N:
              :do`                           .M.       dMMM-     `ms.      /d+`     `NMMs       `do
            .yy-                             :N`    ```mMMM.      -      -hy.       /MMM:       yh
          `+d+`           `:/oo/`       `-/osyh/ossssssdNMM`           .sh:         yMMN`      /m.
         -dh-           :ymNMMMMy  `-/shmNm-`:N/-.``   `.sN            /N-         `NMMy      .m/
       `oNs`          -hysosmMMMMydmNmds+-.:ohm           :             sd`        :MMM/      yy
      .hN+           /d:    -MMMmhs/-.`   .MMMh   .ss+-                 `yy`       sMMN`     :N.
     :mN/           `N/     `o/-`         :MMMo   +MMMN-         .`      `ds       mMMh      do
    /NN/            `N+....--:/+oooosooo+:sMMM:   hMMMM:        `my       .m+     -MMM+     :N.
   /NMo              -+ooooo+/:-....`...:+hNMN.  `NMMMd`        .MM/       -m:    oMMN.     hs
  -NMd`                                    :mm   -MMMm- .s/     -MMm.       /m-   mMMd     -N.
 `mMM/                                      .-   /MMh. -dMo     -MMMy        od. .MMMs..---yh
 +MMM.                                           sNo`.sNMM+     :MMMM/        sh`+MMMNmNm+++-
 mMMM-                                           /--ohmMMM+     :MMMMm.       `hyymmmdddo
 MMMMh.                  ````                  `-+yy/`yMMM/     :MMMMMy       -sm:.``..-:-.`
 dMMMMmo-.``````..-:/osyhddddho.           `+shdh+.   hMMM:     :MmMMMM/   ./yy/` `:sys+/+sh/
 .dMMMMMMmdddddmmNMMMNNNNNMMMMMs           sNdo-      dMMM-  `-/yd/MMMMm-:sy+.   :hs-      /N`
  `/ymNNNNNNNmmdys+/::----/dMMm:          +m-         mMMM+ohmo/.` sMMMMdo-    .om:       `sh
     `.-----+/.`       `.-+hh/`         `od.          NMMNmds/     `mmy:`     +mMy      `:yy.
           /moyso+//+ossso:.           .yy`          `dy+:`         ..       :MMMN+---/oys:
         /+m:  `.-:::-`               /d+                                    +MMMMMMMNh:`
        +MN/                        -yh.                                     `+hddhy+.
       /MM+                       .sh:
      :NMo                      -sh/
     -NMs                    `/yy:
    .NMy                  `:sh+.
   `mMm`               ./yds-
  `dMMMmyo:-.````.-:oymNy:`
  +NMMMMMMMMMMMMMMMMms:`
    -+shmNMMMNmdy+:`


                                                                 Now attempting installation...


Looking for a previous installation of SDKMAN...
Looking for unzip...
Looking for zip...
Looking for curl...
Looking for sed...
Installing SDKMAN scripts...
Create distribution directories...
Getting available candidates...
Prime the config file...
Download script archive...
######################################################################## 100.0%
Extract script archive...
Install scripts...
Set version to 5.9.1+575 ...
Attempt update of interactive bash profile on regular UNIX...
Added sdkman init snippet to /root/.bashrc
Attempt update of zsh profile...
Updated existing /root/.zshrc



All done!


Please open a new terminal, or run the following in the existing one:

    source "/root/.sdkman/bin/sdkman-init.sh"

Then issue the following command:

    sdk help

Enjoy!!!
root@ed19b7e28c60:/home/admin#

となる。次の指示指示通り

source "$HOME/.sdkman/bin/sdkman-init.sh"

を実行しよう。こんな感じだ。

root@ed19b7e28c60:/home/admin# source "$HOME/.sdkman/bin/sdkman-init.sh"
root@ed19b7e28c60:/home/admin#

最後version見て動作することを確認して完了だ。

root@ed19b7e28c60:/home/admin# sdk version

SDKMAN 5.9.1+575

JDKをインストールする

昔はJDKOracle一択だったが、今はOpenJDKがいっぱい有る。

root@ed19b7e28c60:/home/admin# sdk list java
================================================================================
Available Java Versions
================================================================================
 Vendor        | Use | Version      | Dist    | Status     | Identifier
--------------------------------------------------------------------------------
 AdoptOpenJDK  |     | 15.0.1.j9    | adpt    |            | 15.0.1.j9-adpt
               |     | 15.0.1.hs    | adpt    |            | 15.0.1.hs-adpt
               |     | 14.0.2.j9    | adpt    |            | 14.0.2.j9-adpt
               |     | 14.0.2.hs    | adpt    |            | 14.0.2.hs-adpt
               |     | 13.0.2.j9    | adpt    |            | 13.0.2.j9-adpt
               |     | 13.0.2.hs    | adpt    |            | 13.0.2.hs-adpt
               |     | 12.0.2.j9    | adpt    |            | 12.0.2.j9-adpt
               |     | 12.0.2.hs    | adpt    |            | 12.0.2.hs-adpt
               |     | 11.0.9.open  | adpt    |            | 11.0.9.open-adpt
               |     | 11.0.9.j9    | adpt    |            | 11.0.9.j9-adpt
               |     | 11.0.9.hs    | adpt    |            | 11.0.9.hs-adpt
               |     | 8.0.275.open | adpt    |            | 8.0.275.open-adpt
               |     | 8.0.275.j9   | adpt    |            | 8.0.275.j9-adpt
               |     | 8.0.275.hs   | adpt    |            | 8.0.275.hs-adpt
               |     | 8.0.272.hs   | adpt    |            | 8.0.272.hs-adpt
 Alibaba       |     | 11.0.8       | albba   |            | 11.0.8-albba
               |     | 8u272        | albba   |            | 8u272-albba
 Amazon        |     | 15.0.1       | amzn    |            | 15.0.1-amzn
               |     | 11.0.9       | amzn    |            | 11.0.9-amzn
               |     | 8.0.275      | amzn    |            | 8.0.275-amzn
 Azul Zulu     |     | 15.0.1       | zulu    |            | 15.0.1-zulu
               |     | 15.0.1.fx    | zulu    |            | 15.0.1.fx-zulu
               |     | 14.0.2       | zulu    |            | 14.0.2-zulu
               |     | 14.0.2.fx    | zulu    |            | 14.0.2.fx-zulu
               |     | 13.0.5       | zulu    |            | 13.0.5-zulu
               |     | 13.0.5.fx    | zulu    |            | 13.0.5.fx-zulu
               |     | 12.0.2       | zulu    |            | 12.0.2-zulu
               |     | 11.0.9       | zulu    |            | 11.0.9-zulu
               |     | 11.0.9.fx    | zulu    |            | 11.0.9.fx-zulu
               |     | 10.0.2       | zulu    |            | 10.0.2-zulu
               |     | 9.0.7        | zulu    |            | 9.0.7-zulu
               |     | 8.0.272      | zulu    |            | 8.0.272-zulu
               |     | 8.0.272.fx   | zulu    |            | 8.0.272.fx-zulu
               |     | 7.0.282      | zulu    |            | 7.0.282-zulu
               |     | 6.0.119      | zulu    |            | 6.0.119-zulu
 BellSoft      |     | 15.0.1.fx    | librca  |            | 15.0.1.fx-librca
               |     | 15.0.1       | librca  |            | 15.0.1-librca
               |     | 14.0.2.fx    | librca  |            | 14.0.2.fx-librca
               |     | 14.0.2       | librca  |            | 14.0.2-librca
               |     | 13.0.2.fx    | librca  |            | 13.0.2.fx-librca
               |     | 13.0.2       | librca  |            | 13.0.2-librca
               |     | 12.0.2       | librca  |            | 12.0.2-librca
               |     | 11.0.9.fx    | librca  |            | 11.0.9.fx-librca
               |     | 11.0.9       | librca  |            | 11.0.9-librca
               |     | 8.0.275.fx   | librca  |            | 8.0.275.fx-librca
               |     | 8.0.275      | librca  |            | 8.0.275-librca
               |     | 8.0.265.fx   | librca  |            | 8.0.265.fx-librca
 GraalVM       |     | 20.3.0.r11   | grl     |            | 20.3.0.r11-grl
               |     | 20.3.0.r8    | grl     |            | 20.3.0.r8-grl
               |     | 20.2.0.r11   | grl     |            | 20.2.0.r11-grl
               |     | 20.2.0.r8    | grl     |            | 20.2.0.r8-grl
               |     | 20.1.0.r11   | grl     |            | 20.1.0.r11-grl
               |     | 20.1.0.r8    | grl     |            | 20.1.0.r8-grl
               |     | 20.0.0.r11   | grl     |            | 20.0.0.r11-grl
               |     | 20.0.0.r8    | grl     |            | 20.0.0.r8-grl
               |     | 19.3.4.r11   | grl     |            | 19.3.4.r11-grl
               |     | 19.3.4.r8    | grl     |            | 19.3.4.r8-grl
               |     | 19.3.1.r11   | grl     |            | 19.3.1.r11-grl
               |     | 19.3.1.r8    | grl     |            | 19.3.1.r8-grl
 Java.net      |     | 16.ea.25     | open    |            | 16.ea.25-open
               |     | 16.ea.7.lm   | open    |            | 16.ea.7.lm-open
               |     | 16.ea.2.pma  | open    |            | 16.ea.2.pma-open
               |     | 15.0.1       | open    |            | 15.0.1-open
               |     | 14.0.2       | open    |            | 14.0.2-open
               |     | 13.0.2       | open    |            | 13.0.2-open
               |     | 12.0.2       | open    |            | 12.0.2-open
               |     | 11.0.2       | open    |            | 11.0.2-open
               |     | 10.0.2       | open    |            | 10.0.2-open
               |     | 9.0.4        | open    |            | 9.0.4-open
               |     | 8.0.265      | open    |            | 8.0.265-open
 Mandrel       |     | 20.2.0.0     | mandrel |            | 20.2.0.0-mandrel
 SAP           |     | 15.0.1       | sapmchn |            | 15.0.1-sapmchn
               |     | 14.0.2       | sapmchn |            | 14.0.2-sapmchn
               |     | 13.0.2       | sapmchn |            | 13.0.2-sapmchn
               |     | 12.0.2       | sapmchn |            | 12.0.2-sapmchn
               |     | 11.0.9       | sapmchn |            | 11.0.9-sapmchn
 TravaOpenJDK  |     | 11.0.9       | trava   |            | 11.0.9-trava
               |     | 8.0.232      | trava   |            | 8.0.232-trava
================================================================================
Use the Identifier for installation:

    $ sdk install java 11.0.3.hs-adpt
================================================================================
root@ed19b7e28c60:/home/admin#

基本的にどれ使っても大丈夫だとは思うが、sbtがAdoptOpenJDKのJDK8か11を推奨しているのでそれをインストールする。一番右は、上記一番右列のIdentifier。

sdk install java 11.0.9.hs-adpt

実行してみるとこんな感じ

root@ed19b7e28c60:/home/admin# sdk install java 11.0.9.hs-adpt

Downloading: java 11.0.9.hs-adpt

In progress...

######################################################################################################################################################### 100.0%######################################################################################################################################################### 100.0%

Repackaging Java 11.0.9.hs-adpt...

Done repackaging...

Installing: java 11.0.9.hs-adpt
Done installing!


Setting java 11.0.9.hs-adpt as default.
root@ed19b7e28c60:/home/admin#

java --version でバージョンを確認してみると、

root@ed19b7e28c60:/home/admin# java --version
openjdk 11.0.9.1 2020-11-04
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9.1+1)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9.1+1, mixed mode)
root@ed19b7e28c60:/home/admin#

と、こんな感じでjavaがセットされていることが分かる。

sbtのインストール

sbtのインストールもSDKMAN!から行える。

sdk install sbt

実行結果

root@ed19b7e28c60:/home/admin# sdk install sbt

Downloading: sbt 1.4.4

In progress...

######################################################################################################################################################### 100.0%######################################################################################################################################################### 100.0%

Installing: sbt 1.4.4
Done installing!


Setting sbt 1.4.4 as default.
root@ed19b7e28c60:/home/admin#

IntelliJをインストールする

IntelliJを直接ダウンロードするのもいいが、Toolbox Appを利用するのが管理的にも楽だろう。下記からダウンロードできる。

https://www.jetbrains.com/ja-jp/toolbox-app/

IntelliJは有償版を買うことを強く勧めるが、全く使ったことないのにいきなり有償版を使ってもありがたみが分からないだろうから、最初はCommunity版でいいだろう。Communitiy版もToolbox経由でインストールできる。

IntelliJのインストールが終わったら、Preferences > Plugins > MarketplaceでScalaプラグインを追加しておこう。

Community版はPlayFrameworkをサポートしてないが、Scalaが書けないわけではない。困るのはplay templateを書くときくらいで、それ以外の時は意外と問題なく使える。

PlayFrameworkのスターターアプリを作成する

sbtとjdkが準備できたら、PlayFrameworkを使って開発する準備はできた。sbt newを使って、なんと言っていいのか分からないが、スターターキットみたいなものが作成できる。

sbt new playframework/play-scala-seed.g8

ちなみに、PlayFrameworkを使ったサンプルシリーズは下記にたくさんある。

https://developer.lightbend.com/start/?group=play

実行してみる。

root@ed19b7e28c60:/home/admin# sbt new playframework/play-scala-seed.g8
copying runtime jar...
[info] [launcher] getting org.scala-sbt sbt 1.4.4  (this may take some time)...
downloading https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.12/scala-library-2.12.12.jar ...

初回は色々ダウンロードしてすごい長いので省略

This template generates a Play Scala project

name [play-scala-seed]: helloworld
organization [com.example]: dev.tchiba

最後のnameのところで、アプリ名を入力する。organizationは自分のドメイン。まあ、後でも変更できる。

そうすると、下記のようにファイルとディレクトリが出来上がる。

root@ed19b7e28c60:/home/admin# tree
.
|-- helloworld
|   |-- app
|   |   |-- controllers
|   |   |   `-- HomeController.scala
|   |   `-- views
|   |       |-- index.scala.html
|   |       `-- main.scala.html
|   |-- build.sbt
|   |-- conf
|   |   |-- application.conf
|   |   |-- logback.xml
|   |   |-- messages
|   |   `-- routes
|   |-- project
|   |   |-- build.properties
|   |   `-- plugins.sbt
|   |-- public
|   |   |-- images
|   |   |   `-- favicon.png
|   |   |-- javascripts
|   |   |   `-- main.js
|   |   `-- stylesheets
|   |       `-- main.css
|   `-- test
|       `-- controllers
|           `-- HomeControllerSpec.scala
|-- project
|   `-- target
`-- target
    |-- global-logging
    `-- task-temp-directory

17 directories, 14 files

ここまでできたら実行しよう。実行するには sbt run すればいい。

sbt run

....初回は必要なライブラリなどをdownloadしたりするので長々と色々出る。

--- (Running the application, auto-reloading is enabled) ---

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

あとは、http://localhost:9000 にアクセスすれば良い。

なんの面白みもないが、とりあえずできた。

IntelliJでプロジェクトを取り込む

Community版のIntelliJからはPlayFrameworkのプロジェクトを作れないので、上記のようにCLIから作成するしかない。なので、作成したものをIntelliJを起動した後に File > Open から開くのが良い。開くディレクトリは上で示したディレクトリ構造のhelloworldディレクトリである。

ちなみにIntelliJ IDEA Ultimateだと

いきなりいける。Scalaの蘭から選ぶだけで作れる。超簡単!

いつもチャチャっとやってる作業ですが、1からやると結構な文量になりますね。。