How to copy local cached jars to a folder via SBT? - scala

I want to copy all the jars specified in the libraryDependencies to be copy to a folder in a task.
For example, I have the following dependencies defined for the project.
libraryDependencies ++= Seq(
"org.neo4j" % "neo4j" % neo4j_version,
"org.scala-lang.modules" %% "scala-java8-compat" % "0.8.0",
"org.scala-lang" %% "scala-pickling" % "0.9.1",
"org.neo4j.test" % "neo4j-harness" % neo4j_version % "test",
"org.neo4j.driver" % "neo4j-java-driver" % "1.0.4" % "test"
)
Now I want to create a task so that every time I run the task, it will copy the jars in the dependencies to a folder.
I know I can manually specify the absolute paths for the jars to copy. I want a task that can automatically derive the paths to the jars. So later when I add a new dependency, I do not need to find the path in .ivy cache again.
Thanks.

You can use managedClasspath to figure this out. See below for an example.
val copyJarsTask = TaskKey[Unit]("copy-jars", "Copys jars")
libraryDependencies ++= Seq(
"org.scala-lang" %% "scala-pickling" % "0.9.1"
)
copyJarsTask := {
val folder = new File("my-jars")
(managedClasspath in Compile).value.files.foreach { f =>
IO.copyFile(f, folder / f.getName)
}
}

Another option is to use the sbt-native-packager plugin with the Java Archetype and run:
sbt stage
The result will be that all your application dependencies and the JAR or the application itself will end up in the target/universal/stage/lib/ directory.

Related

dependency resolution with sbt for continuous integration

