I'm a newbie on Scala, am trying to use Spark to read from a mysql database. I'm facing a class-not-found exception whatever I do. I tried to connect without Spark, using Squeryl, Scalike, etc. Always the same problem.
Here's one example I tried :
logger.info("Write part")
val dataframe_mysql = spark.sqlContext
.read.format("jdbc")
.option("url", s"jdbc:mysql://${datamart_server}:3306/vol")
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", "company")
.option("user", datamart_user).option("password", datamart_pwd)
.load()
dataframe_mysql.show()
I tried to put the driver classname in a src/main/resources/application.conf:
db.default.driver="com.mysql.jdbc.Driver"
But it didn't help. I've got :
java.sql.SQLException: No suitable driver
I also share the sbt file to show how I add the dependencies :
name := "commercial-api-datamart-feed"
version := "0.1"
scalaVersion := "2.11.6"
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.0"
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.1.3" % Runtime
libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.9.0"
libraryDependencies += "org.apache.spark" %% "spark-core" % "2.3.0"
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.3.0"
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.24" % Runtime
Spark is not mandatory but I think it's better for performance.
How are you running this code? You'll need to pass the MySQL JAR as --jars; something like --jars /path/to/mysql.jar if starting up spark-shell or spark-submit.
If you prefer running a single JAR, you'll need to ensure that the MySQL JAR is embedded as part of your uber JAR. I've never used SBT but you'll need to check whether the final JAR created has the MySQL classes inside it -- if not, use the relevant SBT flags to make that happen.
You have to make sure the mysql dependencies exist on all of the executors. In my environment, I use maven and specify the dependency like this inside of my pom.xml:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>
I then ensure that this dependency is bundled in my application jar (using the maven shade plugin), so that I don't have to place the jar on all of the executors.
Whether you use spark or not to access mysql over jdbc, you need to make sure the mysql-connector is available on your classpath, wherever you are executing mysql queries from.
Related
I'm trying to migrate from anorm to slick, using play 2.4.2, and getting a configuration error:
play.api.Configuration$$anon$1: Configuration error[Cannot connect to database [dethcs]]
at play.api.Configuration$.configError(Configuration.scala:178) ~[play_2.11-2.4.0.jar:2.4.0]
...
Caused by: slick.SlickException: Error getting instance of Slick driver "slick.driver.MySQLDriver"
...
Caused by: java.lang.NoSuchMethodException: slick.driver.MySQLDriver.<init>()
Previous answers I've found on SO have focused on having the right MySQL driver and other dependencies. I believe my build.sbt covers the relevant bases, including:
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.36"
libraryDependencies += "com.typesafe.play" %% "play-slick" % "1.0.1"
libraryDependencies += "com.typesafe.play" %% "play-slick-evolutions" % "1.0.1"
The relevant lines in my application.conf are:
slick.dbs.dethcs.db.driver="com.mysql.jdbc.Driver"
slick.dbs.dethcs.driver="slick.driver.MySQLDriver"
slick.dbs.dethcs.user="redacted"
slick.dbs.dethcs.db.url="jdbc:mysql://localhost/mydb"
slick.dbs.dethcs.password="redacted"
I'd be grateful for any suggestions as to how to fix this -- I'm guessing it's something silly but I've found it very difficult to get documentation and examples that are specific to more recent versions of slick -- and could provide additional info if that would help.
I haven't tried myself, but it looks like you are referencing the MySQLDriver class instead of the corresponding object. Put a trailing $ in it and you should be good to go:
slick.dbs.dethcs.driver="slick.driver.MySQLDriver$"
This appears similar to sbt Configuration vs Ivy configuration, though it doesn't seem like this question is asked:
What is the difference between
libraryDependencies += "com.example" % "foo" % "1.0" % "test"
and
libraryDependencies in Test += "com.example" % "foo" % "1.0"
(And a similar question for IntegrationTest / "it".)
Should I always use SBT configuration, or Ivy configuration? Or does it depend on the particular case?
I have seen the former more often, though it seems that the latter is more consistent with the rest of my build.sbt.
update task and libraryDependencies are a bit odd ones because when you're downloading JARs you probably don't want to download Compile JARs and Test JARs independently or in parallel. For update task to handle all configurations, libraryDependencies needs to handle all configurations too.
libraryDependencies += "com.example" % "foo" % "1.0" % Test
means your project's Test configuration depends on the default configuration of "com.example" % "foo" % "1.0".
libraryDependencies in Test, I don't think would work.
Should I always use SBT configuration, or Ivy configuration? Or does it depend on the particular case?
There are notational differences, but conceptually sbt's configuration and Ivy configuration is the same thing.
I'm using the Play Framework 2.2.3 for my first time and I'm having a lot of trouble importing anorm._ and api.db.DB so I can set up my SQL databases.
My set-up is this:
MainController.scala
import play.api._
import play.api.mvc._
import play.api.db.DB
import anorm._
object MainController extends Controller {...}
application.conf
# db.default.driver=com.mysql.jdbc.Driver
# db.default.url="jdbc:mysql:/usr/local/path/to/database"
build.sbt
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.27"
My first question is whether or not I'm setting up MySQL database connection correctly. The other thing is that when I try to find the import with my IntelliJ, it finds it great. But when I compile in my browser, I get a compilation error: object db is not a member of package play.api. Any tips?
I downloaded both Play 2.2.2 and 2.2.3, and with both I had this problem so version problems are ruled out. I installed from the website, I unzipped the file into my Home folder, and used
play new app
cd app/
play
idea with-sources=yes
for my installation. I honestly just have no idea what's going on.
I have got the same issue and it's resolved by adding: "com.typesafe.play" % "play-iteratees_2.10" % "2.2.3", in my build.scala file.
simply add this to your dependency
<dependency>
<groupId>com.typesafe.play</groupId>
<artifactId>play-jdbc_2.11</artifactId>
<version>2.4.6</version>
</dependency>
Situation:
I want to execute JUnit test cases for my Play! 2.0 application on a Jenkins Server.
To build and test my app on the server I want to use SBT (with command sequence: clean compile test).
Problem:
Regardless of Jenkins, the command play test uses a different classpath than the command java -jar "sbt-launch.jar" test (both commands executed in the root directory of my play project, both commands use the same sbt version 0.12.2). My test cases can be compiled with play test but with java -jar "sbt-launch.jar" test the compiler complains that some JUnit classes (e.g., org.junit.rules.TestWatcher) are missing.
Analysis:
The command show test:full-classpath reveals that the classpathes indeed differ:
play test classpath contains: Attributed(<playhome>\repository\local\junit\junit-dep\4.10\jars\junit-dep.jar)
java -jar "sbt-launch.jar test classpath contains: Attributed(<userhome>\.ivy2\cache\junit\junit-dep\jars\junit-dep-4.8.2.jar)
Question:
Any ideas how to ensure that java -jar "sbt-launch.jar test uses the same classpath as play test?
Build.scala:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "my app"
val appVersion = "1.0-SNAPSHOT"
val appDependencies = Seq(
// Play framework dependencies
javaCore, javaJdbc, javaEbean,
// Add your project dependencies here
"com.typesafe" %% "play-plugins-mailer" % "2.1.0",
"com.feth" %% "play-authenticate" % "0.2.5-SNAPSHOT",
"org.mongodb" % "mongo-java-driver" % "2.10.1",
"com.embedly" % "embedly-api" % "0.1.5",
"org.mockito" % "mockito-all" % "1.9.5",
"org.mongojack" % "mongojack" % "2.0.0-RC5",
"commons-io" % "commons-io" % "2.3"
)
val main = play.Project(appName, appVersion, appDependencies).settings(
resolvers += Resolver.url("play-easymail (release)", url("http://joscha.github.com/play-easymail/repo/releases/"))(Resolver.ivyStylePatterns),
resolvers += Resolver.url("play-easymail (snapshot)", url("http://joscha.github.com/play-easymail/repo/snapshots/"))(Resolver.ivyStylePatterns),
resolvers += Resolver.url("play-authenticate (release)", url("http://joscha.github.com/play-authenticate/repo/releases/"))(Resolver.ivyStylePatterns),
resolvers += Resolver.url("play-authenticate (snapshot)", url("http://joscha.github.com/play-authenticate/repo/snapshots/"))(Resolver.ivyStylePatterns)
)
}
The play script rewires sbt to use a local JUnit file repository in addition to any remote you've used. This is why the download is so large. Ivy, by default, will not copy local files into its local cache, as it assumes they are stable.
SO, what you're seeing is the sbt script which downloaded the file vs. the Play script which has its own local repo that takes priority over the downloaded file.
Now the fun part is around versioning. Ivy has interesting version conflict resolution.
If you paste you look in your target/resolution-cache/reports directory, you may get some insight into the difference between the two commands and why the one junit is chosen over another. My guess is there's a dynamic version range which is looking in the local repository for the play script and not finding the newer version of junit-dep.
I know that the scala swing libraries are present in scala 2.8:
[info] Building project chart 1.0 against Scala 2.8.1
[info] using sbt.DefaultProject with sbt 0.7.4 and Scala 2.7.7
So how come I'm getting this error:
[error] /src/main/scala/Chart.scala:2: value swing is not a member of package scala
[error] import scala.swing.Panel
Is it because SBT is using the wrong version of scala (i.e. 2.7.7)? If so, how do I configure it to use the correct version?
EDIT: Answer
Following Dylan Lacey's answer, I made the following file sbt/project/build/chart.scala:
import sbt._
class SamplesProject(info: ProjectInfo) extends DefaultProject(info)
{
val scalaSwing = "org.scala-lang" % "scala-swing" % "2.8.1"
}
Then I ran: sbt reload update from the shell.
Now things compile!
For sbt 0.11 (and presumably 0.10) then adding the following to build.sbt will do it:
libraryDependencies <+= scalaVersion { "org.scala-lang" % "scala-swing" % _ }
No. The version information reported on line 2 is just the version sbt was built with, it won't effect your build.
Because Swing is a package (Not part of the base classes) I suspect the problem is one of two things. Either:
Your build file doesn't specify that you want to use scala-swing and is getting confused. You can correct this by adding:
val scalaSwing = "org.scala-lang" % "scala-swing" % "packageVersion"
in your /project/build/projectName.scala (Thanks Janx!)
You've added the dependancy but have not yet downloaded the required package. To do this, you need sbt to reload your project definition and then get all required packages:
sbt reload update
If you need option 1, you'll likely need to also do option 2.
If neither of these work, you may have confused your local respository horribly. That can be fixed with a sbt clear-lib, but you will then re-download all your packages.