Scala Play and Multi Project SBT Builds - scala

I created a scala play project like this
activator new foo play-event-sourcing-starter
the project was generated successfully and I can go inside and easily compile and run the app.
However what I want is that I should have a multi project sbt build. I googled and found this https://www.playframework.com/documentation/2.5.x/SBTSubProjects
But this is not the same as what I want because here they have play as the root project. whereas what I want is that I have an empty root project with a build.sbt file and then multiple "peer" projects. One of them is play.
So I changed the steps to
mkdir -p LearnPlay/project
cd LearnPlay
activator new foo play-event-sourcing-starter
Now I went inside foo and moved the build.sbt to the LearnPlay directory. I also moved the build.properties and plugins.sbt files into LearnPlay/project folder.
I edited the build.sbt file so that the root project becomes
lazy val root = (project in file("foo")).enablePlugins(PlayScala)
However now sbt cannot compile the project anymore and it cannot find any of the play framework dependencies.
sbt.ResolveException: unresolved dependency: com.typesafe.play#play-server_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-netty-server_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-logback_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-test_2.10;2.5.9: not found
unresolved dependency: com.typesafe.play#play-omnidoc_2.10;2.5.9: not found
at sbt.IvyActions$.sbt$IvyActions$$resolve(IvyActions.scala:313)
These are the contents of my plugins.sbt file. The resolver is defined correctly so I am not sure why sbt will not be able to find the dependencies after the file was moved from sub-project to root project. it was able to resolve everything when the file was in the project directory of the foo project.
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
// The Play plugin
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.9")
// web plugins
addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.0")

The thing that gave me some ideas what's the problem there is:
unresolved dependency: com.typesafe.play#play-server_2.10;2.5.9: not found
Aren't you surprised, that sbt tries to download the version of play server for Scala 2.10, which doesn't exist for Play 2.5.x, since it's already out of lifecycle.
In my projects this is happening, if I'm not specifying scala version in build.sbt or set it to the 2.10, e.g.
lazy val root = (project in file("foo")).settings(
scalaVersion := "2.10.6",
so, I think you just need to add scalaVersion parameter and set it to something from 2.11.x or 2.12.x

Related

How to exclude classes from compiling when using executing sbt docker:publishLocal?

My build.sbt file has some configuration to use AkkaGrpcPlugin and DockerPlugin because I am publishing the image at docker hub.
lazy val akkaGrpcVersion = "1.0.2"
lazy val protobufVersion = "3.11.4"
enablePlugins(JavaAppPackaging, JavaServerAppPackaging, AkkaGrpcPlugin, DockerPlugin)
akkaGrpcGeneratedLanguages := Seq(AkkaGrpc.Java)
libraryDependencies ++= Seq(
......
)
dockerUsername := Some("felipeogutierrez")
The sbt compile and sbt run work just fine, but the command sbt docker:publishLocal is not working because it tries to find some classes created by the gRPC in the target directory.
[error] /home/felipe/workspace-idea/explore-akka/target/scala-2.12/
akka-grpc/main/org/github/felipegutierrez/explore/akka/rpc/greeting/HelloRequest.java:29:7:
not found: type UnusedPrivateParameter
[error] UnusedPrivateParameter unused) {
[error] ^
these classes belong to the classes at package org.github.felipegutierrez.explore.akka.rpc.greeting and I would like to exclude them from the docker image when I am running sbt docker:publishLocal. I tried this solution but it didn't work. Or find some solution to make this work.
The problem was that I generated the Java files using AkkaGrpcPlugin and they were placed on the target directory of my project. So the docker compiler could not see it. I removed the AkkaGrpcPlugin and the akkaGrpcGeneratedLanguages := Seq(AkkaGrpc.Java) from the build.sbt and installed the protobuf compiler to generate the Java files by myself.
sudo apt install protobuf-compiler
protoc --java_out=main/java main/protobuf/helloworld.proto
Then the files are now generated on the src directory and Docker can see them. So, I don't have to exclude the files anymore in the build.sbt.

sbt: set the base-directory of a remote RootProject

Disclaimer: I am new to sbt and Scala so I might be missing obvious things.
My objective here is to use the Scala compiler as a library from my main project. I was initially doing that by manually placing the scala jars in a libs directory in my project and then including that dir in my classpath. Note that at the time I wasn't using sbt. Now, I want to use sbt and also download the scala sources from github, build the scala jars and then build my project. I start by creating 2 directories: myProject and myProject/project. I then create the following 4 files:
The sbt version file:
// File 1: project/build.properties
sbt.version=0.13.17
The plugins file (not relevant to this question):
// File 2: project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.7.0")
The build.sbt file:
// File 3: build.sbt
lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "me",
scalaVersion := "2.11.12",
version := "0.1.0-SNAPSHOT"
)),
name := "a name"
).dependsOn(ScalaDep)
lazy val ScalaDep = RootProject(uri("https://github.com/scala/scala.git"))
My source file:
// File 4: Test.scala
import scala.tools.nsc.MainClass
object Test extends App {
println("Hello World !")
}
If I run sbt inside myProject then sbt will download the scala sources from github and then try to compile them. The problem is that the base-directory is still myProject. This means that if the scala sbt source files refer to something that is in the scala base-directory they won't find it. For example, the scala/project/VersionUtil.scala file tries to open the scala/versions.properties file that lies in the scala base-directory.
Question: How can I set sbt to download a github repo and then build it using that project's base-directory instead of mine's (by that I mean the base-directory of myProject in the above example) ??
Hope that makes sense.
I would really appreciate any feedback on this.
Thanks in advance !
In the Scala ecosystem you usually depend on binary artifacts (libraries) that are published in Maven or Ivy repositories. Virtually all Scala projects publish binaries, including the compiler. So all you have to do is add the line below to your project settings:
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value
dependsOn is used for dependencies between sub-projects in the same build.
For browsing sources you could use an IDE. IntelliJ IDEA can readily import Sbt projects and download/attach sources for library dependencies. Eclipse has an Sbt plugin that does the same. Ensime also, etc. Or just git clone the repository.

