NoClassDefFoundError: slick/profile/RelationalProfile$SimpleQL - scala

I am able to connect by using the play's default.db:
db.default.driver="com.microsoft.sqlserver.jdbc.SQLServerDriver"
db.default.url="jdbc:sqlserver://my_host.database.windows.net:1433;database=my_db;"
db.default.username="username"
db.default.password="password"
But when I try with Slick:
slick.dbs.default {
driver = "com.typesafe.slick.driver.ms.SQLServerDriver$"
db {
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
url = "jdbc:sqlserver://my_host.database.windows.net:1433;database=my_db;"
user = "username"
password = "password"
}
}
I get:
ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, java.lang.NoClassDefFoundError: slick/profile/RelationalProfile$SimpleQL
Which points to my DAO:
import play.api.db.slick.DatabaseConfigProvider
class UsersDAO #Inject() (override protected val dbConfigProvider: DatabaseConfigProvider) extends Tables(dbConfigProvider) { // <---- This line
...
}
Here is my Tables.scala file:
import models.User
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.driver.JdbcProfile
class Tables #Inject() (protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
import driver.api._
protected val users = TableQuery[Users]
protected class Users(tag: Tag) extends Table[User](tag, "users") {
def id = column[String]("id", O.PrimaryKey)
def firstName = column[String]("first_name")
def lastName = column[String]("last_name")
def * = (id, firstName, lastName) <> ((User.apply _).tupled, User.unapply _)
}
}
Here are the relevant lines in my build.sbt file:
libraryDependencies ++= Seq(
...
"com.typesafe.play" % "play-slick_2.11" % "2.0.2",
"com.typesafe.slick" %% "slick-extensions" % "3.0.0",
...
)
resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/maven-releases/"
I am unable to find out anything about SimpleQL and why it is missing at run time.

play-slick 2.0.2 uses slick 3.1.0 so you have to match this version in slick-extensions:
libraryDependencies ++= Seq(
...
"com.typesafe.play" % "play-slick_2.11" % "2.0.2",
"com.typesafe.slick" %% "slick-extensions" % "3.1.0",
...
)

Related

Slick with PostgreSQL Scala SBT Intellij IDEA