I'm an open-source Scala developer who wants to minimize the hassle of dependencies when pushing to GitHub and triggering a check with continuous integration (CircleCI). I have two projects where one (A) is dependent on the other (B). B is under development at the same time (as a snapshot). My project A build.sbt file has a dependency on this (snapshot) version of B and of course all works fine on my local machine. When I push to GitHub, it naturally fails as that snapshot file is not available to CircleCI.
I have generally worked around this by putting the jar file into my lib directory (and removing the dependency from build.sbt). I believe this is known as an unmanaged dependency.
My question is this: is there any way of setting up my lib directory so that CircleCI can resolve the (managed) dependency from the lib directory? I have tried putting the ivy structure into lib starting with the top level com.phasmidsoftware, with b_2.13 under that and under that 1.0.4-SNAPSHOT and so on down. That doesn't work. I've attached the build.sbt for project A (called Numeric).
organization := "com.phasmidsoftware"
name := "Number"
version := "1.0.9"
scalaVersion := "2.13.6"
scalacOptions ++= Seq( "-target:jvm-1.8", "-encoding", "UTF-8", "-unchecked", "-deprecation", "-Ywarn-dead-code", "-Ywarn-value-discard", "-Ywarn-unused" )
val scalaTestVersion = "3.2.3"
libraryDependencies += "org.scalatest" %% "scalatest" % scalaTestVersion % "test"
resolvers += "Typesafe Repository" at "https://repo.typesafe.com/typesafe/releases/"
libraryDependencies ++= Seq(
"com.phasmidsoftware" %% "matchers" % "1.0.4-SNAPSHOT",
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.2.0-M1",
"org.apache.commons" % "commons-math3" % "3.6.1",
"org.slf4j" % "slf4j-api" % "1.7.31",
"ch.qos.logback" % "logback-classic" % "1.2.3" % "test",
"org.scalacheck" %% "scalacheck" % "1.14.1" % "test"
)
The answer described in How can sbt pull dependency artifacts from git? is indeed the right answer.
I will just add a couple of caveats.
Make sure that you use the git protocol in the URI of your git repository (as is shown in the other answer);
The mechanism works by cloning the repository (the branch is defined by ...#branch) but, once you've cloned it, sbt won't fetch if appropriate -- you do have to do that explicitly yourself.
The other thing to keep in mind is that the clone(s) are placed in ~/.sbt/1.0/staging/... where 1.0 is based on the sbt version number.
And, of course, don't forget to remove the reference to the other project if you have it in your libraryDependencies.
Here's the relevant part of my build.sbt file:
lazy val root = (project in file(".")).dependsOn(matchers)
lazy val matchers = RootProject(uri("git://github.com/rchillyard/Matchers#V1_0_5"))

How to attach sources to scala sbt project at Intellij Idea?

I am new at scala. And for start I want to use Intellij 13.1.5 IDE.
However IDE can't attach sources. Here is how it looks for AnyVal:
Search at internet can't find any source.
I tried Attach sources and attach unpacked scala archive. It doesn't work either.
UPDATE:
Here is sbt configuration:
name := "scalatest-selenium"
version := "1.0"
scalaVersion := "2.11.1"
libraryDependencies ++= Seq(
"net.sourceforge.htmlunit" % "htmlunit" % "2.14",
"org.seleniumhq.selenium" % "selenium-java" % "2.42.2",
"org.scalacheck" % "scalacheck_2.10" % "1.11.4" % "test",
"org.scalatest" % "scalatest_2.11" % "2.2.0" % "test"
)
testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-u", "target/test-reports")
How to solve this trouble?
I get rid of this trouble at the following way:
removed the .sbt directory in your Home Folder.
When you run sbt again, the new folder is created in the correct format and the error goes away.

Cannot run jar file created from Scala file

This the code that I have written in Scala.
object Main extends App {
println("Hello World from Scala!")
}
This is my build.sbt.
name := "hello-world"
version := "1.0"
scalaVersion := "2.11.5"
mainClass := Some("Main")
This is the command that I have run to create the jar file.
sbt package
My problem is that a jar file named hello-world_2.11-1.0.jar has been created at target/scala-2.11. But I cannot run the file. It is giving me an error saying NoClassDefFoundError.
What am I doing wrong?
It also says what class is not found. Most likely you aren't including scala-library.jar. You can run scala target/scala-2.11/hello-world_2.11-1.0.jar if you have Scala 2.11 available from the command line or java -cp "<path to scala-library.jar>:target/scala-2.11/hello-world_2.11-1.0.jar" Main (use ; instead of : on Windows).
The procedure depicted proves valid up to the way the jar file is executed. From target/scala-2.11 try running it with
scala hello-world_2.11-1.0.jar
Check whether it is runnable also from the project root folder with sbt run.
To run the jar file(containing scala code) with multiple main classes use following approach
scala -cp "<jar-file>.jar;<other-dependencies>.jar" com.xyz.abc.TestApp
This command will take care of including scala-library.jar in dependency and will also identify TestApp as main class if it has a def main(args:Array[String]) method. Please note that multiple jar files should be separated by semi-colon(";")
We can use sbt-assembly to package and run the application.
First, create or add the plugin to project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9")
The sample build.sbt looks like below:
name := "coursera"
version := "0.1"
scalaVersion := "2.12.10"
mainClass := Some("Main")
val sparkVersion = "3.0.0-preview2"
val playVersion="2.8.1"
val jacksonVersion="2.10.1"
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-library" % scalaVersion.toString(),
"org.apache.spark" %% "spark-streaming" % sparkVersion,
"org.apache.spark" %% "spark-core" % sparkVersion,
"org.apache.spark" %% "spark-sql" % sparkVersion,
"com.typesafe.play" %% "play-json" % playVersion,
// https://mvnrepository.com/artifact/org.apache.spark/spark-streaming-kafka-0-10
"org.apache.spark" %% "spark-streaming-kafka-0-10" % sparkVersion,
// https://mvnrepository.com/artifact/org.mongodb/casbah
"org.mongodb" %% "casbah" % "3.1.1" pomOnly(),
// https://mvnrepository.com/artifact/com.typesafe/config
"com.typesafe" % "config" % "1.2.1"
)
assemblyMergeStrategy in assembly := {
case PathList("META-INF", xs # _*) => MergeStrategy.discard
case x => MergeStrategy.first
}
From console, we can run sbt assembly and the jar file gets created in target/scala-2.12/ path.
sbt assembly will create a fat jar. Here is an excerpt from the documentation :
sbt-assembly is a sbt plugin originally ported from codahale's assembly-sbt, which I'm guessing was inspired by Maven's assembly plugin. The goal is simple: Create a fat JAR of your project with all of its dependencies.

Can't compile 2.2 to 2.3 Migration

I have been fighting with this for the past few hours and I haven't made any headway at all. It seems no matter what I do, I keep getting the same error.
java.lang.NoClassDefFoundError: play/Project$
My build.sbt
name := "appname"
version := "1.0-SNAPSHOT"
libraryDependencies ++= Seq(
jdbc,
anorm,
cache,
filters,
"org.postgresql" % "postgresql" % "9.3-1100-jdbc4",
"org.mindrot" % "jbcrypt" % "0.3m",
"org.webjars" %% "webjars-play" % "2.3.0-2",
"org.webjars" % "foundation" % "5.3.0",
"org.scalaj" %% "scalaj-http" % "0.3.16"
)
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.10.4"
I have also tried this build.sbt
object ApplicationBuild extends Build {
val appName = "appname"
val appVersion = "1.0-SNAPSHOT"
val appDependencies ++= Seq(
jdbc,
anorm,
cache,
filters,
"org.postgresql" % "postgresql" % "9.3-1100-jdbc4",
"org.mindrot" % "jbcrypt" % "0.3m",
"org.webjars" %% "webjars-play" % "2.3.0-2",
"org.webjars" % "foundation" % "5.3.0",
"org.scalaj" %% "scalaj-http" % "0.3.16"
)
val main = Project(appName, file(".")).enablePlugins(play.PlayScala).settings(
scalaVersion := "2.10.4",
version := appVersion,
libraryDependencies ++= appDependencies
)
}
As well as different tweaks and modifications. Always the same error. The build.properties is set to sbt.version=0.13.5
plugins.sbt
logLevel := Level.Debug
// The Typesafe repository
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
// Use the Play sbt plugin for Play projects
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.4")
After running Patrick Mahoney's suggestion and making sure I removed the import.
Errors:
[error] java.lang.NoClassDefFoundError: play/Project$
[error] Use 'last' for the full log.
Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore? q
me#me-desktop:~/Projects/appname$ sbt --version
sbt launcher version 0.13.6
me#me-desktop:~/Projects/appname$ find . | grep -r "play.Project"
me#me-desktop:~/Projects/appname$ find . | grep -r "play/Project"
Try cleaning your build project compiled outputs:
rm -rf project/target
or
$> sbt "reload plugins" clean
(in addition to applying James' answer)
Thanks to James and Patrick, but I found the problem. The problem was in the activator-sbt-echo-play-shim.sbt file in the /project directory.
It contained the following:
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "0.1.1.3")
I created a second blank 2.3.4 app using Activator and it's activator-sbt-echo-play-shim.sbt listed:
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5")
So I updated the one in my project to 1.5 and deleted the idea and eclipse .sbts for good measure and the app was finally able to compile. It auotmatically updated the above to:
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.5.2")
Now I have other, more expected, issues I need to work out (like anorm). But I'm now able to compile it and get those errors to start working them out. I did not think these files were part of the activator/sbt compile, but I guess they were. I thought they were for debugging. But they made the difference and the changes above worked.
Thanks again to everyone for their help.
Make sure you've updated project/build.properties to have sbt version 0.13.5. Then, remove import play.Project._, it's not needed. That should work.

Have sbt put javadocs and sources of dependencies on the class path

When using a managed dependency, I can tell sbt to download the javadocs and sources:
"mygroup" % "mymodule" % "myversion" withJavadoc() withSources()
But these jars don't seem to be on the runtime classpath?
What I would like to do, is access the javadocs and sources from my application. Can I make these jars appear as managed resources, such that I could do
ClassLoader.getSystemClassLoader.getResource("/my/package/MyDependency.scala")
?
You can do this by adding a classifier.
For a given library dependency, add a javadoc or sources classifer:
libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.0.6" classifier "javadoc"
libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.0.6" classifier "sources"
Then, access its contents from the classpath:
val docStream = getClass.getResourceAsStream("""/scalaz/Monad$.html""")
val doc = io.Source.fromInputStream(docStream).mkString
println(doc)
Here's a working example: https://earldouglas.com/ext/stackoverflow.com/questions/22160701/