It is generally a good practice to split your project into multiple modules. A well organized project is easier to understand. The complexity of the project is broken down into separate parts, each of those parts can be studied individually. Separation also helps to reduce incremental compilation times.
We will now transform our one-module project into project with multiple modules. We will follow a pretty standard separation into Util, DAO, Services and Web modules. One extra module will be macros, because we want to ensure, that they always reside in a separate compilation unit. Here is, how we want our project to look like, once it is imported to IntelliJ:
Multi module build.sbt
Let’s take a look at the
build.sbt file, one section at a time:
We start with defining some common settings. They will be reused in all modules.
Next, we define a root aggregator project. The concept is similar to Maven’s aggregator POM. This module is not really necessary for running the application. However, it comes handy, when we want to execute the same command for all modules, e.g.
Web module has been moved to a subdirectory. Sources are now located in
modules/scalactica2d-web/conf. It depends on another sub-module:
scalactica2dServices. It is also the only module with
PlayScala plugin enabled.
Services, DAO, Util and Macros modules have a standard location of sources in
Note, that sbt command
run does not work anymore. There is no runnable class in the aggregator module. Instead, we will start PlayFramework server by running
scalactica2dWeb/run. It is possible to create and alias in
Thin cake pattern
Now, we just need to wire everything together. For that, we will use the thin cake pattern. Let’s start from bottom up.
First of all, Macros and Util module do not expose any beans. Both contain Scala singletons (
object) or classes, that do not have state and no dependencies. A friend of mine once argued, that Util classes should be included to dependency injection too, just so that we use the same approach the same in whole project. It’s up to you, how you will decide on this.
DAO module components trait contains two beans, both implementing the same interface. It also declares a dependency on a
Services module components contains only one bean and one dependency:
Web module components contain router and controllers.
And finally, we mix in all components together. This is also the place, where we provide top level configuration of the whole application. In this example, we set up the datasource from configuration properties. We also choose which implementation of
PlanetDAO will be used. And we also choose, which filters will be used, while processing HTTP requests (none in this case.