I am trying to create a project with Slick in Intellij IDEA with PostgreSQL driver. But I have managed to find only this tutorial
I followed it, but I have got an error:
Exception in thread "main" java.lang.ExceptionInInitializerError
at Main.main(Main.scala)
Caused by: com.typesafe.config.ConfigException$Missing: No configuration setting found for key 'url'
Here is my code for the main class:
import scala.slick.driver.PostgresDriver.simple._
object Main {
case class Song(
id: Int,
name: String,
singer: String)
class SongsTable(tag: Tag) extends Table[Song](tag, "songs") {
def id = column[Int]("id")
def name = column[String]("name")
def singer = column[String]("singer")
def * = (id, name, singer) <> (Song.tupled, Song.unapply)
}
lazy val songsTable = TableQuery[SongsTable]
val db = Database.forConfig("scalaxdb")
def main(args: Array[String]): Unit = {
val connectionUrl = "jdbc:postgresql://localhost/songs?user=postgres&password=postgresp"
Database.forURL(connectionUrl, driver = "org.postgresql.Driver") withSession {
implicit session =>
val songs = TableQuery[SongsTable]
songs.list foreach { row =>
println("song with id " + row.id + " has name " + row.name + " and a singer is " + row.singer)
}
}
}
}
These is application.conf file:
scalaxdb = {
dataSourceClass = "slick.jdbc.DatabaseUrlDataSource"
properties = {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://localhost/dbname?user=user&password=password"
}
}
And this is build.sbt:
libraryDependencies ++= Seq(
"org.postgresql" % "postgresql" % "9.3-1100-jdbc4",
"com.typesafe.slick" %% "slick" % "2.1.0",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
I can not figure out what I am doing wrong. I would be very grateful for any advice on fixing this.
Don't you mind to use a little more up-to-date version of Slick?
import slick.jdbc.PostgresProfile.api._
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object Main {
case class Song(
id: Int,
name: String,
singer: String)
class SongsTable(tag: Tag) extends Table[Song](tag, "songs") {
def id = column[Int]("id")
def name = column[String]("name")
def singer = column[String]("singer")
def * = (id, name, singer) <> (Song.tupled, Song.unapply)
}
val db = Database.forConfig("scalaxdb")
val songs = TableQuery[SongsTable]
def main(args: Array[String]): Unit = {
Await.result({
db.run(songs.result).map(_.foreach(row =>
println("song with id " + row.id + " has name " + row.name + " and a singer is " + row.singer)))
}, 1 minute)
}
}
build.sbt
scalaVersion := "2.12.4"
libraryDependencies += "com.typesafe.slick" %% "slick" % "3.2.1"
libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.25"
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.2.1"
libraryDependencies += "org.postgresql" % "postgresql" % "42.1.4"

Scala Slick compose column type mappers

I'm using slick-pg which adds support(with implicits) for the List and DateTime types in slick.
Unfortunately I cannot use List[DateTime] - slick does not understand composition of those types, but I've checked that both work correctly on their own(for example List[Int] and DateTime).
Is there a way to easily compose those two implicits?
1. Try to add
implicit def dateTimeList =
MappedColumnType.base[List[DateTime], List[Timestamp]](
_.map(dt => new Timestamp(dt.getMillis)),
_.map(ts => new DateTime(ts.getTime))
)
Just in case, the whole code that compiles:
import java.sql.Timestamp
import org.joda.time.DateTime
import slick.jdbc.PostgresProfile.api._
import slick.lifted.ProvenShape
import slick.basic.Capability
import slick.jdbc.JdbcCapabilities
import com.github.tototoshi.slick.PostgresJodaSupport._
import com.github.tminglei.slickpg._
object App {
trait MyPostgresProfile extends ExPostgresProfile
with PgArraySupport
with PgDate2Support
with PgRangeSupport
with PgHStoreSupport
// with PgPlayJsonSupport
with PgSearchSupport
// with PgPostGISSupport
with PgNetSupport
with PgLTreeSupport {
def pgjson = "jsonb" // jsonb support is in postgres 9.4.0 onward; for 9.3.x use "json"
// Add back `capabilities.insertOrUpdate` to enable native `upsert` support; for postgres 9.5+
override protected def computeCapabilities: Set[Capability] =
super.computeCapabilities + /*JdbcProfile.capabilities.insertOrUpdate*/ JdbcCapabilities.insertOrUpdate
override val api = MyAPI
object MyAPI extends API with ArrayImplicits
with DateTimeImplicits
// with JsonImplicits
with NetImplicits
with LTreeImplicits
with RangeImplicits
with HStoreImplicits
with SearchImplicits
with SearchAssistants {
implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList)
// implicit val playJsonArrayTypeMapper =
// new AdvancedArrayJdbcType[JsValue](pgjson,
// (s) => utils.SimpleArrayUtils.fromString[JsValue](Json.parse(_))(s).orNull,
// (v) => utils.SimpleArrayUtils.mkString[JsValue](_.toString())(v)
// ).to(_.toList)
}
}
object MyPostgresProfile extends MyPostgresProfile
import MyPostgresProfile.api._
// This can be used instead of slick-joda-mapper library
// implicit def dateTime =
// MappedColumnType.base[DateTime, Timestamp](
// dt => new Timestamp(dt.getMillis),
// ts => new DateTime(ts.getTime)
// )
implicit def dateTimeList =
MappedColumnType.base[List[DateTime], List[Timestamp]](
_.map(dt => new Timestamp(dt.getMillis)),
_.map(ts => new DateTime(ts.getTime))
)
case class Record(id: Int, name: String, friends: List[Int], registered: DateTime, visits: List[DateTime])
class RecordTable(tag: Tag) extends Table[Record](tag, Some("public"), "records") {
def id: Rep[Int] = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name: Rep[String] = column[String]("name")
def friends: Rep[List[Int]] = column[List[Int]]("friends")
def registered: Rep[DateTime] = column[DateTime]("registered")
def visits: Rep[List[DateTime]] = column[List[DateTime]]("visits")
def * : ProvenShape[Record] = (id, name, friends, registered, visits) <> (Record.tupled, Record.unapply)
}
val records: TableQuery[RecordTable] = TableQuery[RecordTable]
}
build.sbt
name := "slickdemo"
version := "0.1"
scalaVersion := "2.12.3"
libraryDependencies += "com.typesafe.slick" %% "slick" % "3.2.1"
libraryDependencies += "org.slf4j" % "slf4j-nop" % "1.7.25"
libraryDependencies += "com.typesafe.slick" %% "slick-hikaricp" % "3.2.1"
libraryDependencies += "org.postgresql" % "postgresql" % "42.1.4"
libraryDependencies += "com.github.tminglei" %% "slick-pg" % "0.15.3"
libraryDependencies += "joda-time" % "joda-time" % "2.9.9"
libraryDependencies += "org.joda" % "joda-convert" % "1.9.2"
libraryDependencies += "com.github.tototoshi" % "slick-joda-mapper_2.12" % "2.3.0"
Based on answer and documentation.
2. Alternatively you can add
implicit val dateTimeArrayTypeMapper =
new AdvancedArrayJdbcType[DateTime]("timestamp",
(s) => utils.SimpleArrayUtils.fromString[DateTime](DateTime.parse)(s).orNull,
(v) => utils.SimpleArrayUtils.mkString[DateTime](_.toString)(v)
).to(_.toList)
after strListTypeMapper and playJsonArrayTypeMapper.

