2016-01-22 5 views
1

Итак, у меня есть куча скомпилированных классов case в .jar. Я хочу загрузить и перебрать все из них, и для каждого класса case создайте схему Avro, используя scalavro. Скараво AvroType ожидает TypeTag, поэтому по существу мой вопрос заключается в том, как правильно отражать TypeTags из внешних классов case в банке.Scala Reflection & TypeTag Mismatch

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] 
     } 
    }) 
    } 
} 

Пример случай класс скомпилированного .jar:

case class SimpleScalaAvroObject(version: Int, name: String) 

В настоящее время, когда я пытаюсь запустить этот код, я получаю следующее сообщение об ошибке:

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()  
          ^

Теперь я уверен, что это это не моя единственная проблема, я провел последние два дня, бросая все на это. В какой-то момент я получал класс не найденных исключений в SimpleScalaAvroObject, поэтому я, вероятно, даже не отражаю правильно.

В конце концов я расскажу о классах case, которые действительно интересуются, но на данный момент это действительно просто PoC.

Обращаем ваше внимание, что несколько месяцев назад я был C# разработчиком, так жаль этот испорченный беспорядок Скалы.

Спасибо!

+0

не очень хорошо знакомы с тем, что вы пытаетесь сделать, но я могу вам сказать, что параметр типа 'typeToTypeTag' выводится как' Nothing', потому что компилятор Безразлично «Не знаю, что использовать на основе« Тип ». То есть параметр типа должен быть заполнен во время компиляции, _before_ компилятор может знать, что это (в этом случае). –

ответ

1

Вы можете использовать другой проект avro4s (отказ от ответственности: я написал это), чтобы генерировать схемы во время компиляции, а не во время выполнения, и любые проблемы с тегами типа, которые у вас есть, должны исчезнуть (поскольку компилятор имеет доступ к дополнительной информации о том, что присутствует во время выполнения).

Очень прост в использовании,

case class SimpleScalaAvroObject(version: Int, name: String) 
// this schema is of type org.apache.avro.Schema 
val schema = AvroSchema[SimpleScalaAvroObject] 
Смежные вопросы