0

In SBT multiple projects, the main Web App is depended on some sub-projects. When I was thinking of Stubbed model, I would like to make the stubbed model implementation become a separated sub-projects.

Problem: The SBT project dependency is predefined in SBT. I can not make it dynamic depended on one or other of the sub-projects by command line.

That means, I can not have a "release build" to make web app only depended on a real implemented module, or a "stubbed build" to make the web app only depended on the stubbed module in the same projects tree.

The idea to separate the dependencies is: I don't want to have the product release war includes the stubbed jar. The stubbed jar should only be available in the test environment.

Question: Can I use the command line args to tell SBT which sub-project to be depended?

When starting the project at normal jetty:start, it the main project should be depended on regular sub-project. If I start the SBT with a command line like '-Stub = true', then I would like the main project change the dependency to stubbed sub-project. Since give a time, it should be either in the stubbed model or regular-stubbed model, the compiler should have a chance to update the dependencies. Is it possible to do it in SBT?

Here is a sample project:

lazy val DataTier = Project(
  id = "dataTier",
  base = file("dataTier"))
}

lazy val StubbedDataTier = Project(
  id = "stubbeddataTier",
  base = file("stubbeddataTier"))
}

lazy val webApp = Project(
 "tiny-web",
  file("."))
.aggregate(
    DataTier,
    StubbedDataTier
  )
.dependsOn(
  if (getCmdLineArg("Stub") == "true") StubbedDataTier else DataTier
)

When run SBT, we can do stubbed model:

./sbt ~jetty:start -Stub = true

or in the regular model

./sbt ~jetty:start

If SBT does not support it, is it possible to become a new feature for SBT like this?

.dependsOn(
  if (getCmdLineArg("Stub") == "true") StubbedDataTier else DataTier
)

1 Answers1

0

Sorry for answering my own question. After trying something, I found some workaround, I would like to share it in here so it may be helpful for other people.

Instead of using the command line, I use the environment variable to dynamic control the project link.

Here is example of project configure:

lazy val DataTier = Project(
  id = "dataTier",
  base = file("dataTier"))
  .settings(commonSettings: _*)

lazy val LiveDataTier = Project(
  id = "livedataTier",
  base = file("livedataTier"))
  .settings(commonSettings: _*)
  .dependsOn(
    DataTier
  )

lazy val StubDataTier = Project(
  id = "stubdataTier",
  base = file("stubdataTier"))
  .settings(commonSettings: _*)
  .dependsOn(
    DataTier
  )

lazy val webApp = Project( "my-web",
  file("."))
.aggregate(
    DataTier,
    LiveDataTier,
    StubDataTier
  )
.dependsOn(
  DataTier
)

lazy val stubbed = System.getenv("Stub") match {
  case "true" => {
    System.out.print("The Stubbed model is turned on\n")
    webApp.dependsOn(
      StubDataTier
    )
  }
  case _ =>{
    System.out.print("The Stubbed model is turned off\n")
    webApp.dependsOn(
      LiveDataTier
    )
  }
}

The data tier defined the interface only, then the LiveDataTier and StubDataTier do two sets of the implementation for the same data tier. In the webApp, you don't need to have any switch for the dependency, just use it like you only have one dependency project.

When needing it to be run in the stubbed model, run the command line:

export Stub=true

Then start normal SBT clean build, then the WebApp project will link to StubDataTier

By running the command line:

export Stub=false

Then the webApp will use livedataTier as the dependency sub-project.

By default, it will be livedataTier as the dependency.

This works great for me.

Note: When switching between the two dependencies, you should do a clean build.