heroku - dependency issue causing Scala Play build to fail on heroku - scala

I'm a bit of newbie to the Scala and the Play framework (2.6.x). See git push heroku master failure screenshot below.
I'm requiring the jsoup dependency in build.sbt (the first one):
libraryDependencies += "org.jsoup" % "jsoup" % "1.11.3"
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.2" % Test
And using it in my controller:
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
...
val res = scala.io.Source.fromURL(data.url)("ISO-8859-1").mkString
val s = Jsoup.parse(res).title
In addition I attempted to use it as an unmanaged dependency by adding it to the lib/ folder, though I still get the same Heroku error.
Interestingly, the app works OK and without errors locally. Is there something I'm missing? Thanks.
Edit:
Beginning of build log:
Failure:

My guess is, that you created Play project from a template. Initial template contains both build.sbt but also gradle build (build.gradle, gradlew, gradlew.bat. Locally, you use sbt for compilation. However, Heroku picks up Gradle build.
Problem: You added the dependency only to build.sbt, but not into gradle.build file.
If you do not really need Gradle, than I suggest to delete Gradle build files from your repository and try to push again.
If you want to keep Heroku using Gradle, than you have to maintain both types of build files.
There also probably is a way how to instruct Heroku to use sbt as preferred choice.

Related

sbt assembly, including my jar

I want to build a 'fat' jar of my code. I understand how to do this mostly but all the examples I have use the idea that the jar is not local and I am not sure how to include into my assembled jar another JAR that I built that the scala code uses. Like what folder does this JAR I have to include reside in?
Normally when I run my current code as a test using spark-shell it looks like this:
spark-shell --jars magellan_2.11-1.0.6-SNAPSHOT.jar -i st_magellan_abby2.scala
(the jar file is right in the same path as the .scala file)
So now I want to build a build.sbt file that does the same and includes that SNAPSHOT.jar file?
name := "PSGApp"
version := "1.0"
scalaVersion := "2.11.8"
resolvers += "Spark Packages Repo" at "http://dl.bintray.com/spark-packages/maven"
//provided means don't included it is there. already on cluster?
libraryDependencies ++= Seq(
"org.apache.spark" %% "spark-core" % "2.2.0" % "provided",
"org.apache.spark" %% "spark-sql" % "2.2.0" % "provided",
"org.apache.spark" %% "spark-streaming" % "2.2.0" % "provided",
//add magellan here somehow?
)
So where would I put the jar in the SBT project folder structure so it gets picked up when I run sbt assembly? Is that in the main/resources folder? Which the reference manual says is where 'files to include in the main jar' go?
What would I put in the libraryDependencies here so it knows to add that specific jar and not go out into the internet to get it?
One last thing, I was also doing some imports in my test code that doesn't seem to fly now that I put this code in an object with a def main attached to it.
I had things like:
import sqlContext.implicits._ which was right in the code above where it was about to be used like so:
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
import sqlContext.implicits._
import org.apache.spark.sql.functions.udf
val distance =udf {(a: Point, b: Point) =>
a.withinCircle(b, .001f); //current radius set to .0001
}
I am not sure can I just keep these imports inside the def main? or do I have to move them elsewhere somehow? (Still learning scala and wrangling the scoping I guess).
One way is to build your fat jar using the assembly plugin (https://github.com/sbt/sbt-assembly) locally and publishLocal to store the resulting jar into your local ivy2 cache
This will make it available for inclusion in your other project based on build.sbt settings in this project, eg:
name := "My Project"
organization := "org.me"
version := "0.1-SNAPSHOT"
Will be locally available as "org.me" %% "my-project" % "0.1-SNAPSHOT"
SBT will search local cache before trying to download from external repo.
However, this is considered bad practise, because only final project should ever be a fat-jar. You should never include one as dependency (many headaches).
There is no reason to make project magellan a fat-jar if library is included in PGapp. Just publishLocal without assembly
Another way is to make projects dependant on each other as code, not library.
lazy val projMagellan = RootProject("../magellan")
lazy val projPSGApp = project.in(file(".")).dependsOn(projMagellan)
This makes compilation in projPSGApp tigger compilation in projMagellan.
It depends on your use case though.
Just don't get in a situation where you have to manage your .jar manually
The other question:
import sqlContext.implicits._ should always be included in the scope where dataframe actions are required, so you shouldn't put that import near the other ones in the header
Update
Based on discussion in comments, my advise would be:
Get the magellan repo
git clone git#github.com:harsha2010/magellan.git
Create a branch to work on, eg.
git checkout -b new-stuff
Change the code you want
Then update the versioning number, eg.
version := "1.0.7-SNAPSHOT"
Publish locally
sbt publishLocal
You'll see something like (after a while):
[info] published ivy to /Users/tomlous/.ivy2/local/harsha2010/magellan_2.11/1.0.7-SNAPSHOT/ivys/ivy.xml
Go to your other project
Change build.sbt to include
"harsha2010" %% "magellan" % "1.0.7-SNAPSHOT" in your libraryDependencies
Now you have a good (temp) reference to your library.
Your PSGApp should be build as an fat jar assembly to pass to Spark
sbt clean assembly
This will pull in the custom build jar
If the change in the magellan project is usefull for the rest of the world, you should push your changes and create a pull request, so that in the future you can just include the latest build of this library

Using SORM with Play Framework 2.3.8

I am going through the Video introduction to Play Framework and, but I am stuck creating a DB object with SORM because the import fails.
I tried to add the dependencies in plugins.sbt, and relaunched activator, but it seems that activator cannot find the dependencies and I get and I get an unresolved error:
addSbtPlugin("org.sorm-framework" % "sorm" % "0.3.14")
addSbtPlugin("com.h2database" % "h2" % "1.4.181")
I got the versions from the Yvis repository. I also tried other versions with no better luck.
should be add as
libraryDependencies += "org.sorm-framework" % "sorm" % "0.3.16"
in build.sbt,
but not as
addSbtPlugin("org.sorm-framework" % "sorm" % "0.3.14")
in project/plugins.sbt
good answer by jilen; also, it can be a good idea to re-run sbt after changing the build.sbt, e.g. (in project root dir):
$ sbt
....
$ compile
...
$ eclipse
(the last two apply to Eclipse users more - and then restart Eclipse to make sure the changes are picked up (Refresh/Clean may not be enough)).

How do I resolve my own test artifacts in SBT?

One of my projects will provide a jar package supposed to be used for unit testing in several other projects. So far I managed to make sbt produce a objects-commons_2.10-0.1-SNAPSHOT-test.jar and have it published in my repository.
However, I can't find a way to tell sbt to use that artifact with the testing scope in other projects.
Adding the following dependencies in my build.scala will not get the test artifact loaded.
"com.company" %% "objects-commons" % "0.1-SNAPSHOT",
"com.company" %% "objects-commons" % "0.1-SNAPSHOT-test" % "test",
What I need is to use the default .jar file as compile and runtime dependency and the -test.jar as dependency in my test scope. But somehow sbt never tries to resolve the test jar.
How to use test artifacts
To enable publishing the test artifact when the main artifact is published you need to add to your build.sbt of the library:
publishArtifact in (Test, packageBin) := true
Publish your artifact. There should be at least two JARs: objects-commons_2.10.jar and objects-commons_2.10-test.jar.
To use the library at runtime and the test library at test scope add the following lines to build.sbt of the main application:
libraryDependencies ++= Seq("com.company" % "objects-commons_2.10" % "0.1-SNAPSHOT"
, "com.company" % "objects-commons_2.10" % "0.1-SNAPSHOT" % "test" classifier "tests" //for SBT 12: classifier test (not tests with s)
)
The first entry loads the the runtime libraries and the second entry forces that the "tests" artifact is only available in the test scope.
I created an example project:
git clone git#github.com:schleichardt/stackoverflow-answers.git --branch so15290881-how-do-i-resolve-my-own-test-artifacts-in-sbt
Or you can view the example directly in github.
Your problem is that sbt thinks that your two jars are the same artifact, but with different versions. It takes the "latest", which is 0.1-SNAPSHOT, and ignores the 0.1-SNAPSHOT-test. This is the same behaviour as you would see if, for instance you have 0.1-SNAPSHOT and 0.2-SNAPSHOT.
I don't know what is in these two jars, but if you want them both to be on the classpath, which is what you seem to want to do, then you'll need to change the name of the test artifact to objects-commons-test, as Kazuhiro suggested. It seems that this should be easy enough for you, since you're already putting it in the repo yourself.
It will work fine if you change the name like this.
"com.company" %% "objects-commons" % "0.1-SNAPSHOT",
"com.company" %% "objects-commons-test" % "0.1-SNAPSHOT" % "test",

How can IntelliJ find remote dependencies?

I added the Mailer plugin to my Play Framework 2 project. It compiles and works fine, but IntelliJ can't resolve any of its classes. I would normally just add the jar as a module in my IntelliJ project settings, but I don't have a jar. As far as I understand, the plugin is automatically being pulled from some repository. So how do I make IntelliJ aware of it?
I added this to conf/play.plugins
1500:com.typesafe.plugin.CommonsMailerPlugin
And this as a dependency in project/build.scala
"com.typesafe" %% "play-plugins-mailer" % "2.0.4"
I resolve problems like this with the sbt-idea SBT plugin. Just add this to your project/plugins.sbt file:
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0")
Then, whenever you change your project dependencies, run sbt idea and your IntelliJ project will be updated.
I had to delete the reference to com.github.mpeltonen in my plugins.sbt file first. Then as Bill said, I needed to run play idea. If I tried to run play idea without deleting the reference I got this exception:
java.lang.NoSuchMethodError: org.sbtidea.SbtIdeaPlugin$.ideaSettings()Lscala/collection/Seq;

When does a SBT package get downloaded/built?

I want to use http://dispatch.databinder.net/Dispatch.html .
The site indicates I must add this to project/plugins.sbt:
libraryDependencies += "net.databinder.dispatch" %% "core" % "0.9.1"
which I did. I then restarted the play console and compiled.
Importing doesnt work:
import dispatch._
Guess I have been silly, but then I never used a build system when using Java.
How must I trigger the process that downloads/builds the package? Where are the jars (or equivalent) stored; can I reuse them? When is the package available for use by the Play application?
It doesn't say you should add it to project/plugins.sbt. That is the wrong place. It says to add to the build.sbt file, on the root of your project. Being a Play project, project/Build.scala might be more appropriate -- I don't know if it will pick up settings from build.sbt or not.
To add the dependency in your Build.scala:
val appDependencies = Seq(
"net.databinder.dispatch" %% "core" % "0.9.1"
)
You probably need to run sbt update.
From the sbt Command Line Reference:
update Resolves and retrieves external dependencies as described in library dependencies.