Search code examples
scalaslickakka-streamalpakka

How does slick profile work with respect to slick DB


I am having trouble to understand how to use slick profile.

My problem:

I am trying to use Slick with Akka-stream via the Alpakka JDBC plugin. The example given online is as follows:

#Load using SlickSession.forConfig("slick-h2")
slick-h2 {
  profile = "slick.jdbc.H2Profile$"
  db {
    connectionPool = disabled
    dataSourceClass = "slick.jdbc.DriverDataSource"
    properties = {
      driver = "org.h2.Driver"
      url = "jdbc:h2:/tmp/alpakka-slick-h2-test"
    }
  }
}

import scala.concurrent.Future

import akka.Done
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer

import akka.stream.scaladsl._
import akka.stream.alpakka.slick.scaladsl._

import slick.jdbc.GetResult

object SlickSourceWithPlainSQLQueryExample extends App {
  implicit val system = ActorSystem()
  implicit val mat = ActorMaterializer()
  implicit val ec = system.dispatcher

  implicit val session = SlickSession.forConfig("slick-h2")

  // The example domain
  case class User(id: Int, name: String)

  // We need this to automatically transform result rows
  // into instances of the User class.
  // Please import slick.jdbc.GetResult
  // See also: "http://slick.lightbend.com/doc/3.2.1/sql.html#result-sets"
  implicit val getUserResult = GetResult(r => User(r.nextInt, r.nextString))

  // This import enables the use of the Slick sql"...",
  // sqlu"...", and sqlt"..." String interpolators.
  // See also: "http://slick.lightbend.com/doc/3.2.1/sql.html#string-interpolation"
  import session.profile.api._

  // Stream the results of a query
  val done: Future[Done] =
    Slick
      .source(sql"SELECT ID, NAME FROM ALPAKKA_SLICK_SCALADSL_TEST_USERS".as[User])
      .log("user")
      .runWith(Sink.ignore)

  done.onComplete {
    case _ =>
      session.close()
      system.terminate()
  }
}

The issue is that it works with

implicit val session = SlickSession.forConfig("slick-h2")

I try to use slick session as follows:

object Main extends App {

  implicit val system = ActorSystem()
  implicit val mat = ActorMaterializer()
  implicit val ec = system.dispatcher

  implicit val session = SlickSession.forConfig("pp")
}

Where my pp config is as such:

pp = {

  url                 = "jdbc:oracle:thin:@52.4.90.244:1521:pp"
  driver              = oracle.jdbc.OracleDriver
  keepAliveConnection = true
  connectionPool      = disabled


  user                = "xxxxx"
  password            = "xxxxx"

}

This code breaks at runtime.

Exception in thread "main" slick.SlickException: Configured profile oracle.jdbc.OracleDriver does not conform to requested profile slick.jdbc.JdbcProfile
    at slick.basic.DatabaseConfig$.forConfig(DatabaseConfig.scala:99)
    at akka.stream.alpakka.slick.javadsl.SlickSession$.forConfig(package.scala:47)
    at akka.stream.alpakka.slick.javadsl.SlickSession$.forConfig(package.scala:44)

However in another code, where I do not use Akka-Stream and therefore do not use slickSession as such

object Main extends App {
  val db = Database.forConfig("pp")
.....}

the code works perfectly.

I concluded that this has to do with Database.forconfig("pp") and SlickSession.forConfig("slick-h2") that require 2 different things.

There is an explanation about profile in Slick website but that is not very easy to understand and provides little instruction. It does not list the available profile and their syntax.

Hence my question is, what's the difference between the two forConfig. How the profile works, where are they needed. Why the two configuration files for the database are not dealt with the same way.

Finally and formost, what is the profile for oracle. In slick 3.2.3 Slick is now free. I could not find the profile for it as in profile = "slick.jdbc.H2Profile$"

Can someone help clarify the configuration file difference, what is expected, what the profile does, and what is the profile for Oracle ?


Solution

  • As a follow up of @Jeffrey Chung answer. Here is the solution.

      implicit val session = SlickSession.forConfig("pp")
      import session.profile.api._
    

    and the configuration file should be as such:

    pp {
      profile = "slick.jdbc.OracleProfile$"
      db {
        url                 = "..."
        driver              = oracle.jdbc.OracleDriver
        keepAliveConnection = true
        connectionPool      = disabled
    
    
        user                = "...."
        password            = "...."
      }
    }