panda大学習帳外伝

勝利の方程式の解き方。

メインページ | panda大学習帳 | 第三倉庫(仮) | 用語集📒 | 本サイトについて | プライバシーポリシー


Play FrameworkやScalaやsbtのメモ書き。

Play FrameworkScalasbtについては情報が少ないので、ハマったところから順番にまとめてみました。

中には一般常識レベルのものもあるかもしれませんが、中の人があまりよくわかっていなかったところですので、その点についてはご容赦願います。🙇

なお、ある程度情報がまとまった部分については「panda大学習帳」に新規の記事を作った上で移転する可能性があります。

スポンサーリンク

Play Framework

バージョンについて

本節の記述はVersion 2.7を前提とした記述としています。

Version 2.6以降でAPIの仕様が比較的大幅に変更されているので、注意が必要です。

本編のメモ書き。

  1. routesファイルに定義していないURLをcontrollersパッケージのコードから参照しようとすると、「controllers.routesにコントローラクラスは見つかりません。」というエラーメッセージが表示されて、コンパイルができない。よって、routesファイルへの設定が必要。
  2. データベースに対するSQL文の発行はanormまたはSlickを使うと良い。ただ、Framework側ではSQL文のパラメータを置き換える程度の処理しかしないので、複雑なSQL文が必要になったとき(っていうか、そこそこ実用的なWebアプリケーションを作るときにはほぼ必要になります。)にはSlickだと厳しいかもしれないので、anormの方が無難かもです。
  3. where ~ in 句のin句にパラメータを設定する際にはSeq型のデータを指定する。
  4. Webアプリケーションの実行テストの際に「controllersパッケージのReverse<コントローラのクラス名>のvalueが見つからない」というエラーページが表示される場合にはroutesファイルへの設定が行われていないので、設定を確認する。
  5. テンプレートでif文を書くときに、”@if”の後ろにはスペースを入れないこと。また、波括弧は省略しないこと。
  6. エラーハンドラ以外のところでエラーを発生させ、かつ自前のエラーページを作成するとき等のためにステータスコードを取得するには、RequestHeaderクラスのstatusメソッドを実行すると取得できる。
  7. MessagesRequestHandlerやMessagesRequestはかなりの高確率でMessageRequestHandlerとかMessageRequestと書きがちですので、よくわからないエラーが発生したときには、最初に確認すべきところかも。
  8. 実行環境でアプリケーションを終了させたときに、RUNNING_PIDという名前のファイルが消去されないときがある。このファイルが削除されずに残っているとアプリケーションが起動出来ないので、起動できないときにはRUNNING_PIDという名前のファイルがないかどうか確認し、あった場合には削除すること。

Scala

  1. コンパイルの際に生成される中間ファイルのパスの文字列が長くなり、Windowsのパスの文字列長の制限に引っかかることがあるので、身に覚えのないコンパイルエラーが発生した場合には、プロジェクトのファイルの置き場をドライブ直下に変えるか、いったんLinuxがインストールされているPCにプロジェクトをまるごとコピーした上でコンパイルを行うこと。
  2. mainメソッドが引数としてとる変数argsはjarファイルの直後の引数が0番目である。
  3. Scalaには三項演算子がない。ないだけならまだしも、エディタにおける文法チェック時に一見原因がわかりにくいコンパイルエラーを発生させることがあるので、以下のようなif文で書くことを習慣づけること(以下の例のようにコードブロックを示す波括弧は省略できる場合がある)。
    val x = if (a > 0) 1 else -1
    

    以下のような感じにも書くことができる。

    println("x="+(if(y.equals("")){null}else{"'"+y+"'"}))
    
  4. Listに直接要素を追加するとListを作り直してしまうため、巨大なListを扱うの場合にはパフォーマンスが低下する懸念がある(JavaにおけるStringオブジェクトと似た感じの問題)。そこで、Listに繰り返し要素を追加する処理を行う場合には、ListBufferとして以下のように定義すると良い。emptyメソッドにはListに格納するオブジェクトのクラス名を指定する。
    val l = ListBuffer.empty[ExampleClass]
    
  5. キーと値の組み合わせでデータを格納する場合に、キーの順序にソートしてデータを格納することが必要になることがある。そのような場合にはListMapを使用するとキーの順序にソートしてデータを格納することができる。
  6. 英語の大文字小文字及び数字でランダムな文字列を作成するには以下のように記述すればよい(10文字の文字列を作成する場合)。以下の記述例では2行に分割しているが、(かなり横長にはなるものの)1行で書くこともできる。
    val s = new scala.util.Random(new java.security.SecureRandom).
         alphanumeric.take(10).mkString
    

    また、英語の大文字小文字のみでランダムな文字列を作成する場合にはちょっと工夫が必要で、以下のように記述する(10文字の文字列を作成する場合)。

    val s = new scala.util.Random(new java.security.SecureRandom).
         alphanumeric.filterNot(c => c >= '0' && c <= '9').take(10).
         mkString
    

    alphanumericメソッドはStreamインスタンスを返すが、StreamインスタンスでもfilterNotメソッドが利用可能であることに留意すること。

  7. テキストファイルからの読み込みの際にはscala.io.Sourceクラスを使うと簡単に読めます。また、java.nio.file.Filesを使うとファイルへの書き出しを簡単に行うことができます。
  8. Version 2.13.0以降のScalaを用いて並列コレクションへの変換を行うparメソッドが含まれているコードをコンパイルしようとすると、
    value par is not a member of List[String]
    

    のようなエラーが出力されてコンパイルに失敗することがある。そんなときには、以下の設定等を行う。

    1. build.sbtに以下の設定を追加する。
      libraryDependencies += "org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0"
      
    2. 並列コレクションを使用しているプログラムの先頭に以下のimport文を追加する。
      import scala.collection.parallel.CollectionConverters._
      
  9. 並列コレクションにseqメソッド(toSeqメソッドではないことに注意!!)を作用させると順次コレクションに変換できる。
  10. TupleのListBufferにTupleを追加するときに、
    val a = ListBuffer.empty[(Int,Int)]
    a += (3,7)
    

    と書いてしまうと、Scalaのコンパイラに「2個の引数を持つ+=演算子」と解釈されて、コンパイルエラーになってしまう。そんなときには以下のように書くと、コンパイラが「引数が1個→これはTupleに違いない」とよしなに解釈してくれる。

    val a = ListBuffer.empty[(Int,Int)]
    a += ((3,7))
    
  11. 1個以上の文字列を結合するときに、
    s1+","+s2+","+s3
    

    と書くよりも、以下のように書いた方が速く処理できるようです。

    Array(s1,s2,s3).mkString(",")
    


