So I have a bunch of compiled case classes in a .jar. I want to load and iterate over all of them and for each case class generate an Avro schema using scalavro. The scalavro AvroType expects a TypeTag, so essentially my question is how to appropriately reflect TypeTags from external case classes in a jar.
import java.net.URL
import com.gensler.scalavro.types.AvroType
import org.clapper.classutil.ClassFinder
import java.io.File
import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{ universe => ru }
object scalaAvroGen extends App {
val jarLocation = "someCaseClasses.jar"
val classpath = List(jarLocation).map(new File(_))
val classLoader = new URLClassLoader(Array[URL](new File(jarLocation).toURI.toURL), this.getClass().getClassLoader())
val finder = ClassFinder(classpath)
val classes = finder.getClasses.filterNot(_.isFinal)
classes.foreach {
loadedClass => {
val typeTag = typeToTypeTag(getType(classLoader.loadClass(loadedClass.name)))
val avroSchema = AvroType.apply(typeTag).schema()
println(avroSchema)
}
}
def getType[T](clazz: Class[T])(implicit runtimeMirror: ru.Mirror) =
runtimeMirror.classSymbol(clazz).toType
def typeToTypeTag[T](tpe: Type): TypeTag[T] = TypeTag.synchronized {
val mirror = scala.reflect.runtime.currentMirror
TypeTag(mirror, new reflect.api.TypeCreator {
def apply[U <: reflect.api.Universe with Singleton](m: reflect.api.Mirror[U]) = {
assert(m eq mirror, s"TypeTag[$tpe] defined in $mirror cannot be migrated to $m.")
tpe.asInstanceOf[U#Type]
}
})
}
}
Example case class in the compiled .jar:
case class SimpleScalaAvroObject(version: Int, name: String)
Currently when I attempt to run this code I get the following error:
Error:(20, 39) type mismatch; found : reflect.runtime.universe.TypeTag[Nothing] required: reflect.runtime.universe.TypeTag[T] Note: Nothing <: T, but trait TypeTag is invariant in type T. You may wish to investigate a wildcard type such as `_ <: T`. (SLS 3.2.10)
val avroSchema = AvroType.apply(typeTag).schema()
^
Now I'm sure this is not my only issue, I've spent the last two days throwing everything at this. At one point I was getting class not found exceptions on SimpleScalaAvroObject so I'm probably not even reflecting correctly.
I'll eventually annotations to the case classes I actually care about but for now this is really just a PoC.
Please note up until a few months ago I was a C# dev so sorry for this mangled mess of Scala.
Thanks!
Aucun commentaire:
Enregistrer un commentaire