When you are building applications or libraries in the Scala programming language, you will most likely use a tool like „SBT“ (Scala Build Tool) or „Lightbend Activator“ (which is an extended distribution of SBT) to configure, build and package your project. These tools support automatic dependency management for your project.
Like in almost every build system, SBT allows you to define library dependencies which are resolved automatically, so you don’t have to download and package required libraries by yourself.
Currently SBT can handle a lot of repository types, including Ivy and Maven repositories, which gives you instant access to all libraries available in the Maven universe.
Dependency Management in build.sbt
To add some Maven libraries to your classpath, you can simple edit the file „build.sbt“ in your project. Each dependency is described by a triple of
- Group ID (e.g. „com.google.guava“)
- Artifact ID (e.g. „guava“)
- Revision or Version (e.g. „18.0“)
In the build.sbt file, there is a list of all defined dependencies, to which you can either add single dependencies, or a whole sequence at once. SBT supports a special syntax where GroupID, ArtifactID and Version are separated by the percent sign „%“.
1 |
libraryDependencies += "com.google.guava" % "guava" % "18.0" |
Add multiple dependencies
In order to define more than one library dependency, you can either write the line to add a dependency multiple times, or you can add a whole sequence at one (the build.sbt file is really a Scala file, so you can use Scala syntax here)
1 2 3 4 5 |
libraryDependencies ++= Seq( "com.google.inject" % "guice" % "4.0", "com.google.guava" % "guava" % "18.0", "javax.inject" % "javax.inject" % "1" ) |
Add Scala dependencies
If you don’t want to add only Java libraries but also Scala libraries, you have to make sure that they are compiled against the same Scala version as your project.
In order to ensure this, there is a convention to add the scala version (with ony major and minor version number) to the Maven artifact ID, e.g.:
1 |
libraryDependencies += "org.json4s" % "json4s-native_2.11" % "3.3.0" |
Because most of time you don’t want to take care of this manually, and also the scala version of your project might change, there is a shorter Syntax for this:
When you use a double percent sign (%%) between the GroupID and the ArtifactID, the currently used Scala version is added automatically to the Artifact ID:
1 2 3 4 5 6 7 8 |
scalaVersion := "2.11.8" libraryDependencies ++= Seq( "com.google.inject" % "guice" % "4.0", "com.google.guava" % "guava" % "18.0", "javax.inject" % "javax.inject" % "1", "org.json4s" %% "json4s-native" % "3.3.0" ) |
Add testing dependencies
Like in Maven, there is the possibility to add dependencies only for the testing phase (like JUnit or Scalatest), which are only avaiable to the test classes, but are not used for compiling or packaging the real application.
To achive this, you only have to add an additional percent sign with „Test“ to a dependency:
1 2 3 4 5 6 7 |
libraryDependencies ++= Seq( "com.google.inject" % "guice" % "4.0", "com.google.guava" % "guava" % "18.0", "javax.inject" % "javax.inject" % "1", "org.json4s" %% "json4s-native" % "3.3.0", "org.mockito" % "mockito-core" % "1.10.17" % Test, ) |
Transitive dependencies
As a lot of libraries require some dependencies themselves, it is necessary for SBT to also include the dependencies of all your dependencies as well. This way you get a „dependency tree“ where all the libraries you need to build and run your application are included.
E.g. the library json4s-native needs the library „json4s-core“ where a lot of common classes and algorithms of this library are defined. This is quite common for Maven libraries in order to reuse code and make the libraries more flexible to combine.
You have to keep in mind, is that SBT will only take one version of a specific library (combination of GroupID and ArtifactID) for your dependencies. So if you have some dependencies which require some imaginary „Library X“ in version 2.0 and other ones which require the same library in version 3.4, SBT will choose the highest version 3.4 by default (because most of the time, common libraries are kept downwards-compatibile).
So, because of this transitive dependency resolution, you only have to add the libraries you need for your project, and SBT will make sure that the required dependencies for this libraries are added automatically.