Scala play withSession deprecated

I'm migrating from slick 2.1 to 3.0. As you know the function withSession has been deprecated.
How can I change code bellow:
def insert(vote: Vote) = DB.withSession { implicit session =>
insertWithSession(vote)
}
def insertWithSession(vote: Vote)(implicit s: Session) = {
Votes.insert(vote)
}
I've got compile error on Votes.insert and the error is:
could not find implicit value for parameter s: slick.driver.PostgresDriver.api.Session
At last, Is there any document other than official link helping me to migrate. I need more details.
Assuming that you are using play-slick for slick integration with play.
You can look at https://www.playframework.com/documentation/2.5.x/PlaySlick for more details.
Add the slick and jdbc dependencies in build.sbt
libraryDependencies ++= Seq(
"com.typesafe.play" %% "play-slick" % "2.0.0",
"com.typesafe.play" %% "play-slick-evolutions" % "2.0.0"
"org.postgresql" % "postgresql" % "9.4-1206-jdbc4"
)
Add the postgres config in your application.conf
slick.dbs.default.driver="slick.driver.PostgresDriver$"
slick.dbs.default.db.driver="org.postgresql.Driver"
slick.dbs.default.db.url="jdbc:postgresql://localhost/yourdb?user=postgres&password=postgres"
Now define your models like the following,
package yourproject.models
import play.api.db.slick.DatabaseConfigProvider
import slick.driver.JdbcProfile
case class Vote(subject: String, number: Int)
class VoteTable(tag: Tag) extends Table[Vote](tag, "votes") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def subject = column[String]("subject")
def number = column[Int]("number")
def * = (id.?, subject, number) <> (Vote.tupled, Vote.unapply)
}
class VoteRepo #Inject()()(protected val dbConfigProvider: DatabaseConfigProvider) {
val dbConfig = dbConfigProvider.get[JdbcProfile]
val db = dbConfig.db
import dbConfig.driver.api._
val Votes = TableQuery[VoteTable]
def insert(vote: Vote): DBIO[Long] = {
Votes returning Votes.map(_.id) += vote
}
}
Now your controller will look something like,
import javax.inject.Inject
import yourproject.models.{VoteRepo}
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc.{Action, Controller}
class Application #Inject()(voteRepo: VoteRepo) extends Controller {
def createProject(subject: String, number: Int) = Action.async {
implicit rs => {
voteRepo.create(Vote(subject, number))
.map(id => Ok(s"project $id created") )
}
}
}

