Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need advice on project layout for Play 2.2 submodule with other modules as dependencies

I have an existing SBT project with modules. I want to add Play 2.2 into my project as a submodule. This new Play module will depend on other modules.

What I found so far was mostly about Play being the main project with supporting modules. If Play does support this setup, please point me in the right direction how to do it. Thanks.

My intended setup (simplified):

my_project
\--- desktop_ui
     \--- src/main
     \--- src/test
\--- common
     \--- src/main
     \--- src/test
\--- web_ui (Play framework)
     \--- app/controllers
     \--- app/views
     \--- app/models
     \--- conf
like image 975
thlim Avatar asked Jan 04 '14 18:01

thlim


2 Answers

Play 2.2 supports sbt 0.13 so to use it for your expected project layout I'd recommend to have the following build.sbt in the my_project root project:

import play.Project._

lazy val my_project = project in file(".") aggregate (desktop_ui, common, web_ui)

lazy val desktop_ui = project dependsOn common

lazy val common = project

// no need to dependsOn "common" since it's already a dependency of "desktop_ui"
lazy val web_ui = play.Project(name = "web_ui", path = file("web_ui"))
                    .dependsOn(desktop_ui)

Since my_project uses Play 2.2 class - play.Project - to define a Play project, project/plugins.sbt is required.

resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.2-RC1")

That might explain why Play module is usually a top-level one (since so much is needed in the top-level project that it effectively becomes a Play module).

The complete project layout is as follows:

$ tree
.
├── build.sbt
└── project
    ├── build.properties
    └── plugins.sbt

1 directory, 3 files

What's quite interesting is that even without all the project directories and no Play project in place (just a definition in the build.sbt) you can still run the web_ui project and access it with your web browser (!) It will fail for obvious reasons, but shows there's not much needed to get running with sbt and Play.

$ sbt
[info] Loading global plugins from /Users/jacek/.sbt/0.13/plugins
[info] Loading project definition from /Users/jacek/sandbox/so/play-2.2-multi/my_project/project
[info] Updating {file:/Users/jacek/sandbox/so/play-2.2-multi/my_project/project/}my_project-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to my_project (in build file:/Users/jacek/sandbox/so/play-2.2-multi/my_project/)
[my_project]> projects
[info] In file:/Users/jacek/sandbox/so/play-2.2-multi/my_project/
[info]     common
[info]     desktop_ui
[info]   * my_project
[info]     web_ui
[my_project]> project web_ui
[info] Set current project to web_ui (in build file:/Users/jacek/sandbox/so/play-2.2-multi/my_project/)
[web_ui]> run
[info] Updating {file:/Users/jacek/sandbox/so/play-2.2-multi/my_project/}common...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Updating {file:/Users/jacek/sandbox/so/play-2.2-multi/my_project/}desktop_ui...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Updating {file:/Users/jacek/sandbox/so/play-2.2-multi/my_project/}web_ui...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.

--- (Running the application from SBT, auto-reloading is enabled) ---

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

(Server started, use Ctrl+D to stop and go back to the console...)

[info] play - Application started (Dev)
like image 123
Jacek Laskowski Avatar answered Nov 13 '22 05:11

Jacek Laskowski


Two options:

1) have an 'empty' main project aggregating your 3 sub-projects:

root
\--- project
    \--- Build.scala
\--- web_ui
\--- common
\--- desktop_ui

And in Build.scala something like this:

lazy val common = Project(id = "common", base = file("common"))
lazy val desktopUi = Project(id = "desktop_ui", base = file("desktop_ui")
lazy val webUi = play.Project(name = "web_ui", path = file("web_ui"))
.dependsOn(common, desktopUi)

lazy val root = Project(id = "root", base = file(".")).aggregate(common, desktopUi, webUi)

With this option, you can start sbt from the root folder and build all your projects. You also define all the settings, dependencies in this unique build definition.

2) Another layout can be used to keep your sub-projects independent from each other. I tend to prefer this way because it's cleaner (e.g. I can work on common as an independent project, not as a submodule) but it is not as convenient to build the whole system.

root
\--- web_ui
    \--- project
        \--- Build.scala
\--- common
     \--- project
        \--- Build.scala
\--- desktop_ui
     \--- project
        \--- Build.scala

Here, each project is independent (you can use build.sbt instead of Build.scala if you want, see sbt documentation) and in web_ui/project/Build.scala :

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

val main = play.Project(name = "web_ui", path = file("web_ui")).dependsOn(common, desktopUi) 

Here, root is just used to gather everything in one folder, then the play project references the other modules.

like image 41
vptheron Avatar answered Nov 13 '22 04:11

vptheron