Insertion into scylladb table using phantom library in scala not working

66 Views Asked by At

I'm new to ScyllaDB, and trying to perform CRUD operations using phantom library in scala. First I've made 3-node cluster and its running fine.

Datacenter: DC1
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address     Load       Tokens       Owns    Host ID                               Rack
UN  172.19.0.3  1.1 MB     256          ?       1db1e9a6-8e99-4d7c-b086-f169b4619e16  Rack1
UN  172.19.0.2  1.14 MB    256          ?       f6e6ef6b-7ec5-4a59-aaa0-975eac039794  Rack1
UN  172.19.0.4  1.14 MB    256          ?       9aac568d-bafb-4d9b-b2aa-8a0bfd64ef4f  Rack1

Then I made keyspace with name "user_keyspace", and create table "users" inside it. Now I'm trying to insert data using phantom library in scala. User Model:

case class User(userID: Int, firstName: String, lastName: String)

Users class, which I extend with Table[]:

import com.outworkers.phantom.dsl._

abstract class Users extends Table[Users, User] {
  override def tableName: String = "users"

  object UserID extends IntColumn with PartitionKey {
    override def name: String = "user_id"
  }

  object FirstName extends IntColumn {
    override def name: String = "first_name"
  }

  object LastName extends IntColumn {
    override def name: String = "last_name"
  }
}

UsersDatabase Class:

import com.outworkers.phantom.dsl._

class UsersDatabase(override val connector: CassandraConnection) extends Database[UsersDatabase](connector) {
  object users extends Users with Connector
}

UsersOperations Class:

import com.outworkers.phantom.dsl._
import scala.concurrent.Future

class UserOperations(db: UsersDatabase) {

  import db.{session, space}

  def insertUser(user: User): Future[ResultSet] =
    db.users.store(user).future()
}

Main Class:

import com.outworkers.phantom.dsl._
import scala.util._

object App extends App {
  private val connection: CassandraConnection =
    ContactPoints(List("172.19.0.3", "172.19.0.2", "172.19.0.4"))
      .keySpace("user_keyspace")

  private val db = new UsersDatabase(connection)
  private val userOperations = new UserOperations(db)

  userOperations.insertUser(User(2,"Ali","Hassan")).onComplete{
    case Success(value) =>
      println("Users: " + value)
      db.shutdown()

    case Failure(exception) =>
      println("Exception: " + exception)
      db.shutdown()
  }
}

build.sbt file:

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.1"

lazy val root = (project in file("."))
  .settings(
    name := "my_scylladb_app"
  )

libraryDependencies += "com.outworkers" %% "phantom-dsl" % "2.59.0"
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.13.10"
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.4.6"

When I run this code, it gives error:

[error] /home/zaryab/IdeaProjects/my_scylladb_app/src/main/scala/UserOperations.scala:14:19: could not find implicit value for parameter sg: com.outworkers.phantom.macros.SingleGeneric.Aux[User,Repr,HL,Out] (The type you're trying to store User should match either Repr or HL)
[error]     db.users.store(user).future()
[error]                   ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed

Please help me to remove this error.

1

There are 1 best solutions below

2
Dmytro Mitin On

If you define the class as case class User(userID: Int, firstName: String, lastName: String) then

object FirstName extends IntColumn {
  override def name: String = "first_name"
}

object LastName extends IntColumn {
  override def name: String = "last_name"
}

must be

object FirstName extends StringColumn {
  override def name: String = "first_name"
}

object LastName extends StringColumn {
  override def name: String = "last_name"
}

This was the error.


By the way, it's better to use the same version of scala-reflect, scala-compiler as scalaVersion. So

ThisBuild / scalaVersion := "2.13.1"
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.13.10"

should be better either

ThisBuild / scalaVersion := "2.13.10"
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.13.10"

or

ThisBuild / scalaVersion := "2.13.1"
libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.13.1"

It's better to write

libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value

or even

libraryDependencies += scalaOrganization.value % "scala-reflect" % scalaVersion.value

to avoid such confusion. Actually, you do not seem to use scala-reflect at all.