Play! 2.0 framework multi Module project

2020-03-06 01:49发布

问题:

I would need to have two different projects, let's say internal and external, which use the same data layer, and I would like to avoid replicating the configuration file for dryness reasons.

I have looked to the sub projects documentation at http://www.playframework.org/documentation/2.0.2/SBTSubProjects but the doc is pretty short.

I am now aware of the possibility to modularize the configuration, thanks to @Georg Engel

import sbt._
import Keys._
import PlayProject._

object ApplicationBuild extends Build {

    val appName         = "MyApp"
    val appVersion      = "1.0-SNAPSHOT"

    val appDependencies = Seq(
      // Add your project dependencies here,
    )

    lazy val common = Project(appName + "-common", file("modules/common"))

    lazy val website = PlayProject(
    appName + "-website", appVersion, path = file("modules/website")
    ).dependsOn(common)

    lazy val adminArea = PlayProject(
    appName + "-admin", appVersion, path = file("modules/admin")
    ).dependsOn(common)

    lazy val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
      // Add your own project settings here      
    ).dependsOn(
    website, adminArea
    )


}

and the compilation errors I had where only due to the reverse router (canceling routes but not controller actions result in this)

回答1:

We are using submodules like this (where "core" is the shared submodule):

Build.scala

val coreModule = PlayProject(appName + "-core", "1.0", appDependencies, path = file("modules") / "core")

val main = PlayProject(appName + "-app", appVersion, appDependencies, mainLang = SCALA).settings(
  // Add your own project settings here      
).dependsOn(coreModule).aggregate(coreModule)

Unfortunatelly submodules have to live under the project tree ("../core" as path isn't possible) - so we are using git submodules to get the shared module into the tree:

git submodule add git://git.example.com/modules.git modules

git submodule init

git submodule update

Propably SVN externals, mercurial submodules etc. will do this job too.



回答2:

Here is what I do and have done. I make a multi-module Maven project where I basically keep all my core reusable code.

Then for all my other web projects (projects that make a WAR) I use SBT, Gradle, and even Ant with Maven plugins in some cases. Those projects hold there own config (like db host and creds).

framework
   - pom.xml
   - db-module
     - pom.xml
     - src/main/resources # possible classpath loading config here
     - etc...
   - mail-module
     - pom.xml
     - etc...
   - service-module
     - pom.xml
     - etc...

Other projects then just depend on the framework and for SBT projects (play 2.0) you can set it up so that one of your resolvers is a local maven repo: https://github.com/harrah/xsbt/wiki/Getting-Started-Library-Dependencies

EDIT for clarification: Framework pom.xml is the parent project. You can make the mail-module depend on the db-module and then in your separate web app project you can just depend on the mail-module and you will get both the mail-module and the db -module.

Many people throw Maven under the bus but it still does multi-module projects better than anything else.

More explanation:

  • http://www.sonatype.com/books/mvnex-book/reference/multimodule-web-spring-sect-intro.html#fig-multimodule-web-spring-projects

  • Download the example maven pom files here: http://www.sonatype.com/book/mvn-examples-1.0.zip ... Chapter 7 is the multi-module.



回答3:

A source dependency on a module living somewhere in your source tree can help you to achieve the build you want :

import sbt._
import Keys._
import PlayProject._

object ApplicationBuild extends Build {

    val appName         = "test"
    val appVersion      = "1.0-SNAPSHOT"

    val appDependencies = Seq(
      // Add your project dependencies here,
    )

    lazy val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
      // Add your own project settings here      
    ).dependsOn(common)


    lazy val common = RootProject(file("../common")) 


}

You cannot mix a play project with another, so your configuration should be in "dependencies". The good thing with source dependencies is they are live in your project (thanks to the recursivity of SBT). If the source of your dependency change, your main project get the change at the next compile.

You can check the complete structure of my multimodule play app here: https://github.com/un-jon/play2MultiModule.