How to add a github java dependency in sbt config?

I've added this code to my Build.scala.
lazy val root = Project("root", file(".")) dependsOn(jbcrypt)
lazy val jbcrypt = RootProject(uri("https://github.com/jeremyh/jBCrypt.git"))
But sbt fails with the error:
[error] (root/*:update) sbt.ResolveException: unresolved dependency: default#jbcrypt_2.11;0.1-SNAPSHOT: not found
How to tell sbt that it is Java not Scala?
How to reference to a specific branch or tag?
Thank you.
Building a project from source is only possible if the referenced project is a sbt project. sbt doesn't know of all the different build systems out there, so how is it supposed to know how to build a non sbt project?
It is possible to add support for other build systems through a sbt plugin but this may be a lot of work.
Your referenced project is a simple Maven project, which means that you can easily create a sbt project from it. Just fork the repo and create a build.sbt with the following content:
scalaVersion := "2.11.5"
projectDependencies += "junit" % "junit" % "3.8.1" % "test"
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (isSnapshot.value) Some("snapshots" at nexus + "content/repositories/snapshots")
else Some("releases" at nexus + "service/local/staging/deploy/maven2")
}
This is the minimal code that was necessary to get it up and running. sbt seems to require that a publish repo is specified, it also seems to require an explicit Scala version. The dependency is already specified by your linked Maven project.
Of course, you know need to change the URI of RootProject to point to the location of your fork.
To your second question: You can reference a commit/tag/branch by appending it to the URI, separated with a # sign:
uri("git://github.com/your/repo#<commit-hash/tag/branch>")

Installing sbteclipse

i have problems top use sbteclipse
What I have done:
went to my global sbt folder.
created a plugins folder
created the file plugins.sbt with addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
went to my eclipse project and created a build.sbt file
it contains:
name := "foo"
version := "1.0"
scalaVersion := "2.9.2"
libraryDependencies += "net.java.dev.jna" % "jna" % "3.4.0"
I am selecting the project folder in my cmd. and type sbt eclipse
But I always get the following error
[error] Not a valid command: eclipse (similar: help, alias)
[error] Not a valid project ID: eclipse
[error] Expected ':'
[error] Not a valid key: eclipse (similar: deliver, licenses, clean)
[error] eclipse
[error] ^
ps: I am using Windows. I am also using sbt 0.12
Your global sbt folder is at %USERPROFILE%\.sbt (C:\Users\<username>\.sbt most likely). So your plugins should be defined at %USERPROFILE%\.sbt\plugins\plugins.sbt
Failing this you can add it to your project directly. Add the file path is <project_root>\project\plugins.sbt. If the project directory doesn't exist you will need to create it.
I think that I might have found a solution. First, the default directory checked for plugins configuration is 'USER_HOME/.sbt/plugins' and NOT 'USER_HOME/.sbt/0.13/plugins'.
Secondly, the sbt version specified seems to matter. In 'PROJECT_HOME/project/build.properties', there's an 'sbt.version' property. If the version of sbt specified in this file is different from the actually installed version of sbt, there's likely to be an issue. I think I was affected more so by this because I'm using an Activator template and it already had 'sbt.version' specified in this 'build.properties' file.
While nosing around, I came across this
"Support for plugin configuration in project/plugins/ has been removed. It was deprecated since 0.11.2" from sbt website at http://www.scala-sbt.org/0.13.0/docs/Community/ChangeSummary_0.13.0.html. I still see a lot of guys pointing that it should be configured in 'PROJECT_HOME/projects/plugins.sbt'. I think this is very confusing.
I had similar a issue and answered to a similar question.
I tried "everything" and, eventually, I just had to update my sbt from 0.13.1 to 0.13.9.

How to inform SBT to consume specific scala version for plugins?

Now I somehow messed up my global sbt plugins (~/.sbt/plugins/build.sbt). They were always fine retrieved against Scala 2.9.1 which seems to be the version that sbt 0.11.3 wants, and all the plugins (sbt-gpg-plugin, sbt-idea-plugin) are published against 2.9.1.
Now whatever I do, it persistently tries to find them built against 2.9.2:
[warn] Note: Some unresolved dependencies have extra attributes. Check that these dependencies exist with the requested attributes.
[warn] com.github.mpeltonen:sbt-idea:1.0.0 (sbtVersion=0.11.3, scalaVersion=2.9.2)
[warn] com.jsuereth:xsbt-gpg-plugin:0.6 (sbtVersion=0.11.3, scalaVersion=2.9.2)
...
[error] {file:...}default-50be6e/*:update: sbt.ResolveException: unresolved dependency: com.github.mpeltonen#sbt-idea;1.0.0: not found
How can I fix this, so sbt retrieves the plugins for Scala 2.9.1 as before?
For the sake of completeness, this is how my files look after the suggestions:
// project-home/build.sbt
scalaVersion := "2.9.2"
...
 
// project-home/project/plugins.sbt
resolvers += "less is" at "http://repo.lessis.me"
addSbtPlugin( "me.lessis" % "ls-sbt" % "0.1.1" )
scalaVersion := "2.9.1" // "just in case it helps"
 
// ~/.sbt/plugins/build.sbt
scalaVersion := "2.9.1" // "just in case it helps"
resolvers += "sbt-idea-repo" at "http://mpeltonen.github.com/maven/"
resolvers += Resolver.url( "sbt-plugin-releases", url( "http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases" ))( Resolver.ivyStylePatterns )
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.0.0")
addSbtPlugin( "com.jsuereth" % "xsbt-gpg-plugin" % "0.6" )
What is even worse, the problem persists, even after I removed ~/.sbt/plugins/build.sbt. So there are no more references (at least visible to me) to either sbt-idea or xsbt-gpg-plugin. Still I cannot compile any project any more, because sbt still tries to find those two plugins. Epic fail.
You could provide the Scala version of plugin. I didn't use ~/.sbt/, but I think it will works too.
The following is my project configuration using Scala 2.9.2 as my project compiler, and using some pluign that are compiled from Scala 2.9.1. Since Scala 2.9.1 and Scala 2.9.2 is binary compatible, I don't encounter any problem yet.
// MyProject/build.sbt
name := "MyProject"
version := "0.1"
scalaVersion := "2.9.2"
The following is plugin configuration:
// File: MyProject/project/plugins.sbt
import sbt._
import Defaults._
resolvers += Resolver.url("sbt-plugin-releases",
new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases/"))(
Resolver.ivyStylePatterns)
// Resolved to:
//
// http://..../com.untyped/sbt-less/scala_2.9.1/sbt_0.11.3/0.4/jars/sbt-less.jar
//
libraryDependencies += sbtPluginExtra(
m = "com.untyped" % "sbt-less" % "0.4", // Plugin module name and version
sbtV = "0.11.3", // SBT version
scalaV = "2.9.1" // Scala version compiled the plugin
)
Some references:
SBT plugins are versioned to the scala version they were built with.
You're not the only one... Again, no answers.
And another case study, this may have answers.
A possibly relevant quote? " Remember to also remove the project/plugins -directory, because if the directory exists, project/plugins.sbt is ignored."
You can also specify sbtVersion and scalaVersion. There is an overloaded addSbtPlugin -
addSbtPlugin(dependency : sbt.ModuleID, sbtVersion : scala.Predef.String, scalaVersion : scala.Predef.String)
Ok, I went back to all the events that could have led to this. And because I found that other projects were still building, I started to understand that the problem with this particular project B was that it appeared that the two plugins were regular dependencies of project A which it depended on.
When sbt refused to acknowledge the presence of the GPG plugin which I uncommented in ~/.sbt/plugins/build.sbt, I renamed that file to ~/.sbt/plugins.sbt, and back again. That intermediate position somehow meant that the plugins were not any more plugins (despite being added as addSbtPlugin), but regular dependencies for the project A when I publish that.
I tried to find that messed up A's ivy.xml across all known Ivy2 cache directories. It was not possible to find the one that sbt was obviously seeing.
Long story, short answer: I had to bump the version of A artificially to get rid of the wrong ivy.xml cached somewhere in a hidden place. That forced sbt to re-find A with the correct ivy.xml (not depending any more on the plugins).
Now I'm just worried what happens if I put my global plugin settings into place :-#
Future advise: Never ever ever put anything into ~/.sbt/plugins.sbt. If you need sbt to understand that you changed ~/.sbt/plugins/build.sbt: Reboot your computer. Don't touch any file.