I am connecting to a postgres database with scala (2.9.2).
First time I make a SELECT (by running the code with 'run' in the sbt terminal in IntelliJ) it works well, but if I do 'run' again in the sbt shell I get an error that claims:
[error] (run-main) java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost/db
java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost/db
at java.sql.DriverManager.getConnection(DriverManager.java:602)
at java.sql.DriverManager.getConnection(DriverManager.java:185)
at SequenceGenerator$.connect(Validator.scala:50)
at SequenceGenerator$.generate(Validator.scala:54)
at Main$.main(Validator.scala:32)
at Main.main(Validator.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
I have installed the postgres connector through sbt, this row in my build.sbt file.
libraryDependencies += "postgresql" % "postgresql" % "9.1-901.jdbc4"
This is my code for making a SELECT:
object SequenceGenerator{
def connect() = {
DriverManager.getConnection("jdbc:postgresql://localhost/db","user", "pass")
}
def generate() = {
val db = connect()
val st = db.createStatement
val res = st.executeQuery("SELECT value from table LIMIT 2")
while( res.next) {
println(res.getString("value"))
}
}
}
We had to add this to our integration tests startup to get around the same issue with the mysql jdbc driver:
Class.forName("com.mysql.jdbc.Driver").newInstance
I'm not sure why SBT unloads the driver, but something like this would probably work for you:
object SequenceGenerator{
//Use whatever your jdbc driver class should be here, I'm just guessing
Class.forName("org.postgresql.Driver").newInstance
def connect() = {
DriverManager.getConnection("jdbc:postgresql://localhost/db","user", "pass")
}
def generate() = {
val db = connect()
val st = db.createStatement
val res = st.executeQuery("SELECT value from table LIMIT 2")
while( res.next) {
println(res.getString("value"))
}
}
}
The main problem is that you are trying to load the driver using the old DriverManager approach. You have to use Database.forDataSource approach in slick and use a proper Database Pool like C3P0.
I think this is a classloading issue between Slick, SBT and the Driver.
Obviously make sure that the driver is in the classpath.
Related
I'm trying to enable in-memory mongodb in testing, I am using simplyscala to do the work.
class controllerSpec extends PlaySpec with GuiceOneAppPerTest with Injecting with BeforeAndAfterAll with MongoEmbedDatabase{
//declares a variable which will hold the reference to running mongoDB Instance
var mongoInstance: MongodProps = null
// Start In-memory Mongo instance in before statement
override def beforeAll(): Unit =
try{
val rnd = new scala.util.Random
val range = 12000 to 36000
val portNum = range(rnd.nextInt(range length))
mongoInstance = mongoStart(portNum) } //Try starting mongo on random port number
catch { case ex:Exception => } // Handle exception In case local mongo is running//code to run before all tests starts
override def afterAll(): Unit = mongoStop(mongoInstance)
However I have error :
[info] controllerSpec:
java.lang.NoSuchFieldException: handle
at java.base/java.lang.Class.getDeclaredField(Class.java:2411)
at de.flapdoodle.embed.process.runtime.Processes.windowsProcessId(Processes.java:109)
at de.flapdoodle.embed.process.runtime.Processes.access$200(Processes.java:51)
at de.flapdoodle.embed.process.runtime.Processes$PidHelper$2.getPid(Processes.java:209)
| => rat de.flapdoodle.embed.process.runtime.Processes.processId(Processes.java:72)
at de.flapdoodle.embed.process.runtime.ProcessControl.<init>(ProcessControl.java:64)
at de.flapdoodle.embed.process.runtime.ProcessControl.start(ProcessControl.java:205)
at de.flapdoodle.embed.process.runtime.AbstractProcess.<init>(AbstractProcess.java:98)
at de.flapdoodle.embed.mongo.AbstractMongoProcess.<init>(AbstractMongoProcess.java:53)
at de.flapdoodle.embed.mongo.MongodProcess.<init>(MongodProcess.java:50)
at de.flapdoodle.embed.mongo.MongodExecutable.start(MongodExecutable.java:44)
at de.flapdoodle.embed.mongo.MongodExecutable.start(MongodExecutable.java:34)
at de.flapdoodle.embed.process.runtime.Executable.start(Executable.java:101)
at com.github.simplyscala.MongoEmbedDatabase.mongoStart(MongoEmbedDatabase.scala:26)
at com.github.simplyscala.MongoEmbedDatabase.mongoStart$(MongoEmbedDatabase.scala:22)
at controllersSpec.ssmServiceSpec.ssmControllerSpec.mongoStart(ssmControllerSpec.scala:22)
at controllersSpec.ssmServiceSpec.ssmControllerSpec.beforeAll(ssmControllerSpec.scala:32)
at org.scalatest.BeforeAndAfterAll.liftedTree1$1(BeforeAndAfterAll.scala:212)
at org.scalatest.BeforeAndAfterAll.run(BeforeAndAfterAll.scala:210)
at org.scalatest.BeforeAndAfterAll.run$(BeforeAndAfterAll.scala:208)
at controllersSpec.ssmServiceSpec.ssmControllerSpec.run(ssmControllerSpec.scala:22)
at org.scalatest.tools.Framework.org$scalatest$tools$Framework$$runSuite(Framework.scala:317)
at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:510)
at sbt.ForkMain$Run.lambda$runTest$1(ForkMain.java:304)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Does it have something to do with the BeforeAndAfterAll? Please tell me if I did anything wrong thank you.
Upgrade the version of the Embedded MongoDB dependency test driver to 3.4.3
Gradle:
testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo:3.4.3'
pom.xml
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>3.4.3</version> <!-- make this version a property instead-->
<scope>test</scope>
</dependency>
I am new with scala and I face the following problem.
import akka.actor.Actor
import akka.actor.Props
import akka.event.Logging
import akka.actor.ActorSystem
object test extends App {
val system = ActorSystem("hello-world")
val myActor = system.actorOf(Props[MyActor], "myactor2")
}
class MyActor extends Actor {
val log = Logging(context.system, this)
val props1 = Props[MyActor]
def receive = {
case "test" => log.info("received test")
case _ => log.info("received unknown message")
}
val child = context.actorOf(Props[MyActor], name = "myChild")
}
So when I run it, I receive
[error] (run-main-1) java.lang.RuntimeException: While trying to load extension [akka.actor.InstanceCountingExtension]
java.lang.RuntimeException: While trying to load extension [akka.actor.InstanceCountingExtension]
at akka.actor.ActorSystemImpl.$anonfun$loadExtensions$1(ActorSystem.scala:906)
at scala.collection.Iterator.foreach(Iterator.scala:929)
at scala.collection.Iterator.foreach$(Iterator.scala:929)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1406)
at scala.collection.IterableLike.foreach(IterableLike.scala:71)
...
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
Caused by: java.lang.ClassNotFoundException: akka.actor.InstanceCountingExtension
at java.lang.ClassLoader.findClass(ClassLoader.java:530)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[trace] Stack trace suppressed: run last compile:run for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
at scala.sys.package$.error(package.scala:27)
The problem is the ActorSystem, but i can't understand why. When I delete the system an myActor everything works fine. It even works when i make it only val system = ActorSystem but then system couldn't create actorOf.
You probably have this setting in your application.conf
akka.library-extensions += "akka.actor.InstanceCountingExtension"
This is an actor system extension used by akka-actor-tests to make assertions about the number of actor instances currently running in a system.
I don't think this is intended as an extension to be used by applications, it is more like a test utility.
However, depending on what you need:
if you just want to run your program, just delete the configuration line above, and all should be fine
if you need the extension for some reason, import akka-actor-tests test jar, or alternatively make sure you got this class available at runtime.
The problem was with the test folder. When I removed the test it started working.
I want to create an set task which creates a database schema with slick. For that, I have a task object like the following in my project:
object CreateSchema {
val instance = Database.forConfig("localDb")
def main(args: Array[String]) {
val createFuture = instance.run(createActions)
...
Await.ready(createFuture, Duration.Inf)
}
}
and in my build.sbt I define a task:
lazy val createSchema = taskKey[Unit]("CREATE database schema")
fullRunTask(createSchema, Runtime, "sbt.CreateSchema")
which gets executed as expected when I run sbt createSchema from the command line.
However, the problem is that application.conf doesn't seem to get taken into account (I've also tried different scopes like Compile or Test). As a result, the task fails due to com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'localDb'.
How can I fix this so the configuration is available?
I found a lot of questions here that deal with using the application.conf inside the build.sbt itself, but that is not what I need.
I have setup a little demo using SBT 0.13.8 and Slick 3.0.0, which is working as expected. (And even without modifying "-Dconfig.resource".)
Files
./build.sbt
name := "SO_20150915"
version := "1.0"
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.3.0" withSources() withJavadoc(),
"com.typesafe.slick" %% "slick" % "3.0.0",
"org.slf4j" % "slf4j-nop" % "1.6.4",
"com.h2database" % "h2" % "1.3.175"
)
lazy val createSchema = taskKey[Unit]("CREATE database schema")
fullRunTask(createSchema, Runtime, "somefun.CallMe")
./project/build.properties
sbt.version = 0.13.8
./src/main/resources/reference.conf
hello {
world = "buuh."
}
h2mem1 = {
url = "jdbc:h2:mem:test1"
driver = org.h2.Driver
connectionPool = disabled
keepAliveConnection = true
}
./src/main/scala/somefun/CallMe.scala
package somefun
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import slick.driver.H2Driver.api._
/**
* SO_20150915
* Created by martin on 15.09.15.
*/
object CallMe {
def main(args: Array[String]) : Unit = {
println("Hello")
val settings = new Settings()
println(s"Settings read from hello.world: ${settings.hw}" )
val db = Database.forConfig("h2mem1")
try {
// ...
println("Do something with your database.")
} finally db.close
}
}
class Settings(val config: Config) {
// This verifies that the Config is sane and has our
// reference config. Importantly, we specify the "di3"
// path so we only validate settings that belong to this
// library. Otherwise, we might throw mistaken errors about
// settings we know nothing about.
config.checkValid(ConfigFactory.defaultReference(), "hello")
// This uses the standard default Config, if none is provided,
// which simplifies apps willing to use the defaults
def this() {
this(ConfigFactory.load())
}
val hw = config.getString("hello.world")
}
Result
If running sbt createSchema from Console I obtain the output
[info] Loading project definition from /home/.../SO_20150915/project
[info] Set current project to SO_20150915 (in build file:/home/.../SO_20150915/)
[info] Running somefun.CallMe
Hello
Settings read from hello.world: buuh.
Do something with your database.
[success] Total time: 1 s, completed 15.09.2015 10:42:20
Ideas
Please verify that this unmodified demo project also works for you.
Then try changing SBT version in the demo project and see if that changes something.
Alternatively, recheck your project setup and try to use a higher version of SBT.
Answer
So, even if your code resides in your src-folder, it is called from within SBT. That means, you are trying to load your application.conf from within the classpath context of SBT.
Slick uses Typesafe Config internally. (So the approach below (described in background) is not applicable, as you can not modify the Config loading mechanism itself).
Instead try the set the path to your application.conf explicitly via config.resource, see typesafe config docu (search for config.resource)
Option 1
Either set config.resource (via -Dconfig.resource=...) before starting sbt
Option 2
Or from within build.sbt as Scala code
sys.props("config.resource") = "./src/main/resources/application.conf"
Option 3
Or create a Task in SBT via
lazy val configPath = TaskKey[Unit]("configPath", "Set path for application.conf")
and add
configPath := Def.task {
sys.props("config.resource") = "./src/main/resources/application.conf"
}
to your sequence of settings.
Please let me know, if that worked.
Background information
Recently, I was writing a custom plugin for SBT, where I also tried to access a reference.conf as well. Unfortunately, I was not able to access any of .conf placed within project-subfolder using the default ClassLoader.
In the end I created a testenvironment.conf in project folder and used the following code to load the (typesafe) config:
def getConfig: Config = {
val classLoader = new java.net.URLClassLoader( Array( new File("./project/").toURI.toURL ) )
ConfigFactory.load(classLoader, "testenvironment")
}
or for loading a genereal application.conf from ./src/main/resources:
def getConfig: Config = {
val classLoader = new java.net.URLClassLoader( Array( new File("./src/main/resources/").toURI.toURL ) )
// no .conf basename given, so look for reference.conf and application.conf
// use specific classLoader
ConfigFactory.load(classLoader)
}
I'm trying to use Slick 2.1 with MS SQL Server in my Play 2.3 application. I'm stuck with trying to make Slick's code generator to work in Build.scala. This is because MS SQL Server JDBC driver is not on maven and I'm just manually putting the driver jar file in the /lib folder. At the moment I'm getting this error:
[error] (run-main-0) java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlserver.SQLServerDriver
This is how the part where code generator is looks like:
lazy val slickCodeGenTask = (sourceManaged, dependencyClasspath in Compile, runner in Compile, streams) map { (dir, cp, r, s) =>
val outputDir = (dir / "slick").getPath
val url = "jdbc:sqlserver://localhost:1433;databaseName=mydb"
val jdbcDriver = "com.microsoft.jdbc.sqlserver.SQLServerDriver"
val slickDriver = "com.typesafe.slick.driver.ms.SQLServerDriver"
val pkg = "db"
toError(r.run("scala.slick.codegen.SourceCodeGenerator", cp.files, Array(slickDriver, jdbcDriver, url, outputDir, pkg, user, pswd), s.log))
val fname = outputDir + "/db/Tables.scala"
Seq(file(fname))
}
How do I make MS SQL Server JDBC driver play along with Slick code generator?
SBT in Play 2.3 doesn't seem to automatically add contents of lib folder to classpath, so I've stumbled on a solution after running idea command for my Intellij IDEA which among other things adds jars from lib to classpath.
Also, after lots of digging around the final solution to this particular problem was to use open source jtds driver for slick code generator and ms jdbc driver for the rest of the application. This is what generator code ended up looking like:
lazy val slickCodeGenTask = (sourceManaged, dependencyClasspath in Compile, runner in Compile, streams) map { (dir, cp, r, s) =>
val outputDir = "app"
val url = "jdbc:jtds:sqlserver://localhost:1433;databaseName=mydb"
val jdbcDriver = "net.sourceforge.jtds.jdbc.Driver"
val slickDriver = "com.typesafe.slick.driver.ms.SQLServerDriver"
val pkg = "db"
toError(r.run("scala.slick.codegen.SourceCodeGenerator", cp.files, Array(slickDriver, jdbcDriver, url, outputDir, pkg, user, pswd), s.log))
val fname = "Tables.scala"
Seq(file(fname))
}
On a tangential note, for sbt 0.13.x, it is recommended to change scala.slick.codegen.SourceCodeGenerator -> slick.codegen.SourceCodeGenerator
I want to add data to redis:
object Obj1 {
val redis = new RedisClient
def insert(): Unit = {
val data = List(
(111, 222, 333),
(444, 555, 666)
)
for ((x, i) <- data.zipWithIndex) {
redis lpush (f"key1$i", x._1)
redis lpush (f"key2$i", x._2)
}
}
}
It complains at runtime:
[error] (run-main) java.lang.Exception: ERR Operation against a key holding the wrong kind of value
java.lang.Exception: ERR Operation against a key holding the wrong kind of value
And it does it due to $i for some reason. Even "key123" causes the error.
Client https://github.com/debasishg/scala-redis
Your code works absolutely fine using Scala 2.10.3 with Scala-Redis 2.11 even with String interpolation. Tried on IntelliJ with SBT 0.13.
Try updating to the latest version of the client (if you are using an older version). If you are using SBT :
libraryDependencies += "net.debasishg" % "redisclient_2.10" % "2.11"