尝试构建一个通用的 Scala 2.11 Jackson 序列化程序,该序列化程序使用 Jackson Smile 2.6.6 和 jackson-module-scala。无论出于何种原因,Java都找不到一个公共的无参数构造函数。尽管下面的类可以编译,但我在运行时从 Kafka 客户端收到以下错误:
Caused by: org.apache.kafka.common.KafkaException: Could not instantiate class ai.bernie.api.util.serialization.kafka.JacksonGenericSerializer Does it have a public no-argument constructor?
at org.apache.kafka.common.utils.Utils.newInstance(Utils.java:318) ~[kafka-clients-0.10.0.0.jar:na]
at org.apache.kafka.common.config.AbstractConfig.getConfiguredInstance(AbstractConfig.java:201) ~[kafka-clients-0.10.0.0.jar:na]
at org.apache.kafka.clients.consumer.KafkaConsumer.<init>(KafkaConsumer.java:671) ~[kafka-clients-0.10.0.0.jar:na]
... 27 common frames omitted
Caused by: java.lang.InstantiationException: ai.bernie.api.util.serialization.kafka.JacksonGenericSerializer
at java.lang.Class.newInstance(Class.java:427) ~[na:1.8.0_51]
at org.apache.kafka.common.utils.Utils.newInstance(Utils.java:314) ~[kafka-clients-0.10.0.0.jar:na]
... 29 common frames omitted
Caused by: java.lang.NoSuchMethodException: ai.bernie.api.util.serialization.kafka.JacksonGenericSerializer.<init>()
at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_51]
at java.lang.Class.newInstance(Class.java:412) ~[na:1.8.0_51]
... 30 common frames omitted
这是类,我该如何解决它?我已经尝试了使用 final def
并将私有 var 移动到类中的各种组合,尽管我可能做错了,但也尝试使用无参数apply
方法创建一个伴随对象。
class JacksonGenericSerializer[T: Manifest] private (
private var mapper: ObjectMapper with ScalaObjectMapper = null
) extends Closeable with AutoCloseable with Serializer[T] with Deserializer[T] {
final def this() = this(new ObjectMapper(new SmileFactory) with ScalaObjectMapper)
override def configure(map: java.util.Map[String, _], b: Boolean) {
if (mapper == null) {
mapper = new ObjectMapper(new SmileFactory) with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
}
}
override def serialize(s: String, record: T): Array[Byte] = {
try {
mapper.writeValueAsBytes(record)
}
catch {
case e: JsonProcessingException => {
throw new IllegalArgumentException(e)
}
}
}
override def deserialize(s: String, bytes: Array[Byte]): T = {
try {
mapper.readValue[T](bytes)
}
catch {
case e: IOException => {
throw new IllegalArgumentException(e)
}
}
}
override def close {
mapper = null
}
}
编辑
我还应该提到我正在使用 Google Guice,尽管我怀疑它会影响这一点,因为序列化类本身没有被注入,只有使用它的 Kafka 消费者/生产者父类。
因为JacksonGenericSerializer
类型参数具有上下文绑定(即 [T: Manifest]
)辅助的"无参数"构造函数实际上接受一个参数:Manifest[T]
您可以使用javap确认这一点:
$ javap JacksonGenericSerializer.class
Compiled from "JacksonGenericSerializer.scala"
public class JacksonGenericSerializer<T> implements java.io.Closeable, java.lang.AutoCloseable, org.apache.kafka.common.serialization.Serializer<T>, org.apache.kafka.common.serialization.Deserializer<T> {
public void configure(java.util.Map<java.lang.String, ?>, boolean);
public byte[] serialize(java.lang.String, T);
public T deserialize(java.lang.String, byte[]);
public void close();
public JacksonGenericSerializer(scala.reflect.Manifest<T>);
}
这个问题涉及一个类似的问题:如何仅使用零参数构造函数通过 Java 反射创建上下文绑定的 Scala 类的新实例?