Search code examples
scalacassandraphantom-dsl

com.datastax.driver.core.exceptions.CodecNotFoundException: Codec not found for requested operation: [int <-> java.lang.Long]


Wrote this simple Phantom DSL code

case class FooRow(id: Long, dt: DateTime, et: Long, rid: Option[Long], d: Option[String] = None)
class FooTable extends CassandraTable[FooTable, FooRow] {
   object id extends LongColumn(this) with PartitionKey[Long]
   object dt extends DateTimeColumn(this) with PartitionKey[DateTime]
   object et extends LongColumn(this) with PartitionKey[Long]
   object rid extends OptionalLongColumn(this)
   object d extends OptionalStringColumn(this)
   override def fromRow(r: Row): FooRow = {
      FooRow(
         id(r),
         dt(r),
         et(r),
         rid(r),
         d(r)
      )
   }
}

When I try to insert a row. using this code

   def put(data: FooRow) : ResultSet = {
      val query = insert
         .value(_.id, data.id)
         .value(_.dt, data.dt)
         .value(_.rid, data.rid)
         .value(_.d, data.d)
         .value(_.et, data.et)
      query.consistencyLevel_=(ConsistencyLevel.QUORUM)
      Await.result(query.future(), awaitConfiguration.awaitTimeoutValue seconds)
   }

I get an error

[info] - should be able to retrieve all history records by respondent id *** FAILED ***
[info]   com.datastax.driver.core.exceptions.CodecNotFoundException: Codec not found for requested operation: [int <-> java.lang.Long]
[info]   at com.datastax.driver.core.CodecRegistry.notFound(CodecRegistry.java:679)
[info]   at com.datastax.driver.core.CodecRegistry.createCodec(CodecRegistry.java:526)
[info]   at com.datastax.driver.core.CodecRegistry.findCodec(CodecRegistry.java:506)
[info]   at com.datastax.driver.core.CodecRegistry.access$200(CodecRegistry.java:140)
[info]   at com.datastax.driver.core.CodecRegistry$TypeCodecCacheLoader.load(CodecRegistry.java:211)
[info]   at com.datastax.driver.core.CodecRegistry$TypeCodecCacheLoader.load(CodecRegistry.java:208)
[info]   at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3542)
[info]   at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2323)
[info]   at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2286)
[info]   at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2201)
[info]   at com.google.common.cache.LocalCache.get(LocalCache.java:3953)
[info]   at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3957)
[info]   at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4875)
[info]   at com.datastax.driver.core.CodecRegistry.lookupCodec(CodecRegistry.java:480)
[info]   at com.datastax.driver.core.CodecRegistry.codecFor(CodecRegistry.java:448)
[info]   at com.datastax.driver.core.CodecRegistry.codecFor(CodecRegistry.java:430)
[info]   at com.datastax.driver.core.AbstractGettableByIndexData.codecFor(AbstractGettableByIndexData.java:69)
[info]   at com.datastax.driver.core.AbstractGettableByIndexData.getLong(AbstractGettableByIndexData.java:152)
[info]   at com.datastax.driver.core.AbstractGettableData.getLong(AbstractGettableData.java:26)
[info]   at com.datastax.driver.core.AbstractGettableData.getLong(AbstractGettableData.java:95)
[info]   at com.websudos.phantom.builder.primitives.DefaultPrimitives$LongPrimitive$$anonfun$fromRow$7.apply(Primitive.scala:187)
[info]   at com.websudos.phantom.builder.primitives.DefaultPrimitives$LongPrimitive$$anonfun$fromRow$7.apply(Primitive.scala:187)
[info]   at com.websudos.phantom.builder.primitives.Primitive$$anonfun$nullCheck$1.apply(Primitive.scala:69)
[info]   at scala.util.Try$.apply(Try.scala:192)
[info]   at com.websudos.phantom.builder.primitives.Primitive.nullCheck(Primitive.scala:69)
[info]   at com.websudos.phantom.builder.primitives.DefaultPrimitives$LongPrimitive$.fromRow(Primitive.scala:187)
[info]   at com.websudos.phantom.column.PrimitiveColumn.optional(PrimitiveColumn.scala:52)
[info]   at com.websudos.phantom.column.Column.apply(Column.scala:42)
[info]   at com.abhi.FooTable.fromRow(FooService.scala:27)

The most confusing thing is that if you look at the code above, here is absolutely no Int anywhere.

as per the stacktrack the error is occurring at the line

et(r),

Solution

  • The only thing I can think of is that your Cassandra schema was not created with phantom and that in your DB the types of the columns differ from what phantom infers as valid.

    Both long and datetime columns in phantom get translated to bigint type in Cassandra, so you need to make sure that the schema in your DB matches that. It sounds to me like the one of your DB columns is int instead of long, so when the driver tries to parse records it blows up. This also means you are not used automated schema generation, which phantom can do out of the box. Read this for more details.

    Also, off topic, in more recent versions of phantom, both the fromRow and put method are macro derived, so you don't actually need to type them manually. So in phantom 2.7.3 I'd expect your code to look like this:

    import com.outworkers.phantom.dsl._
    
    case class FooRow(
      id: Long,
      dt: DateTime,
      et: Long,
      rid: Option[Long],
      d: Option[String] = None
    )
    
    abstract class FooTable extends CassandraTable[FooTable, FooRow] with RootConnector {
       object id extends LongColumn(this) with PartitionKey
       object dt extends DateTimeColumn(this) with PartitionKey
       object et extends LongColumn(this) with PartitionKey
       object rid extends OptionalLongColumn(this)
       object d extends OptionalStringColumn(this)
    
       def put(data: FooRow): ResultSet = {
    
         Await.result(
           store(data).consistencyLevel_=(ConsistencyLevel.QUORUM).future(),
           awaitConfiguration.awaitTimeoutValue seconds
         )
    
       }
    }