How do dependencies work in Scala? - scala

For my existing projects I am migrating from scalaVersion 2.10.5 to 2.11.7 and sbtVersion 1.13.9 also.
Current migrating project is Sales, it have Sales-common, Sales-read, Sales-write modules. It have one dependent project Core. But I don't have Core project code I have only already published artefact jars(I have myapp-core-read_2.10-2.2.33.jar, 2.10 is Scala version).
My project looks like this
Sales
common
build.sbt
read
build.sbt
write
build.sbt
build.sbt
Till now, with scala 2.10.5 everything working fine using in real time also.
After change the version I run sbt clean and sbt update. I am getting Unresolved dependency issue like this:
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: mycompany#myapp-core-read_2.11;2.2.33: not found
[warn] :: mycomapny#myapp-core-write_2.11;2.2.33: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
My Sales buld.sbt is this:
name := "myapp-sales"
organization in ThisBuild := "com.mycompany"
scalaVersion in ThisBuild := "2.11.7"
//crossScalaVersions in Thisq
//Build := List("2.10.5", scalaVersion.value)
//crossPaths := false
scalacOptions in Compile in ThisBuild ++= Seq("-unchecked", "-deprecation", "-encoding", "utf8", "-language:postfixOps", "-language:implicitConVersions")
lazy val common = Project("myapp-sales-common", file("common"))
lazy val read = Project("myapp-sales-read", file("read")).configs(IntegrationTest).settings(Defaults.itSettings: _*).dependsOn(common, write)
lazy val write = Project("myapp-sales-write", file("write")).configs(IntegrationTest).settings(Defaults.itSettings: _*).dependsOn(common)
conflictWarning in ThisBuild := ConflictWarning.disable
parallelExecution in Test in ThisBuild := false
parallelExecution in IntegrationTest in ThisBuild := false
javacOptions in Compile in ThisBuild ++= Seq("-source", "1.6", "-target", "1.6")
//Remove SNAPSHOT check from the release process (for now until Squants gets a release)
releaseProcess := releaseProcess.value.filterNot(_ == ReleaseTransformations.checkSnapshotDependencies)
My read module build.sbt:
libraryDependencies ++= Seq(
"com.mycompany" %% "myapp-core-read" % myappsales.CoreVersion % "compile", // disable using the Scala version in output paths and artifacts,
"com.mycompany" %% "myapp-core-write" % myappsales.CoreVersion % "compile",
"com.mycompany" %% "myapp-registration-common" % myappsales.RegistrationVersion % "compile",
"com.mycompany" %% "myapp-load-common" % myappsales.LoadVersion % "compile",
"com.mycompany" %% "myapp-core-write-test" % myappsales.CoreVersion % "it, test",
"com.mycompany" %% "myapp-core-test" % myappsales.CoreVersion % "it, test"
)
libraryDependencies ++= Seq(
"com.typesafe" % "config" % myappsales.TypeSafeConfigVersion % "compile",
"org.json4s" %% "json4s-native" % Versions.Json4s % "compile",
"io.spray" % "spray-routing" % Versions.Spray % "compile",
"com.typesafe.akka" %% "akka-actor" % Versions.Akka % "compile",
"com.typesafe.akka" %% "akka-remote" % Versions.Akka % "compile"
exclude ("io.netty", "netty")
)
//Assemby settings
test in assembly := {}
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("play.api.libs.iteratee.**" -> "shade.play.api.libs.iteratee.#1")
.inLibrary("play" % "play-iteratees_2.10" % "2.1-RC2")
.inLibrary("org.reactivemongo" % "reactivemongo_2.10" % "0.8.1-SNAPSHOT"),
ShadeRule.rename("scala.concurrent.stm.**" -> "shade.scala.concurrent.stm.#1")
.inLibrary("org.scala-stm" % "scala-stm_2.10.0" % "0.6")
.inLibrary("play" % "play-iteratees_2.10" % "2.1-RC2")
)
assemblyMergeStrategy in assembly := {
case "application.conf" => MergeStrategy.concat
case path => MergeStrategy.defaultMergeStrategy(path)
}
//Make assembly a publishable artifact
artifact in (
Compile, assembly) := {
val art = (artifact in (Compile, assembly)).value
art.copy(`classifier` = Some("assembly"))
}
addArtifact(artifact in (Compile, assembly), assembly)
How can I make it work with existing myapp-core-read_2.10-2.2.33.jar jar?

