2

Is it possible to auto derive codecs for values classes in scala-mongo-driver?

Using existing macros produces StackOverflowError

package test

import org.bson.codecs.configuration.CodecRegistries.{fromCodecs, fromProviders, fromRegistries}
import org.mongodb.scala.MongoClient.DEFAULT_CODEC_REGISTRY
import org.mongodb.scala.bson.codecs.Macros._
import org.mongodb.scala.{MongoClient, MongoCollection}

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}

// Models
case class Name(value: String) extends AnyVal
case class Person(name: Name)

object TestValueClassCodecs extends App {

  private[this] val codecRegistry =
    fromRegistries(
      fromProviders(
        classOf[Person],
        classOf[Name],
      ),
      DEFAULT_CODEC_REGISTRY
    )

  protected val collection: MongoCollection[Person] =
    MongoClient(s"mongodb://localhost:27017")
      .getDatabase("TestDB")
      .withCodecRegistry(codecRegistry)
      .getCollection[Person]("test_repo_values_classes")

  val res = Await.result(
    collection.insertOne(Person(Name("Jesus"))).toFuture(),
    10.seconds
  )

}

Output:

Caused by: java.lang.StackOverflowError
    at scala.collection.LinearSeqOptimized.length(LinearSeqOptimized.scala:54)
    at scala.collection.LinearSeqOptimized.length$(LinearSeqOptimized.scala:51)
    at scala.collection.immutable.List.length(List.scala:91)
    at scala.collection.SeqLike.size(SeqLike.scala:108)
    at scala.collection.SeqLike.size$(SeqLike.scala:108)
    at scala.collection.AbstractSeq.size(Seq.scala:45)
    at scala.collection.convert.Wrappers$IterableWrapperTrait.size(Wrappers.scala:25)
    at scala.collection.convert.Wrappers$IterableWrapperTrait.size$(Wrappers.scala:25)
    at scala.collection.convert.Wrappers$SeqWrapper.size(Wrappers.scala:66)
    at java.util.AbstractCollection.toArray(AbstractCollection.java:136)
    at java.util.ArrayList.<init>(ArrayList.java:178)
    at org.bson.internal.ProvidersCodecRegistry.<init>(ProvidersCodecRegistry.java:34)
    at org.bson.codecs.configuration.CodecRegistries.fromRegistries(CodecRegistries.java:126)
    at org.mongodb.scala.bson.codecs.macrocodecs.MacroCodec.$init$(MacroCodec.scala:86)
    at test.TestValueClassCodecs$$anon$1$$anon$3$NameMacroCodec$1.<init>(TestValueClassCodecs.scala:51)
    at test.TestValueClassCodecs$$anon$1$$anon$3$NameMacroCodec$2$.apply(TestValueClassCodecs.scala:51)
    at test.TestValueClassCodecs$$anon$1$$anon$3.get(TestValueClassCodecs.scala:51)
    at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:45)
    at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:45)
    at org.bson.internal.ChildCodecRegistry.get(ChildCodecRegistry.java:58)
    at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:45)
    at org.bson.internal.ChildCodecRegistry.get(ChildCodecRegistry.java:58)
    at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:45)
    at org.bson.internal.ChildCodecRegistry.get(ChildCodecRegistry.java:58)
    at org.bson.internal.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:45)

I am using version: org.mongodb.scala:mongo-scala-bson_2.12:4.1.1

If the Name class is not a value one everything works just fine.

Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96

0 Answers0