Anorm and JDBC dependencies not found in Play Framework?

I am running my application with Play Framework(version: 2.2.3), it's giving compilation errors like: not found value anorm and not found value jdbc, I am not sure whether it has connected with my database set up or not ? I have checked the question, but still no use. Please help me that where I am doing wrong ?.
I have done the following:
build.scala:
import sbt._
object AppBuild extends Build {
val appDependencies = Seq(
jdbc,
"com.google.inject" % "guice" % "3.0",
"javax.inject" % "javax.inject" % "1",
"org.postgresql" % "postgresql" % "9.4-1200-jdbc41",
"com.typesafe.play" % "play-iteratees_2.10" % "2.2.3"
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// we can add our own project settings
)
}
app.scala:
package models
import anorm._
import anorm.SqlParser._
import play.api.db.DB
import play.api.db._
import play.api.Play.current
case class Test(id: Pk[Long], content: String)
object Test {
def create(test: Test): Unit = {
DB.withConnection { implicit connection =>
SQL("insert into test(content) values ({content})").on(
'content -> test.content
).executeUpdate()
}
}
}
plugins.sbt:
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.2.3")
app.conf:
db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://localhost:5432/abcdatabase"

Cannot resolve symbols (foreach, list,...) using Slick-play

I'm beginning with slick and scala, using playframewok
I have configured my project to work with play 2.2.0 using play-slick 0.5.0.8
My problem is that I can't execute some essential methods like "list , foreach, for{}yield ..."
I have tried a stand alone example and it works with the same slick version 1.0.1??
Here is the project build file
import sbt._
import Keys._
import play.Project._
object Build extends Build {
val appName = "homePage"
val appVersion = "1.0-ALPHA"
val appDependencies = Seq(
// Add your project dependencies here,
jdbc,
"com.typesafe.play" %% "play-slick" % "0.5.0.8" ,
"postgresql" % "postgresql" % "9.1-901-1.jdbc4",
"com.typesafe.slick" %% "slick" % "1.0.1"
)
val main = play.Project(appName, appVersion, appDependencies).settings(
// add web app as
playAssetsDirectories <+= baseDirectory / "webapp"
)
}
My model ::
package model
import java.util.Calendar
import scala.slick.driver.PostgresDriver.simple._
case class Article(id: Long,
content: String,
date: java.sql.Date)
object Articles extends Table[Article]("articles") {
def id = column[Long]("art_id", O.PrimaryKey , O.AutoInc) // This is the primary key column
def content = column[String]("art_content", O.NotNull)
def date = column[java.sql.Date]("art_date", O.NotNull, O.Default(new java.sql.Date(Calendar.getInstance().getTime.getTime)))
def * = id ~ content ~ date <> (Article.apply _, Article.unapply _)
}
here is the code that doesn't work
query foreach { case (content, date) =>
println(" " + name + ": " + count)
}
//:: cannot resolve the symbol foreach
same thing for [for , yield]
(for(p <- Props if p.key === k) yield p.value).firstOption
I don't know what is the problem, so every help will be appreciated.
import scala.slick.driver.PostgresDriver.simple._ in the file, where you try to call foreach.
I should have used import scala.slick.driver.PostgresDriver.simple._ in my service source file:
import model._
import scala.slick.lifted.Query
import scala.slick.driver.PostgresDriver.simple._
object ArticlesService {
val PAGE_SIZE :Int = 100
def getPaginatedResult(pageNumber : Int) (implicit s: scala.slick.session.Session)= {
val query= Query(Articles)
query.drop(pageNumber * PAGE_SIZE).take(PAGE_SIZE).list()
}
}