Important note: Scala 2.10 and 2.11 are not binary compatible so you will have to recompile the modules on which you depend
Answer to question:
This seems to be related to how SBT resolves dependencies. When you declare a dependency like so:
"com.mycompany" %% "myapp-core-read" % myappsales.CoreVersion
The %% part in the declaration means that SBT will automatically append the scala version to the library name, so your dependency becomes
group: com.mycompany
artifactId: myapp-core-read_2.11
version: `your version`
It seems that your myapp-core-read was not compiled with scala 2.11 thus SBT can't find the correct version.
You can avoid this by using % and applying the correct suffix manually, so your dependency would become:
"com.mycompany" % "myapp-core-read_2.10" % myappsales.CoreVersion
Having said that, I think scala 2.10 and 2.11 are not binary compatible so you might have to recompile the myapp-core-read module with 2.11.

Related

Dependency duplication when creating a fat jar for playframework with play-ws

I noticed that when trying to build fat jara for playframework 2.7 with play-ws (sbt assembly), dependency duplications occur. I get a lot of errors related to javax.activation-api and shaded-asynchttpclient e.g.
[error] deduplicate: different file contents found in the following:
[error] /home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/javax/activation/javax.activation-api/1.2.0/javax.activation-api-1.2.0.jar:javax/activation/UnsupportedDataTypeException.class
[error] /home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/com/typesafe/play/shaded-asynchttpclient/2.0.6/shaded-asynchttpclient-2.0.6.jar:javax/activation/UnsupportedDataTypeException.class
The problem turns out to be the play-ws without which sbt assembly is carried out correctly. The only place in my code where I explicitly use javax is dependency injection. Using guice instead gives the same result. Here is my build.sbt (which is based on https://www.playframework.com/documentation/2.7.x/Deploying)
name := "My-App"
version := "1.0"
scalaVersion := "2.11.12"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaSource in ThisScope := baseDirectory.value
mainClass in assembly := Some("play.core.server.ProdServerStart")
fullClasspath in assembly += Attributed.blank(PlayKeys.playPackageAssets.value)
libraryDependencies ++= Seq(
ws,
specs2 % Test,
"com.typesafe.play" %% "play-json" % "2.7.4",
"com.typesafe.play" %% "play-slick" % "4.0.2",
"com.typesafe.play" %% "play-slick-evolutions" % "4.0.2",
"com.typesafe" % "config" % "1.4.0",
"org.mindrot" % "jbcrypt" % "0.4",
"mysql" % "mysql-connector-java" % "8.0.17",
"org.mindrot" % "jbcrypt" % "0.4",
"com.iheart" %% "ficus" % "1.4.7",
"com.typesafe.scala-logging" % "scala-logging_2.11" % "3.9.0"
)
assemblyMergeStrategy in assembly := {
case manifest if manifest.contains("MANIFEST.MF") =>
// We don't need manifest files since sbt-assembly will create
// one with the given settings
MergeStrategy.discard
case referenceOverrides if referenceOverrides.contains("reference-overrides.conf") =>
// Keep the content for all reference-overrides.conf files
MergeStrategy.concat
case x =>
// For all the other files, use the default sbt-assembly merge strategy
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}

common-validator sbt dependency for scala 2.12.1

My sbt file looks as follows
organization := "scala"
name := "MyProject"
version := "1.0"
scalaVersion := "2.12.1"
libraryDependencies += "com.github.nscala-time" %% "nscala-time" % "2.20.0"
libraryDependencies += "commons-net" % "commons-net" % "3.6"
libraryDependencies += "commons-validator" % "commons-validator" % "1.6.0"
When I run sbt compile I get this
sbt.librarymanagement.ResolveException: unresolved dependency: commons-validator#commons-validator;1.6.0: not found
However when I change scala version to 2.11.7, sbt compiles fine. What am I missing? How can I make it work for 2.12.1?
According to mvnrepo (https://mvnrepository.com/artifact/commons-validator/commons-validator)
use libraryDependencies += "commons-validator" % "commons-validator" % "1.6"

Scala play with reactivemongo, not working

I am trying to follow along this tutorial and I can't get reactivemongo to work:
This is my error:
UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: org.reactivemongo#play2-reactivemongo_2.12;0.11.7.play24: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn]
[warn] Note: Unresolved dependencies path:
[warn] org.reactivemongo:play2-reactivemongo_2.12:0.11.7.play24 (/Users/jwan/Desktop/programming/scala_play/rest-api/build.sbt#L12-20)
This is my built.sbt:
name := """rest-api"""
organization := "com.example"
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.12.4"
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.2" % Test
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test,
"org.reactivemongo" %% "play2-reactivemongo" % "0.11.7.play24",
"org.scalatest" % "scalatest_2.11" % "2.2.4" % "test"
)
// Adds additional packages into Twirl
//TwirlKeys.templateImports += "com.example.controllers._"
// Adds additional packages into conf/routes
// play.sbt.routes.RoutesKeys.routesImport += "com.example.binders._"
And this is my application.conf:
# https://www.playframework.com/documentation/latest/Configuration
play.modules.enabled += "play.modules.reactivemongo.ReactiveMongoModule"
mongodb.uri = "mongodb://localhost:27017/getting-started-play-scala"
I can't get sbt run to work. Any ideas?
According to https://mvnrepository.com/artifact/org.reactivemongo/play2-reactivemongo.
Required scala version is 2.11 for reactivemongo 0.11.7.play24.
Try 0.13.0-play26 for scalaVersion := "2.12.4" and play 26.
libraryDependencies += "org.reactivemongo" %% "play2-reactivemongo" % "0.13.0-play26"

Why is Scala looking for SNAPSHOT version?

I mentioned json4s-native 3.3.0 but it refering 3.3.0-SNAPSHOT.
In my project there is 3 modules (common, read and write) each have its scala.sbt.
Before change:
"org.json4s" %% "json4s-native" % Versions.Json4s % "compile",
After change:(Changed all the places in 3 modules)
"org.json4s" %% "json4s-native" % "3.3.0" % "compile",
I run:
sbt
clean
update
Error:
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: org.json4s#json4s-native_2.10;3.3.0-SNAPSHOT: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn]
[warn] Note: Unresolved dependencies path:
[warn] org.json4s:json4s-native_2.10:3.3.0-SNAPSHOT
My Sales buld.sbt is this:
name := "myapp-sales"
organization in ThisBuild := "com.mycompany"
scalaVersion in ThisBuild := "2.11.7"
//crossScalaVersions in Thisq
//Build := List("2.10.5", scalaVersion.value)
//crossPaths := false
scalacOptions in Compile in ThisBuild ++= Seq("-unchecked", "-deprecation", "-encoding", "utf8", "-language:postfixOps", "-language:implicitConVersions")
lazy val common = Project("myapp-sales-common", file("common"))
lazy val read = Project("myapp-sales-read", file("read")).configs(IntegrationTest).settings(Defaults.itSettings: _*).dependsOn(common, write)
lazy val write = Project("myapp-sales-write", file("write")).configs(IntegrationTest).settings(Defaults.itSettings: _*).dependsOn(common)
conflictWarning in ThisBuild := ConflictWarning.disable
parallelExecution in Test in ThisBuild := false
parallelExecution in IntegrationTest in ThisBuild := false
javacOptions in Compile in ThisBuild ++= Seq("-source", "1.6", "-target", "1.6")
//Remove SNAPSHOT check from the release process (for now until Squants gets a release)
releaseProcess := releaseProcess.value.filterNot(_ == ReleaseTransformations.checkSnapshotDependencies)
My read module build.sbt:
libraryDependencies ++= Seq(
"com.mycompany" %% "myapp-core-read" % myappsales.CoreVersion % "compile", // disable using the Scala version in output paths and artifacts,
"com.mycompany" %% "myapp-core-write" % myappsales.CoreVersion % "compile",
"com.mycompany" %% "myapp-registration-common" % myappsales.RegistrationVersion % "compile",
"com.mycompany" %% "myapp-load-common" % myappsales.LoadVersion % "compile",
"com.mycompany" %% "myapp-core-write-test" % myappsales.CoreVersion % "it, test",
"com.mycompany" %% "myapp-core-test" % myappsales.CoreVersion % "it, test"
)
libraryDependencies ++= Seq(
"com.typesafe" % "config" % myappsales.TypeSafeConfigVersion % "compile",
"org.json4s" %% "json4s-native" % Versions.Json4s % "compile",
"io.spray" % "spray-routing" % Versions.Spray % "compile",
"com.typesafe.akka" %% "akka-actor" % Versions.Akka % "compile",
"com.typesafe.akka" %% "akka-remote" % Versions.Akka % "compile"
exclude ("io.netty", "netty")
)
//Assemby settings
test in assembly := {}
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("play.api.libs.iteratee.**" -> "shade.play.api.libs.iteratee.#1")
.inLibrary("play" % "play-iteratees_2.10" % "2.1-RC2")
.inLibrary("org.reactivemongo" % "reactivemongo_2.10" % "0.8.1-SNAPSHOT"),
ShadeRule.rename("scala.concurrent.stm.**" -> "shade.scala.concurrent.stm.#1")
.inLibrary("org.scala-stm" % "scala-stm_2.10.0" % "0.6")
.inLibrary("play" % "play-iteratees_2.10" % "2.1-RC2")
)
assemblyMergeStrategy in assembly := {
case "application.conf" => MergeStrategy.concat
case path => MergeStrategy.defaultMergeStrategy(path)
}
//Make assembly a publishable artifact
artifact in (
Compile, assembly) := {
val art = (artifact in (Compile, assembly)).value
art.copy(`classifier` = Some("assembly"))
}
addArtifact(artifact in (Compile, assembly), assembly)
Why it still looking for SNAPSHOT version?
There's a fairly standard way of investigating this kind of problems. In your plugins.sbt
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.2")
Then go sbt dependencyBrowseGraph, this will open your browser and take you to a page where the entire graph of your dependencies including the evicted one can be browsed. Now figure out where the SNAPSHOT is coming from and get rid of it with an exclusion.

sbt value not found addSbtPlugin when installing onejar plugin

I'm trying to install the one-jar sbt plugin but am getting the following error:
sbt/project/plugins/plugins.sbt:5: error: not found: value addSbtPlugin
addSbtPlugin("com.github.retronym" % "sbt-onejar" % "0.6")
Here is the relevant contents of my sbt/build.sbt file:
seq(com.github.retronym.SbtOneJar.oneJarSettings: _*)
name := "dsg_nlp"
version := "0.11"
scalaVersion := "2.9.1"
libraryDependencies ++= Seq( "org.scalatest" %% "scalatest" % "1.6.1" % "test" )
libraryDependencies += "commons-lang" % "commons-lang" % "2.6"
traceLevel in run := 0
fork in run := true
javaOptions in run ++= Seq("-Xmx7G", "-agentlib:hprof=cpu=samples,depth=12", "-server", "-enableassertions")
scalacOptions ++= Seq("-optimize")
mainClass in (one-jar, Compile, packageBin) := Some("Test")
And the contents of my project/plugins/plugins.sbt file:
resolvers += "retronym-releases" at "http://retronym.github.com/repo/releases"
resolvers += "retronym-snapshots" at "http://retronym.github.com/repo/snapshots"
addSbtPlugin("com.github.retronym" % "sbt-onejar" % "0.6")
I would suggest the following changes to the code above:
Make sure you have only one setting per line. So split
libraryDependencies ++= Seq( "org.scalatest" %% "scalatest" % "1.6.1" % "test" )
libraryDependencies += "commons-lang" % "commons-lang" % "2.6"
into two lines.
The last line should read
mainClass in oneJar := Some("Test")
if you want to use another mainClass for the oneJar-Plugin. If it's the same as in the compile scope. You may as well write this as
mainClass in Compile := Some("Test")
but do not specifiy both.
Your project directory structure should look like this:
Project-Root /
|-- build.sbt
|-- project/plugins.sbt
the actual names of the sbt-files don't matter they just have to end in .sbt.