次の SBT/Play2 マルチプロジェクト設定があります。
import sbt._
import Keys._
import PlayProject._
object ApplicationBuild extends Build {
val appName = "traveltime-api"
val appVersion = "1.0"
val appDependencies = Seq(
// Google geocoding library
"com.google.code.geocoder-java" % "geocoder-java" % "0.9",
// Emailer
"org.apache.commons" % "commons-email" % "1.2",
// CSV generator
"net.sf.opencsv" % "opencsv" % "2.0",
"org.scalatest" %% "scalatest" % "1.7.2" % "test",
"org.scalacheck" %% "scalacheck" % "1.10.0" % "test",
"org.mockito" % "mockito-core" % "1.9.0" % "test"
)
val lib = RootProject(file("../lib"))
val chiShape = RootProject(file("../chi-shape"))
lazy val main = PlayProject(
appName, appVersion, appDependencies, mainLang = SCALA
).settings(
// Add your own project settings here
resolvers ++= Seq(
"Sonatype Snapshots" at
"http://oss.sonatype.org/content/repositories/snapshots",
"Sonatype Releases" at
"http://oss.sonatype.org/content/repositories/releases"
),
// Scalatest compatibility
testOptions in Test := Nil
).aggregate(lib, chiShape).dependsOn(lib, chiShape)
}
ご覧のとおり、このプロジェクトは lib と chiShape という 2 つの独立したサブプロジェクトに依存しています。
コンパイルが正常に動作するようになりました - すべてのソースが正しくコンパイルされます。ただし、実行またはテストしようとすると、実行時のどちらのタスクにもクラスパス上のサブプロジェクトからのクラスがロードされず、NoClassFound 例外が発生して事態が悪化します。
たとえば、私のアプリケーションはシリアル化されたデータをファイルからロードする必要があり、次のようになります: テストは FakeApplication を開始し、データのロードを試みてブームになります:
[info] CsvGeneratorsTest:
[info] #markerFilterCsv
[info] - should fail on bad json *** FAILED ***
[info] java.lang.ClassNotFoundException: com.library.Node
[info] at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
[info] at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
[info] at java.security.AccessController.doPrivileged(Native Method)
[info] at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
[info] at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
[info] at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
[info] at java.lang.Class.forName0(Native Method)
[info] at java.lang.Class.forName(Class.java:264)
[info] at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:622)
[info] at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
[info] ...
奇妙なことに、stage は staged/ に chi-shapes_2.9.1-1.0.jar と lib_2.9.1-1.0.jar を含むディレクトリ構造を作成します。
実行時/テスト構成でサブプロジェクトをクラスパスに入れるにはどうすればよいですか?
アップデート:
Global#onStart に次のコードを追加しました。
override def onStart(app: Application) {
println(app)
ClassLoader.getSystemClassLoader.asInstanceOf[URLClassLoader].getURLs.
foreach(println)
throw new RuntimeException("foo!")
}
テストを起動すると、クラスパスのデータが非常に少なくなります。少なくとも :)
FakeApplication(.,sbt.classpath.ClasspathUtilities$$anon$1@182253a,List(),List(),Map(application.load-data -> test, mailer.smtp.test-mode -> true))
file:/home/arturas/Software/sdks/play-2.0.3/framework/sbt/sbt-launch.jar
[info] CsvGeneratorsTest:
ステージングされたアプリを起動するとき、それがどうあるべきか、たくさんのものがあります:)
$ target/start
Play server process ID is 29045
play.api.Application@1c2862b
file:/home/arturas/work/traveltime-api/api/target/staged/jul-to-slf4j.jar
クラスパスには少なくともテスト用のjarが必要なので、それは奇妙です。