0

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 ?

MaatDeamon
  • 9,532
  • 9
  • 60
  • 127

2 Answers2

1

The upgrade guide in the Slick documentation explains the distinction between drivers and profiles:

Slick’s driver concept has been renamed to profile to end the confusion over Slick drivers vs JDBC drivers....

As for the reason that Alpakka's SlickSession doesn't accept your configuration, take a look at the source code:

object SlickSession {
  private final class SlickSessionImpl(val slick: DatabaseConfig[JdbcProfile]) extends SlickSession {
    val db: JdbcBackend#Database = slick.db
    val profile: JdbcProfile = slick.profile // <-- expects a profile
  }
  ...
}

SlickSession specifically looks for a profile in the configuration, which is why defining a driver won't work.

To define a profile for Oracle, use OracleProfile.

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
  • Honestly, the documentation around that is not great.I did my digging yesterday following some of the step you recommend here and figured out how to make it work. But this conf things is quite complex to grasp as in not straightforward. I mean one has to study the code to understand it. Documentation use DB, example use DB or Profile albeit an old approch. Took me some time to figure out what i need to do. It works but i am not even 100% sure that i am doing the right thing – MaatDeamon Aug 24 '18 at 14:45
1

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            = "...."
  }
}
MaatDeamon
  • 9,532
  • 9
  • 60
  • 127