PlayFramework의 하위 프로젝트에서 끝난 것

빠진 것



PlayFramework2.3.x계에서의 서브프로젝트의 설정에서는 참은 이하 2점
  • 테스트시 설정 파일 읽기
  • routes 설정

  • 하는 방법



    기본적으로 PlayFramework의 공식 문서대로 설정합니다.
    하위 프로젝트
    공식 문서에서는 2.2.x에서는 Build.scala로 모두 설정하고 있습니다만, 2.3.x에서는 build.sbt와 Build.scala의 양쪽 모두에 적절히 설정하는 방법으로 변경되고 있는 것 같습니다.
    Build.scala만으로도 기술은 가능하다고 생각합니다만, 이 기사에서는 공식 문서대로의 설정으로 빠진 것을 기술합니다.

    설정해보기



    이번은 DDD 같은 구성에 플러스, 정적 파일만의 프로젝트도 서브 프로젝트로서 나누고 있습니다.

    메인 프로젝트 설정



    conf/build.sbt
    name := """multi-project-sample"""
    
    version := "1.0-SNAPSHOT"
    
    lazy val asset = (project in file("modules/asset"))
      .enablePlugins(PlayScala)
    
    lazy val infrastructure = (project in file("modules/infrastructure"))
      .enablePlugins(PlayScala)
    
    lazy val domain = (project in file("modules/domain"))
      .enablePlugins(PlayScala)
      .dependsOn(infrastructure)
    
    lazy val application = (project in file("modules/application"))
      .enablePlugins(PlayScala)
      .dependsOn(infrastructure, domain)
    
    lazy val main = (project in file("."))
      .enablePlugins(PlayScala)
      .dependsOn(asset, infrastructure, domain, application)
      .aggregate(asset, infrastructure, domain, application)
    
    Setting.main
    

    하위 프로젝트별 설정



    modules/xxx/build.sbt
    name := """multi-project-xxx"""
    
    version := "1.0-SNAPSHOT"
    
    Setting.application
    

    프로젝트 고급 설정



    빠진 것 1
    javaOptions in Test ++= Seq("-Dconfig.file=../../conf/application.conf")
    

    서브 프로젝트에서 테스트 할 때 application.conf를 참조하면 그대로는 경로 설정이 다르므로 내용을 얻을 수 없습니다.
    run, stage 된 것은 프로젝트가 집계되어 있으므로 conf/application.conf를 참조할 수 있습니다만, test시에는 개별의 프로젝트로서 실행되므로 module/xxx/conf/application.conf의 패스를 참조해 버립니다.
    우선 상기의 설정을 넣고 있습니다만, 갈 수 없습니다! !

    project/Build.scala
    import sbt._
    import Keys._
    import scoverage._
    
    object Setting {
      val common: Seq[Setting[_]] = Seq(
        organization := "com.example",
        scalaVersion := "2.11.5",
        libraryDependencies ++= Dependency.common,
        
        scalacOptions ++= Seq("-deprecation", "-feature", "-language:reflectiveCalls"),
        
        )
    
      val asset = common ++ Seq(
        resolvers ++= Resolver.common,
        libraryDependencies ++= Dependency.asset,
        javaOptions in Test ++= Seq("-Dconfig.file=../../conf/application.conf")
      )
      val infrastructure = common ++ Seq(
        resolvers ++= Resolver.infrastructure,
        libraryDependencies ++= Dependency.infrastructure,
        javaOptions in Test ++= Seq("-Dconfig.file=../../conf/application.conf")
      )
      val domain = common ++ Seq(
        resolvers ++= Resolver.domain,
        libraryDependencies ++= Dependency.domain,
        javaOptions in Test ++= Seq("-Dconfig.file=../../conf/application.conf")
      )
      val application = common ++ Seq(
        resolvers ++= Resolver.application,
        libraryDependencies ++= Dependency.application,
        javaOptions in Test ++= Seq("-Dconfig.file=../../conf/application.conf")
      )
      val main = common ++ Seq(
        resolvers ++= Resolver.main,
        libraryDependencies ++= Dependency.main
      )
    }
    
    object Dependency {
      val common = Seq()
    
      val asset = common ++ Seq()
      val infrastructure = common ++ Seq()
      val domain = common ++ Seq()
      val application = common ++ Seq()
      val main = common ++ Seq()
    }
    
    object Resolver {
      val common = Seq()
    
      val asset = common ++ Seq()
      val infrastructure = common ++ Seq()
      val domain = common ++ Seq()
      val application = common ++ Seq()
      val main = common ++ Seq()
    }
    

    routes 분할



    routes 파일은 집계된 후에 고유한 파일이어야 하므로 하위 프로젝트별로 routes 파일 이름을 변경하여 주 프로젝트의 routes에서 참조하도록 설정합니다.
    패스의 설정 부분은, 독특하다면 적당한 이름으로 좋은 것 같습니다.

    conf/routes
    GET     /                   controllers.Application.index
    ->      /asset              asset.Routesh
    ->      /application        application.Routes
    GET     /assets/*file       controllers.Assets.at(path="/public", file)
    

    훔친 것 2
    공식 문서에 기재되어 있으므로 빠진 것은 나뿐이겠지…
    하위 프로젝트의 routes에서도 Assets 클래스를 사용하려면 상속된 클래스를 준비해야 합니다.
    이것은 라우팅 클래스를 생성할 때 이름이 독특하지 않으면 클래스 이름이 중복되기 때문이 아닐까? 어쩌면

    modules/asset/app/controllers/Assets.scala
    package controllers.asset
    object Assets extends controllers.AssetsBuilder
    

    modules/asset/conf/asset.routes
    GET /assets/*file           controllers.asset.Assets.at(path="/public", file)
    

    놀라다



    test 명령! !


    [multi-project-sample] $ test
    [info] ApplicationSpec
    [info]
    [info] Application should
    [info] + with configuration
    [info]
    [info] Total for specification ApplicationSpec
    [info] Finished in 1 second, 49 ms
    [info] 1 example, 0 failure, 0 error
    [info] Passed: Total 1, Failed 0, Errors 0, Passed 1
    [info] ApplicationSpec
    [info]
    [info] Application should
    [info] + send 404 on a bad request
    [info] + render the index page
    [info]
    [info] Total for specification ApplicationSpec
    [info] Finished in 1 second, 217 ms
    [info] 2 examples, 0 failure, 0 error
    [info] IntegrationSpec
    [info]
    [info] Application should
    [info] + work from within a browser
    [info]
    [info] Total for specification IntegrationSpec
    [info] Finished in 1 second, 611 ms
    [info] 1 example, 0 failure, 0 error
    [info] Passed: Total 3, Failed 0, Errors 0, Passed 3
    [success] Total time: 10 s, completed 2015/02/11 18:18:14
    

    Scoverrage! !



    아, 설정은 별도 필요합니다.
    coverageAggregate를 사용하여 보고서를 집계할 수 있습니다.
    $ activator clean coverage test coverageAggregate
    $ open target/scala-2.11/scoverage-report/index.html
    



    이미지 취득 확인! !



    아래에서 설명하는 Github 프로젝트에서 다음 명령을 실행하면 하위 프로젝트와 메인 프로젝트에 배치 된 이미지를 각각 올바르게 얻을 수 있음을 알 수 있습니다.
    $ wget http://127.0.0.1:9000/assets/scala-chan.png
    $ wget http://127.0.0.1:9000/assets/mysql-chan.png
    

    사이고에게



    GitHub에서 작동하는 샘플을 Push하고 있습니다.
    play2.3-multi-project-sample

    좋은 웹페이지 즐겨찾기