play framework2 の起動(run)でポートを指定する方法と、失敗パターン

-Dオプションでポートを指定する

play -Dhttp.port=9001  run 

すると↓のログが出力されます。

[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0%0:9001

失敗するパターン

play  run -Dhttp.port=9001 

この方法だと失敗します。

[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0%0:9000

runの後ろにオプションを指定しても反映されない。 デフォルト値の9000で実行されます。

※追加するオプションはrunの手前で実行する。

ソースを覗く

port指定する場所をソースからみてみます。

Play20 / framework / src / play / src / main / scala / play / core / server / NettyServer.scalaの230行目あたり。

val server = new NettyServer(
    new StaticApplication(applicationPath),
    Option(System.getProperty("http.port")).map(Integer.parseInt(_)).getOrElse(9000),
    Option(System.getProperty("https.port")).map(Integer.parseInt(_)),
    Option(System.getProperty("http.address")).getOrElse("0.0.0.0")
)

ここで指定しているオプションは、http.port、https.port、http.addressの3つ。

OptionはScala特有の記述方法で、PHPでいうとissetとかempty関数みたいな利用方法のよう。 scala-cookbook:Option Monad nullや存在しない値の処理を隠蔽するに詳しく書いてました。

Scalaの見方が分かってくると少しずつ楽しくなってきます。

def createServer(applicationPath: File): Option[NettyServer] = {
//~~~省略~~~
}

createServerという関数?の定義にOption[NettyServer]が利用されていて、 使っているところが以下の部分です。

 def main(args: Array[String]) {
    args.headOption.orElse(
      Option(System.getProperty("user.dir"))).map(new File(_)).filter(p => p.exists && p.isDirectory).map { applicationPath =>
        createServer(applicationPath).getOrElse(System.exit(-1))
      }.getOrElse {
        println("Not a valid Play application")
      }
  }

Optionが多用されてますね。user.dirのプロパティがあれば、 その値を元にFileオブジェクトを生成してexistsとisDirectorycで存在チェックし、問題なければサーバ起動という処理の流れです。

System.getProperty("user.dir")は何を示しているのか。

System.getProperty("user.dir")が何を表すのか分からなかったので、調べてみました。 ソースを探しても見つからないのでググる。 プロパティで指定したキー("user.dir")はカレントディレクトリだそうです。

応用 Java Application - Utility classes - Propertiesにありました。

代表的なプロパティのキーバリューをコピペして整形してメモる。

key value
file.separator ファイルの区切り文字(UNIXなら、'/')
java.class.path Java クラスパス
java.class.version Java クラスのバージョン
java.home Java がインストールされているディレクトリ
java.vendor.url Java ベンダのURL
java.version Java のバージョン
line.separator 行の区切り
os.arch OSのアーキテクチャ
os.name OS名
path.separator パスの区切り(':')
user.dir カレント・ディレクトリ
user.home ユーザのホーム・ディレクトリ
user.name ユーザ名

他の言語であれば、envとかで取得する項目のようですが、javaではプロパティを利用するそうです。 .netでいうと、ConfigurationSettingsみたいなものでしょうか。