sbt

  1. sbt-1.3.0-RC1でPlay Frameworkのプロジェクトをコンパイルするとviews.htmlが見つからないといわれる。なお、sbt-1.2.8及び1.3.3ではビルドできる。
  2. sbt.bat自体はバッチプログラムなので、ビルド関連のコマンドを自動化する等の目的で別のバッチファイルからsbtを呼び出す場合には”call sbt <command>“のように記述すること。
  3. sbtでcompileを実行すると、
    [warn] there was one deprecation warning (since 2.13.0); re-run with -deprecation for details
    

    などと言われることがあります。そのようなときには、以下のうち少なくとも一方の設定を行う。

    1. build.sbtに以下の設定を追加する。
      scalacOptions ++= Seq("-deprecation", "-feature")
      
    2. sbtのプロンプトで、以下のコマンドを実行する。
      set scalacOptions in ThisBuild ++= Seq("-deprecation", "-feature")
      

      なお、上記のWarningは、String型以外の変数をString型と連結する場合に発生することが多いようです(※個人の感想です。このような場合はString型以外の方の変数をas[String]等でString型に変換すると、上記のWarningが発生しなくなります)。

その他、または複合的なやつ。

  1. DB Browser for SQLiteでデータの中身を確認しながらWebアプリケーションを実行していると、”SQLITE_BUSY”というエラーが発生することがある(データベースのデータをupdate文などで変更すると発生するようである)。そんなときには、DB Browser for SQLiteのメニューバーから「File」→「Close Database」と選択して変更を保存しつつデータベースの接続を終了すると、Webアプリケーション側のエラーが解消される。
  2. セッションに保持されているデータは、sbtによるビルドを実行すると破棄されてしまうようなので、セッションのデータがなくても実行できる状態(例:ログイン前)からやり直すこと。
  3. ScalaのプロジェクトのディレクトリをEmacsのミニバッファからタイプするのは少々面倒なので、Emacsの設定ファイル(init.el等)に以下の設定を追加する(“your scala directory”の部分は適当に置き換えること。)と、F9キーを押すとneotreeのバッファが起動された際に設定したディレクトリを表示させることができるようになる。
    (global-set-key [f9] 'open-scala-workspace)
    (defun open-scala-workspace ()
      "Open scala workspace"
      (interactive)
      (neo-global--open-dir "your scala directory")
      (neo-global--select-window))
    
  4. ネットに接続されていないPCにPlay frameworkの実行環境をインストールすると起動に時間がかかるかもしれないので、play.http.secret.keyはapplication.confなどの設定ファイルに設定すること。play.http.secret.keyキーに設定される文字列は適当な文字列で良いが、あまり長さの短いものを設定すると「キーの文字列長が短過ぎる。」と怒られるので、Linuxで以下のコマンドを実行するなどして長めのものを設定する。
    $ head -c 32 /dev/urandom | base64
    NUWoceVNSiwbPA1+PgY8GT0yGhEBk41oKP3dKedkQKI=
    

スポンサーリンク

リンク

Play Frameworkを使って作ったWebアプリケーションのプロジェクトをSubversionのリポジトリにimportしてみた。 | panda大学習帳のScalaのカテゴリ | メインページ | panda大学習帳 | 第三倉庫(仮) | 用語集📒 | 本サイトについて | プライバシーポリシー


スポンサーリンク