play アプリケーションのクラスパス指定を短くする


この記事は Play framework Advent Calendar 2014 の9日目です。
昨日は @nazoking さんの play2.3 の sbt-web を使わず node で代替システムを作るための資料 でした。
明日は @xuwei_k さんの 2014年に自分がしたpull req です。

play でアプリを立ち上げて ps axwwww とかでプロセス見たときに恐ろしいことになっているのにお気づきでしょうか・・・

/usr/bin/java -classpath /opt/myapp/lib/org.scala-lang.scala-library-2.10.0.jar:/opt/myapp/lib/play.play_2.10-2.1.3.jar:/opt/myapp/lib/play.sbt-link-2.1.3.jar:/opt/myapp/lib/org.javassist.javassist-3.16.1-GA.jar:/opt/myapp/lib/play.play-exceptions-2.1.3.jar:/opt/myapp/lib/play.templates_2.10-2.1.3.jar:/opt/myapp/lib/com.github.scala-incubator.io.scala-io-file_2.10-0.4.2.jar:/opt/myapp/lib/com.github.scala-incubator.io.scala-io-core_2.10-0.4.2.jar:/opt/myapp/lib/com.jsuereth.scala-arm_2.10-1.3.jar:/opt/myapp/lib/play.play-iteratees_2.10-2.1.3.jar:/opt/myapp/lib/org.scala-stm.scala-stm_2.10.0-0.6.jar:/opt/myapp/lib/com.typesafe.config-1.0.0.jar:/opt/myapp/lib/io.netty.netty-3.6.3.Final.jar:/opt/myapp/lib/com.typesafe.netty.netty-http-pipelining-1.1.1.jar:/opt/myapp/lib/org.slf4j.jul-to-slf4j-1.6.6.jar:/opt/myapp/lib/org.slf4j.jcl-over-slf4j-1.6.6.jar:/opt/myapp/lib/ch.qos.logback.logback-core-1.0.7.jar:/opt/myapp/lib/ch.qos.logback.logback-classic-1.0.7.jar:/opt/myapp/lib/com.typesafe.akka.akka-actor_2.10-2.1.0.jar:/opt/myapp/lib/com.typesafe.akka.akka-slf4j_2.10-2.1.0.jar:/opt/myapp/lib/org.slf4j.slf4j-api-1.7.2.jar:/opt/myapp/lib/joda-time.joda-time-2.1.jar:/opt/myapp/lib/org.joda.joda-convert-1.2.jar:/opt/myapp/lib/org.apache.commons.commons-lang3-3.1.jar:/opt/myapp/lib/com.ning.async-http-client-1.7.6.jar:/opt/myapp/lib/oauth.signpost.signpost-core-1.2.1.2.jar:/opt/myapp/lib/oauth.signpost.signpost-commonshttp4-1.2.1.2.jar:/opt/myapp/lib/commons-logging.commons-logging-1.1.1.jar:/opt/myapp/lib/org.codehaus.jackson.jackson-core-asl-1.9.10.jar:/opt/myapp/lib/org.codehaus.jackson.jackson-mapper-asl-1.9.10.jar:/opt/myapp/lib/net.sf.ehcache.ehcache-core-2.6.0.jar:/opt/myapp/lib/javax.transaction.jta-1.1.jar:/opt/myapp/lib/org.scala-lang.scala-reflect-2.10.0.jar:/opt/myapp/lib/play.play-jdbc_2.10-2.1.3.jar:/opt/myapp/lib/play.play-java_2.10-2.1.3.jar:/opt/myapp/lib/org.yaml.snakeyaml-1.10.jar:/opt/myapp/lib/org.hibernate.hibernate-validator-4.3.0.Final.jar:/opt/myapp/lib/javax.validation.validation-api-1.0.0.GA.jar:/opt/myapp/lib/org.jboss.logging.jboss-logging-3.1.0.CR2.jar:/opt/myapp/lib/org.springframework.spring-context-3.1.2.RELEASE.jar:/opt/myapp/lib/org.springframework.spring-core-3.1.2.RELEASE.jar:/opt/myapp/lib/org.springframework.spring-beans-3.1.2.RELEASE.jar:/opt/myapp/lib/org.reflections.reflections-0.9.8.jar:/opt/myapp/lib/com.google.guava.guava-13.0.1.jar:/opt/myapp/lib/com.google.code.findbugs.jsr305-2.0.1.jar:/opt/myapp/lib/javax.servlet.javax.servlet-api-3.0.1.jar:/opt/myapp/lib/com.jolbox.bonecp-0.7.1.RELEASE.jar:/opt/myapp/lib/com.h2database.h2-1.3.168.jar:/opt/myapp/lib/tyrex.tyrex-1.0.1.jar:/opt/myapp/lib/play.anorm_2.10-2.1.3.jar:/opt/myapp/lib/mysql.mysql-connector-java-5.1.18.jar:/opt/myapp/lib/org.scalaz.scalaz-core_2.10-6.0.4.jar:/opt/myapp/lib/eu.medsea.mimeutil.mime-util-2.1.3.jar:/opt/myapp/lib/log4j.log4j-1.2.14.jar:/opt/myapp/lib/com.amazonaws.aws-java-sdk-1.5.6.jar:/opt/myapp/lib/org.apache.httpcomponents.httpclient-4.2.jar:/opt/myapp/lib/org.apache.httpcomponents.httpcore-4.2.jar:/opt/myapp/lib/commons-codec.commons-codec-1.6.jar:/opt/myapp/lib/javax.mail.mail-1.4.5.jar:/opt/myapp/lib/javax.activation.activation-1.1.jar:/opt/myapp/lib/org.codehaus.janino.janino-2.6.1.jar:/opt/myapp/lib/org.codehaus.janino.commons-compiler-2.6.1.jar:/opt/myapp/lib/dnsjava.dnsjava-2.1.1.jar:/opt/myapp/lib/junit.junit-3.8.2.jar:/opt/myapp/lib/net.sf.opencsv.opencsv-2.0.jar:/opt/myapp/lib/com.ibm.icu.icu4j-50.1.jar:/opt/myapp/lib/jivesoftware.smack-3.1.0.jar:/opt/myapp/lib/jivesoftware.smackx-3.1.0.jar:/opt/myapp/lib/csvutil_2.10-1.0.jar:/opt/myapp/lib/scalacsv_2.10-0.1-SNAPSHOT.jar:/opt/myapp/lib/seqform_2.10-0.1-SNAPSHOT.jar:/opt/myapp/lib/dbcolumns_2.10-0.1-SNAPSHOT.jar:/opt/myapp/lib/seqformdbcolumns_2.10-0.1-SNAPSHOT.jar:/opt/myapp/lib/playlib_2.10-0.1-SNAPSHOT.jar:/opt/myapp/lib/playtestlib_2.10-0.1-SNAPSHOT.jar:/opt/myapp/lib/myapp_2.10-1.0-SNAPSHOT-98.jar play.core.server.NettyServer

みたいな感じですね!

そこで build.sbt に

    scriptClasspath := {
      val originalClasspath = scriptClasspath.value
      val manifest = new java.util.jar.Manifest()
      manifest.getMainAttributes().putValue("Class-Path", originalClasspath.mkString(" "))
      val classpathJar = (target in Universal).value / "lib" / "classpath.jar"
      IO.jar(Seq.empty, classpathJar, manifest)
      Seq(classpathJar.getName)
    },
    mappings in Universal += (((target in Universal).value / "lib" / "classpath.jar") -> "lib/classpath.jar"),

のようなことを書くと、

/usr/bin/java -classpath /opt/myapp/lib/classpath.jar play.core.server.NettyServer

のようにすっきりします!

windows で activator start とかして環境変数が長すぎて起動できない場合などにも効果的です。

ご利用ください。